Customizing your own model parameters
This page delves into some of the more powerful things you can do with pipelines. It is aimed at people who have already completed the How to write advanced pipelines tutorial.
Pipeline model parameters
You should be aware that each pipeline step has parameters, but the pipeline model itself can also have its own parameters. Unlike step parameters, you have complete control over defining the model parameters yourself.
The model parameters are essentially custom variables that get replaced at run-time.
These variables are denoted by a $
in the pipeline file.
The model parameters can customize the behaviour of the model across all input data. Model parameters can encapsulate an assumption you are making about your model, which you may want to vary.
As a simple example, say we only wanted to run our model for one particular construction type at a time.
But we wanted to be able to vary that construction type easily, without editing the pipeline file each time.
We can turn the construction type we filter on into a construction
parameter, e.g.
input('assets.csv', name: 'asset') -> filter(filter: asset.construction = $construction)
When we run our model, we can then specify what specific construction type we are interested in, e.g.
riskscape model run my_pipeline --param "construction='steel'"
You can define the default values for your parameters in your model’s INI definition.
Just use param.<name> = <default>
, e.g.
[model my_pipeline]
framework = pipeline
location = my_pipeline.txt
param.construction = 'timber'
Parameter properties
When you want to share a model with other users, you can restrict what sort of values
the user can specify for certain parameters. For example, you could specify that
a parameter called damage_ratio
always had to be a numeric, or always had
to be within a certain range, such as 0.0 to 1.0.
You can specify what properties a parameter is expected to have in your project.ini
file.
For example, the damage_ratio
parameter would look like this:
param.damage_ratio.properties = numeric, min: 0.0, max: 1.0
If the user tries to enter anything that is not a numerical value between 0.0 and 1.0, then they will get an error when they try to run the model.
The parameter properties supported on the RiskScape CLI include: bookmark, integer, list, min, max, numeric, and text.
Tip
Specifying the text
or bookmark
properties means that the user no longer
needs to use ''
single-quotes when entering a new parameter value.
Function parameters
Model parameters also work if the assumption you are making is in your function. You simply need to pass the model parameter through to your function.
To do this you add an extra argument to your function.
The new argument will be a Struct
and contain the attributes you want to vary.
For example, say our Kaijū function was making an assumption on how resilient timber buildings
are to Kaijū attacks. We can modify our function to take an additional ‘options’ argument,
which is a Struct
with a timber_resilience
attribute. The (abridged) function would look like this:
from nz.org.riskscape.engine.types import Types
from nz.org.riskscape.engine.types import Struct
ID = 'kaiju_stomp'
DESCRIPTION = 'Models damage from a Kaiju stomping a building'
ARGUMENT_TYPES = ['building', 'kaiju_attack', \
Struct.of('timber_resilience', Types.INTEGER) ]
RETURN_TYPE = 'building_attack_outcome'
def function(building, stomp, options):
if building.get('construction') == 'timber':
# the resilience for timber buildings can be passed
# into our function, making it easier to vary it
resilience = options.get('timber_resilience')
elif building.get('construction') == 'concrete':
# whereas the resilience for concrete buildings is
# still hard-coded in the function itself
resilience = 5
# ...
Then to call our function from our pipeline code, we create a new Struct
with a
timber_resilience
attribute. In this case, the value for timber_resilience
is a model
parameter that we can now change on the fly whenever we run our model.
select({*,
kaiju_stomp(asset, hazard, { timber_resilience: $timber_resilience }) as damage
) as compute consequence
The ‘options’ Struct
could hold many different attributes, if there are many assumptions
in your function that you want to vary.
A working example
Click Here to download a working example of a parameterized pipeline.
Open the pipeline.txt
and project.ini
files and familiarize yourself with them.
You can see that the model defines ‘resilience’ parameters for the three construction materials of interest.
These parameters then get passed directly to the kaiju_stomp
function.
To run the model with default parameter values, use the command:
riskscape model run demo
Reproducible models
Model parameters can make it harder to tell later what actual parameter values were used to produce a certain set of results. Fortunately, RiskScape always saves the actual parameter values it used in the output directory.
Have a look at the output directory created by the last ‘model run’ command.
It should contain a pipeline.txt
file - this contains the pipeline code with the $
parameters
replaced with the actual values used by the ‘model run’ command.
Any piece of raw pipeline code (i.e. without parameters) can be executed using the riskscape pipeline eval
command.
So you can use the pipeline.txt
file in the output directory to re-run the exact same pipeline again in the future, e.g.
riskscape pipeline eval <pipeline.txt>
Try this now and check you get the same results.
Parameter INI files
When your model has several different parameters, rather than specifying each parameter on the command line, you can just specify one INI file that contains all the parameter values you want to use.
To pass the INI file to the ‘model run’ command, use the --parameters
CLI option (note the ‘s’ on the end).
For example:
riskscape model run demo --parameters stronger-resilience.ini
Using INI files can be helpful if you want to vary several different assumptions in a related way.
For example, this project contains two different INI files that make different assumptions about
a building’s resilience: stronger-resilience.ini
and weaker-resilience.ini
.
Try running the model with each of these INI files and see what difference it makes to the overall damage.