All data in RiskScape has a type. Types define the shape of the data that goes in and out of your models. RiskScape uses a set of built-in simple types to describe the data in a model. For example, we have simple types, such as:
integer(whole numbers), e.g. 1, -4
real numbers (
floatingpoint), e.g. 0.25454, -8464564564.2
texte.g. free form strings of text with no fixed length
geometrye.g. points, polygons, lines, etc
Each attribute in your input data can generally be described using a simple type.
A collection of attributes is called a struct in RiskScape. A struct is a complex type.
A struct is a way of keeping related data together. For example, all the attributes in your exposure-layer input data can be represented by a struct. Each attribute, or member, in the struct has a name and a type (a bit like a database schema).
For example, say we had a shapefile that contained the following building data:
Our model then reads this data into a struct called
exposure struct would contain the following attributes, or struct members:
geometry type), and
This struct could be defined using the following type expression (more on this later):
struct(ID: integer, Cons_Frame: text, the_geom: geometry, Use_Cat: text)
If you are familiar with Pandas, a struct is similar to the
dtypes in a
There are a few types that have a special meaning in RiskScape, namely
nullabletype is a way of saying that a value might be null, or not present. When used in a function, it can mean that a function argument is optional. Nullable always applies to another underlying type, e.g.
For example, the hazard intensity measure in a model is usually
nullable. The element-at-risk may not actually be exposed to the hazard, and if not then there will be no corresponding hazard intensity measure.
anythingtype is a way of saying that there must be a value, but it can be any value whatsoever. Anything can be used when the exact type is not clear.
For example, the expression
if_then_else(hazard > 0.25, 'Damaged', 0)could result in an integer (
0), or it could result in a text string (
'Damaged'). RiskScape cannot be certain, so the resulting type becomes
Viewing type information
To list the different built-in RiskScape types available to use, run the
riskscape type-registry list command.
This displays some help information alongside each of the types, explaining what is is and how it might be used.
If you’re new to RiskScape, try running
riskscape type-registry list now.
Types in models
RiskScape will generally manage your model’s data types behind the scenes, so you do not have to worry about it. However, types can make your models more robust and easier to share and understand.
Types can define a relationship between your input data and your Python function. Typically, you may want to re-use your Python function but potentially change the exposure-layer data, e.g. use a building dataset from another region or country. If the new exposure-layer isn’t in the format that your Python function expects, then your model will not work correctly.
Let’s say we have a tsunami damage function that uses the building construction framing (a
Our Python function expects the
Cons_Frame attribute to be
text, e.g. ‘Timber’, ‘Masonry’, ‘Concrete’, etc.
The tsunami inundation depth will be a floating-point number, which is
nullable (i.e. may or may not exist).
RiskScape will always try to pass the exposure-layer data and the sampled hazard intensity measure to your function.
The exposure-layer data is represented as a
struct, so your function’s first argument-type is generally always a
We would define our damage function in our
project.ini to take two argument types:
The construction framing attribute for our building:
struct function argument only needs to specify the subset of attributes that your Python function actually uses.
You do not have to specify every single attribute that is in your exposure-layer data.
When RiskScape passes a
struct to your function, it turns the
struct argument into a
of key-value pairs. The dictionary keys are the
struct member names, e.g.
When you run your model, RiskScape goes through each row of data in your exposure-layer (represented by an
and passes the data one by one to your Python function, along with the sampled
hazard intensity measure.
The following diagram highlights what happens in the ‘Consequence Analysis’ phase of the model, when the Python function is called.
If we wanted to change the exposure-layer that our model uses, the new data would still need to contain a
text format. If the attribute were numeric instead of textual, or if it had a different name (e.g.
then the model would not work.
When your input data is in a slightly different format, you can use bookmarks to change the attribute names or types. See
Types are defined using a type expression. For simple types, it is enough to refer to them by their id. Complex types look more like function calls and accept arguments, e.g:
# a simple type text # a list of text list(text) # a struct with various members, including a nullable description struct(id: integer, name: text, description: nullable(text))
Types can be defined in your Projects by adding type expressions to your project’s INI file. A type can be added like this:
# the bit after type is the identifier [type my_types_id] # single line definition type = struct(id: integer, name: text) [type another_type] # multi-line struct definition type.id = integer type.name = text
You can view the results of adding types to your project with the
riskscape type list command.
Any problems with the types in your project will be shown to you when RiskScape starts up.
In some situations, a value in your model can be coerced from one type to another. This is not guaranteed to succeed and a failed coercion can result in different behaviour. Typically it will fail the model run or give a null result.
An example of coercion would be converting some text to a number, for example the
text “11.43” can be coerced to type
“$11.43c” can not.
A type is said to be equivalent (or more formally, covariant) if the value of the type can be safely represented by another type. The type
anything is equivalent to any other type you give it, except
nullable. Apart from this special case, equivalence is determined by comparing
the two types for equality and things called wrapping types - a wrapping type surrounds another type to add extra metadata or validation to it.
An examples of a wrapping types is the
within type - it wraps another type to constrain values to be within a known set, e.g.
animals = within(text, 'cat', 'dog', 'pig').
text type is equivalent to this
animals type, as the
text type can represent all the values that it can. The opposite is not true, as there are
that can not be represented by the
animals type, e.g. “robot” is not a valid value for
An understanding of this can be helpful when building expressions to customize your models.
Here are some tips if you are getting a ‘type mismatch’ error when running your model:
When defining types for a function, make sure you only define the minimum subset of attributes that your Python code actually uses (these are the attributes that you try to access from the Python dictionary, e.g.
riskscape bookmark info BOOKMARK_IDto view the attribute names and types for your input data. The command also accepts a path to a shapefile directly, instead of a
The Creating a RiskScape project tutorial has examples on how to use bookmarks to change an attribute’s name or type.
When you are using CSV input data, all the attributes will default to
texttype. Refer to the Creating a RiskScape project tutorial for how to turn numeric CSV data back into
You can use the
anythingtype for your exposure-layer function argument, as a sort of wildcard. RiskScape will simply pass all your exposure-layer attributes to your Python function as one big Python dictionary. Your Python code will need to check that any required attributes are present itself.
Mixing two different types together will generally result in the
anythingtype. This can even happen from combining together
floatingvalues. If you are using zero in an expression with
floatingdata, then you need to use
If needed, RiskScape can automatically turn
floatingtype, but it cannot go the other way (coercing
integertype). This means that using the
floatingtype for function arguments can be more permissive than
You can safely omit the
nullabletype for your hazard intensity measure. This will mean that your function will not be called for unexposed elements-at-risk, and the resulting
consequencewill simply be null in these cases.
RiskScape also provides types that will perform validation.
range types will check that the input data is within a specified range of values.