Jython

By default, RiskScape will execute your Python function using the Java-based implementation, called Jython.

Alternatively, you can setup RiskScape to use CPython. You can also mix and match, and use CPython for some functions and Jython for other functions.

This page describes some of the behaviour specific to Jython in more detail.

Calling other RiskScape functions

You can call other user-defined Jython functions from your function, as well as some built-in RiskScape functions. For example, we could call our hello function from the hello world example from another different function:

# basic syntax is: functions.get(<function-name>).call(<arguments>)
greeting = functions.get('hello').call('Kia ora', 'Ronnie')

Note that currently this has the following limitations:

  • The types of the arguments must match exactly, e.g. you cannot pass an integer to something that expects a floating argument.

  • You must not omit any optional arguments.

  • Built-in RiskScape functions that support a wide range of argument-types (i.e. functions that accept or return the type Anything) are not supported.

Jython packages

If you have used Python (or more specifically, CPython) in the past, you may notice that Jython is a little different, in particular when importing and using packages.

For example, generating a random number between zero and one would usually look like the following in CPython.

import random
num = random.uniform(0, 1.0)

Whereas in Jython, it would look like this:

from java.util import Random
random = Random()
num = random.nextDouble()

Note

We recommend you call the built-in RiskScape functions where possible, rather than importing Jython packages.

For example, to achieve the same thing using the built-in RiskScape function:

num = functions.get('random_uniform').call(0.0, 1.0)

Tip

In general, once you start needing to import Python packages, it will be simpler to switch from using Jython to using CPython.

Basic loss function

Now let’s look at a more complicated example. The below Python code (quake.py) is an example of a basic loss function.

def function(building, hazard):
  loss = {}
  loss['replacement'] = building['replace']
  loss['hazard'] = hazard
  construction = building['construct']
  if hazard is None:
    loss['dr'] = 0
    loss['loss'] = 0
  else:
    loss['dr'] = damage_function(construction, hazard)
    loss['loss'] = loss['replacement'] * loss['dr']
  return loss

CONSTRUCT_WOOD = 1

def damage_function(construction, hazard):
  if construction == CONSTRUCT_WOOD:
    mean = 0.22
    stddev = 0.74
  else:
    mean = 0.92
    stddev = 0.64

  # call the built-in 'lognorm_cdf' riskscape function
  return functions.get('lognorm_cdf').call(hazard, mean, stddev)

This function demonstrates many points we have already covered, such as:

  • The building argument is a struct, and contains two attributes that we are interested in: construction type and replacement value. Note that the actual building input data file might contain many more attributes, but our function only cares about two of them.

  • The hazard argument is nullable, i.e. it may be None.

  • We call the builtin RiskScape function lognorm_cdf to calculate the cumulative log normal distribution.

  • The return value is a struct, which we build up as a Python dictionary.

The INI file definition for this function might look like this:

[function quake]
description = Example loss function
location = quake.py
argument-types = [ building, hazard: nullable(floating) ]
return-type = shaking_result

[type building]
type.replace = integer
type.construct = integer

[type shaking_result]
type.hazard = nullable(floating)
type.loss = floating
type.dr = floating
type.replacement = integer

We have defined the building argument and return-value as separate types here, for clarity.

Older behaviour

If you have used older RiskScape releases, this next section covers some of the differences you might notice with Jython functions.

Function parameters

In previous releases, RiskScape used to support a special PARAMETERS keyword for Jython functions. These parameters were helpful if your function made certain assumptions when determining the consequence for a given exposure and hazard - you could then vary these assumptions between model runs. The function parameters applied across all exposure and hazard input data.

The PARAMETERS keyword is no longer supported for Jython. Instead, you can use model parameters to pass assumptions to your function, and to vary these assumptions between model runs.

Defining argument/return types inline

An older approach used to define the function ID, ARGUMENT_TYPES, and RETURN_TYPE inline in the Python code, rather than in the INI file. This is still supported in the meantime for backwards compatibility.

If you are using this approach, Jython type usage has more examples of using types within a Python function.