Add new Movement Models

Making a new movement model involves the following steps:

Make the code

Make a new file with an abbreviation of the movement model’s name.

Any movement model must be a new class named Model that inherits from ollin.MovementModel. A name for the class must be specified as an attribute:

from ollin import MovementModel


class Model(MovementModel):
  name = 'New Movement Model'

Movement behaviour is implemented in the method generate_movement. This method must have as arguments:

  1. The model instance (self).
  2. An array with initial positions.
  3. A Site in which motion is to take place.
  4. Number of steps to simulate.
  5. Mean velocity to try to achieve.

And it must return an array of shape [num, steps, 2] where num is the number of initial positions contained in the initial positions array.

See MovementModel for full reference.

For example:

from ollin import MovementModel
import numpy as np


class Model(MovementModel):
  name = 'Random Movement'

  def generate_movement(self, initial_position, site, steps, velocity):
    num = len(initial_position)
    movement = np.random.random([num, steps, 2])
    return movement

Warning

Note that velocity and site arguments are not used in this mock version of a movement model. This is perfectly fine and will not break any of the functionalities, although will probably lead to a bad movement model.

Note

The name for the velocity argument might suggest that movement generated by the model must have mean velocity equal to velocity. Although this would be desirable, it might not be possible, and so models have to go through a calibration phase so that desired mean velocity is obtained. See Velocity Calibration.

If the movement model you wish to write depends on some parameters, please specify default parameters at the class definition inside the default_parameters dictionary, inside the movement key. This parameters can be overwritten at instantiation, and are be available at self.parameters. For example:

class Model(MovementModel):
  name = 'Random Movement'
  default_parameters = {
    'movement': {
      'alpha': 0.4
    }
  }

  def generate_movement(self, initial_position, site, steps, velocity):
    movement_parameters = self.parameters['movement']
    alpha = movement_parameters['alpha']

    num = len(initial_position)
    movement = np.random.binomial(1, alpha, shape=[num, steps, 2])
    return movement

Efficiency Considerations

Movement simulation is generally a computationally expensive operation. Hence a careful though on its implementation is often necessary. Bare Python functions have large overhead due to the nature of the language, but there are many paths to greater efficiency:

numpy:The fundamental numerical python package. Numpy routines handle large amounts of operations with optimized code, reducing the computing time in considerable amounts. Numpy arrays and operations are used through Ollin and are heavily recommended for any Movement Model implementation. Check this guide to get started with Numpy.
numba:This wonderful library allows to make optimized compiled versions of python functions while still having a simple interface and relative ease-of-use. Many Numpy operations are compatible with Numba compilation, but it does not support arbitrary functions. Check numba documentation on how to convert your functions into a optimized version and to consult valid operations.
cython:Cython is a superset of Python language that compiles to optimized C code that can be called from Python.

Calibration

In order to generate motion with the desired mean speed, or to generate scenarios with a given home range or occupancy, the model must be calibrated before use. For more details on calibration see Calibration.

To calibrate the model open a new python terminal (or a jupyter notebook), import your model and make a new instance:

>> import ollin
>> from new_model import Model
>> model = Model()

Ollin has a calibration tool that can be run in the following fashion:

>> calibrated_model, calibrated_parameters = ollin.calibrate(model)

This function will run many simulations so be prepared to wait. If you wish to have some feedback on progress configure logging before running calibrate:

>> import logging
>> logging.basicConfig(level=logging.INFO)

The calibration procedure can be configured, see calibration.config to consult all settings.

Warning

Calibration simulations are executed in all available cores of host computer and will consume large amounts of memory. We recomend stopping other processes before calibration.

With the results of the simulations, the parameters are fitted to the generated data and returned in a dictionary. Use these values to adjust the default parameters in the code file. So if:

>> calibrated_parameters
{
  'home_range': {
    'alpha': 59.02095500748234,
    'exponent': 1.903072119815655
  },
  'density': {
    'hr_exp': 0.8441724458551622,
    'density_exp': 0.8501718469622543,
    'alpha': 4.950773510732457,
    'niche_size_exp': 0.8760285191282491
  },
  'velocity': {
    'alpha': 0.002223569915673946,
    'beta': 1.013044346939526
  }
}

Then edit the file to:

from ollin import MovementModel
import numpy as np


class Model(MovementModel):
  name = 'Random Movement'
  default_parameters = {
    'movement': {
      'alpha': 0.4
    },
    'home_range': {
      'alpha': 59.02095500748234,
      'exponent': 1.903072119815655
    },
    'density': {
      'hr_exp': 0.8441724458551622,
      'density_exp': 0.8501718469622543,
      'alpha': 4.950773510732457,
      'niche_size_exp': 0.8760285191282491
    },
    'velocity': {
      'alpha': 0.002223569915673946,
      'beta': 1.013044346939526
    }
  }

  def generate_movement(self, initial_position, site, steps, velocity):
    movement_parameters = self.parameters['movement']
    alpha = movement_parameters['alpha']

    num = len(initial_position)
    movement = np.random.binomial(1, alpha, shape=[num, steps, 2])
    return movement

The model is now calibrated.

Add file to models library

Once the model is calibrated, fork the repository and move the file to the directory ollin/movement_models/. Reinstall Ollin using the setup script (see Installation Guide) and use the model freely! Don’t forget to send the pull request.