# Differences between PCRcalc and PCRaster Python¶

The majority of PCRcalc operations can be easily adjusted to PCRaster Python operations. Nevertheless, both modelling languages differ in a few areas. The following sections explain these differences and give sample applications. The differences in the operators (e.g +,-,...) are already listed in Operators.

## Setting geographical attributes of a model¶

To use the PCRaster operations you need to define the model area and resolution. While this is done in PCRcalc with the areamap section, PCRasterPython does not make use of sections. Apply the setclone operation instead:

setclone(map)


Sets the clone.

map
Filename of clone map.

Thus, the PCRcalc areamap section

areamap clone.map;


would become in a PCRaster Python script

setclone("clone.map")


Note

The first operation in a script must be the setclone operation.

Like in PCRcalc scripts it is not possible to mix maps with different extents, i.e. varying cellsize, number of rows or columns.

An input map is identified by a Python string containing the pathname to the disk dataset. The function readmap(pathname) reads a map.

• PCRaster operations with a function syntax can accept the pathname.

Dem = readmap("dem.map")
Slope1 = slope(Dem)
# or direct by pathname
Slope2 = slope("dem.map")

• PCRaster operations with an operator syntax do not accept a pathname.

# will yield "dem.mapdem.mapdem.map"
stringTimes3 = "dem.map" * 3
# will yield a Spatial object

• When using the PCRaster Python Framework one usually uses the class method readmap(self, filename) instead of the function readmap(pathname).

# ... denotes removed fragments
...
class RunoffModel(object):
...
def initial(self):
def dynamic(self):

dynModel = DynamicFramework(RunoffModel, 50)
dynModel.run()


## Writing output maps¶

To store maps use:

report(map, filename)


Writes a map to a file.

map
Map you want to write.
filename
Filename to use.

Note the differences between PCRcalc and Python.

# PCRcalc script code
binding
dem = dem.map;
initial

# Python code


The report operation only writes spatial data to disk. For writing non spatial data as timeseries in the DynamicFramework use the TimeoutTimeseries construct.

## Accessing cell values of a map¶

With PCRaster Python you can query cell values from a map:

cellvalue(map, row, col)


Returns a cell value from a map.

map
Map you want to query.
row
Row index of a cell in the map. Indices range from [1, number-of-rows].
col
Col index of a cell in the map. Indices range from [1, number-of-cols].

Returns a tuple with two elements: the first is the cell value, the second is a boolean value which shows whether the first element, is valid or not. If the second element is False, the cell contains a missing value.

cellvalue(map, index)


Returns a cell value from a map.

map
Map you want to query.
index
Linear index of a cell in the map. Indices range from [1, number-of-cells].

Returns a tuple with two elements: the first is the cell value, the second is a boolean value which shows whether the first element, is valid or not. If the second element is False, the cell contains a missing value.

## Global options¶

To set the global options of a script use

setglobaloption(name)


Sets the global option name. The option name must not contain the leading dashes as used on the command line of pcrcalc.

# Python example:
setglobaloption("unitcell")

# The pcrcalc equivalent:
pcrcalc --unitcell -f model.mod


## Writing time series¶

PCRaster Python does not provide a timeoutput operation like PCRcalc does. Instead, a separate class in the modelling framework is handling the PCRcalc timeoutput style timeseries.

Therefore, the PCRcalc

binding
outlet=samples.map;

dynamic
...
Q = ...
report runoff.tss = timeoutput(outlet , Q);


will become in your Python model script

from pcraster.framework import *

class RunoffModel(object):

def initial(self):
...
self.runoffTss=TimeoutputTimeseries("runoff", self, "samples.map",

def dynamic(self):
...
runoff = ...
self.runoffTss.sample(runoff)

myModel = RunoffModel("clone.map")
dynModelFw = DynamicFramework(myModel, endTimeStep=28, firstTimestep=1)
dynModelFw.run()


In the initial section of the model class you create a member variable self.runoffTss holding the TimeoutputTimeseries object. The output is written to the file runoff.tss (for the DynamicFramework in the current working directory, for the MonteCarloFramework it will store the file into the corresponding sample subdirectories). samples.map is either a boolean, nominal or ordinal map holding the sample locations. By default the header section is written to the timeseries file.

In the dynamic section self.runoffTss.sample(runOff) samples the values of the expression (here runoff) at the given locations for the current timestep. Note that for sequenced calls of sample() the values of the last call are sampled.

See also the example script runoff.py in the deterministic subdirectory of the workspace/framework directory.

## Converting to and from NumPy arrays¶

You can convert PCRaster maps to NumPy arrays and vice versa with the following conversion functions:

numpy2pcr(dataType, array, mv)


Converts entities from NumPy to PCRaster.

dataType
Either Boolean, Nominal, Ordinal, Scalar, Directional or Ldd.
array
Array you want to convert.
mv
Value that identifies a missing value in array.

Returns a map.

pcr2numpy(map, mv)


Converts entities from PCRaster to NumPy.

map
Map you want to convert.
mv
Value to use in result array cells as a missing value.

Returns an array.

The following example script demonstrates the usage of the conversion functions:

import numpy
from pcraster import *

setclone("clone.map")

a = numpy.array([[12,5,21],[9,7,3],[20,8,2],[5,6,-3]])

# conver a to a PCRaster Python map
# with the value 20 indicating a 'missing value' cell
n2p = numpy2pcr(Nominal, a, 20)
print "cellvalue:", cellvalue(n2p, 2, 3)[0]

# write it to a PCRaster map
report(n2p, "n2p.map")
# read the PCRaster map back
# print it as a numpy array
# missing value is replaced by 9999
print pcr2numpy(p2n, 9999)


Execution of the script will result in the following output:

cellvalue: 3
[[  12    5   21]
[   9    7    3]
[9999    8    2]
[   5    6   -3]]


## PCRcalc operations returning multiple results¶

In PCRcalc some operations can be combined and return two result values like:

# PCRcalc
state,flux = accufractionstate,accufractionflux(ldd.map,material.map,0.5);


This syntax is not supported in PCRaster Python scripts. Use two separate operations instead, although this will double the execution time:

# Python
state = accufractionstate("ldd.map", "material.map", 0.5)
flux = accufractionflux("ldd.map", "material.map", 0.5)


## Boolean operations¶

Do not use PCRaster objects in context of Python boolean operations.

“In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false: None, numeric zero of all types, empty sequences (strings, tuples and lists), and empty mappings (dictionaries). All other values are interpreted as true.”

—Python Reference Manual [http://docs.python.org/ref].

This means that PCRaster objects will always be interpreted as true when used in the above mentioned cases.

When the PCRaster (field) objects are used in a Python boolean context you will recieve the error:

The truth value for PCRaster spatial data types is ambiguous.
See the section Boolean operations in the PCRaster Python manual.

Most likely you used one of the following Python constructs:

booleanMap = readmap("dump.map")

if booleanMap:
selection = map1
selection = ifthen(booleanMap, map1)

if booleanMap:
something = map1
else:
something = map2
something = ifthenelse(booleanMap, map1, map2)

dumpAndHouseHold = booleanMap and booleanMap2
dumpAndHouseHold = booleanMap & booleanMap2

dumpOrHouseHold = booleanMap or booleanMap2
dumpOrHouseHold = booleanMap | booleanMap2

dumpXorHouseHold = booleanMap xor booleanMap2
dumpXorHouseHold = booleanMap ^ booleanMap2

notDump = not booleanMap
notDump = ~ booleanMap