Tutorial¶
The tutorial gives a short introduction into the usage of the arrayed variables in Python.
Importing the module¶
To use the arrayed variables in your Python script use:
from PCRaster.Collection import *
Creating collection index types¶
In oldcalc, index types are created as follows:
# oldcalc
PlantSpecies = [
Species1,
Species2,
Species3];
In Python, an index type is created as:
# Python
PlantSpecies = Index(["Species1", "Species2"])
The indices are given as a list of names.
Creating variable collections¶
In oldcalc, arrayed variables are created as follows:
# oldcalc
Variable1[Species1] = ...;
Variable1[Species2] = ...;
In Python, you create a variable collection object by using the index types:
# Python
PlantSpecies = Index(["Species1", "Species2"])
Variable1 = VariableCollection([PlantSpecies], value=None)
This will initialise the indices with the default value None
. Afterwards, you can assign values as:
Variable1[PlantSpecies.Species1] = ...
Variable1[PlantSpecies.Species2] = ...
As an alternative, you can use an external parameter file to initialise the values (collection values not specified in the external file will be set to the default value None
) like:
# Python
Variable1 = VariableCollection([PlantSpecies], value=ValueFromParameterTable("Variable1", "values.tbl", dataType=Scalar))
where Variable1
is the name of the collection variable referred to in the external file, values.tbl
the filename of the external file and Scalar
the PCRaster data type of the collection. In case of initialising collection indices with PCRaster field objects, i.e. reading maps from disk, set the dataType
argument to None
.
Creating multidimensional collections¶
Multidimensional collections are created in a similar way as one-dimensional arrays:
# Python
PlantSpecies = Index(["Plant1", "Plant2"])
Herbivores = Index(["Species1", "Species2", "Species3"])
Interaction = VariableCollection([Herbivores, PlantSpecies], value=None)
This will create a variable Interaction
holding a 2-dimensional collection. You can set values like:
Interaction[Herbivores.Species1, PlantSpecies.Plant1] = scalar(2.5)
# repeat initialisation for the remaining Herbivore-PlantSpecies combinations
Again, the variable can be initialised from a parameter file insetead:
Interaction = VariableCollection([Herbivores, PlantSpecies], value=ValueFromParameterTable("Interaction", "interaction.tbl", dataType=Scalar))
The parameter file looks similar to:
#interaction.tbl
Interaction Species1 Plant1 0.2
Interaction Species1 Plant2 0.35
Interaction Species2 Plant1 0.33
Interaction Species2 Plant2 0.35
Interaction Species3 Plant1 0.4
Interaction Species3 Plant2 0.5
Iterating over the collection¶
While in oldcalc a foreach
construct iterates over the array:
# oldcalc
foreach species in PlantSpecies {
Variable1[species] = ...;
Variable2[species] = ...;
}
In Python there are two options to iterate over the collection. First, you can use the for in
construct and iterate over the index types:
for species in PlantSpecies:
Variable1[species] = ...
Variable2[species] = ...
Iterating over multidimensional collections can be done with nested for in
statements:
for herb in Herbivores:
for plant in Plants:
Interaction[herb, plant] = ...
As a second option you can iterate over the collection:
for herb, plant in Interaction:
Interaction[herb, plant] = ...
Using None
values in a collection¶
Not necessarily all values in a collection need to be specified. E.g. in our Herbivore-PlantSpecies interaction example, some interactions between species do not appear. If so, you can assign None
to that variable:
Interaction[Herbivores.Species3, PlantSpecies.Plant2] = None
When iterating over index types, it is now required to test if values are set:
for herb in Herbivores:
for plant in Plants:
if not Interaction[herb, plant] is None:
Interaction[herb, plant] = ...
The collection iterator only operates on values being not None
, therefore it is not necessary to change the code:
for herb, plant in Interaction:
Interaction[herb, plant] = ...
Reporting timeseries¶
To report timeseries for each collection index the variable collection class needs to be initialised with the ValueTimeoutputTimeseries
class:
InteractionTss = VariableCollection([Herbivores, PlantSpecies], value=ValueTimeoutputTimeseries("Interaction", self, idMap="locations.map", noHeader=False)))
Afterwards you can sample values for each collection index:
for herb, plant in Interaction:
InteractionTss[herb, plant].sample(Interaction[herb, plant])
The resulting output files will be named like Interaction-Species3-Plant2.tss
.
Linking variable names to external names¶
In the case you want to use variable names in your model script different from the ones in the parameter files you can link those external names to variable names while you initialise the Index
class:
Herbs = Index(["ES=EvergreenShrub", "SPG=ShortPerennialGrass", "Cal=Calluna"])
GrowthFactor = VariableCollection([Herbs], value=ValueFromParameterTable("GrowthFactor", "parameterFile.tbl", Scalar))
To assign external names use the format Modelname = Externalname
. Here, you create in your model script a collection variable GrowthFactor
with the three indices Herbs.ES
, Herbs.SPG
and Herbs.Cal
. In the parameter file you can refer to the external names EvergreenShrub
, ShortPerennialGrass
and Calluna
:
GrowthFactor EvergreenShrub 0.3
GrowthFactor ShortPerennialGrass 0.37
GrowthFactor Calluna 0.29