Source code for ollin.calibration.calibrate

"""Module for Movement Model calibration.

Every Movement Model is defined in terms of user controllable parameters which
must be calibrated before use. Model calibration refers to the three following
procedures:

    1. Velocity calibration:
        Even though all Movement Models must implement some way of controlling
        agent mean speed, it may be impossible to precisely select the correct
        speed parameter to obtain the desired mean speed, specially for complex
        models with interactions between environment and other individuals.
        Hence a correction to the speed parameter must be calculated to amend
        such shortcomings. Mean speed is calculated in a variety of scenarios
        and a correction factor is calculated by fitting the velocity data of
        the simulated movements to desired outcome.

    2. Home Range calibration.
    3. Occupancy calibration.
        A main feature of :py:mod:`ollin` is its capacity to generate random
        scenarios with a user determined home range and occupancy values. In
        order for this to be possible, the fundamental relations between
        home range and mean velocity, and density and occupancy, must be
        understood. These relations depend on the Movement Model. Home range
        and Occupancy calibration refer to the process in which simulations
        in a variety of scenarios are run and a parametric model of response
        functions are fitted to the data to obtain an approximate functional
        relation between home range and mean velocity, and density and
        occupancy.
"""
import os
import logging

from .home_range import HomeRangeCalibrator
from .occupancy import OccupancyCalibrator
from .velocity import VelocityCalibrator

from ..movement_models.base import MovementModel
from .config import STARTING_PARAMETERS, BASE_CONFIG


logger = logging.getLogger(__name__)


[docs]def calibrate( model, config=None, save_fig=False, save_path=None, plot_style='fivethirtyeight'): """Calibrate parameters of movement model. Arguments --------- model : :py:obj:`.MovementModel` Movement model instance to calibrate. config : dict, optional Dictionary holding calibration configuration values. If None is given, default configurations will be used. See :py:mod:`.config` save_fig : bool, optional If True, calibration procedure will save calibration graphs. save_path : str, optional Path in which to save calibration figures. Must be provided if save_fig is True. plot_style: str, optional Name of pyplot style to use in calibration figures. See pyplot_ to see all available options. Returns ------ calibrated_model : :py:class:`.MovementModel` Same Movement model instance with calibrated parameters. calibrated_parameters : dict Dictionary holding all calibrated parameters. Raises ------ ValueError: If no save_path was provided while save_fig is True. .. _pyplot: https://matplotlib.org/gallery/style_sheets/style_sheets_reference.html """ # Check if instance of class or class is passed as argument if issubclass(model, MovementModel): model = model(STARTING_PARAMETERS) else: params = model.handle_parameters(STARTING_PARAMETERS) model.parameters = params if (save_fig and save_path is None): msg = 'No path was given for calibration figures.' raise ValueError(msg) # Make sure save path exists if save_fig: import matplotlib.pyplot as plt if not os.path.exists(save_path): os.makedirs(save_path) # Handle configs if config is None: config = {} calibration_config = BASE_CONFIG.copy() calibration_config.update(config) logger.info('Starting Velocity calibration.') # Calibrate velocity vel_calibrator = VelocityCalibrator(model, calibration_config) velocity_parameters = vel_calibrator.fit() model.parameters['velocity'] = velocity_parameters if save_fig: logger.info('Saving velocity calibration plot.') with plt.style.context(plot_style): ax = vel_calibrator.plot() path = os.path.join(save_path, 'velocity_calibration.png') ax.get_figure().savefig(path, frameon=True) logger.info('Starting Home range calibration.') # Calibrate Home Range hr_calibrator = HomeRangeCalibrator(model, calibration_config) hr_paramters = hr_calibrator.fit() model.parameters['home_range'] = hr_paramters if save_fig: logger.info('Saving home range calibration plot.') with plt.style.context(plot_style): ax = hr_calibrator.plot() path = os.path.join(save_path, 'home_range_calibration.png') ax.get_figure().savefig(path, frameon=True) logger.info('Starting Occupancy calibration.') # Calibrate Occupancy oc_calibrator = OccupancyCalibrator(model, calibration_config) oc_parameters = oc_calibrator.fit() model.parameters['density'] = oc_parameters if save_fig: logger.info('Saving occupancy calibration plot.') with plt.style.context(plot_style): ax = oc_calibrator.plot(x_var='density') path = os.path.join( save_path, 'occupancy_calibration_density.png') ax.get_figure().savefig(path, frameon=True) ax = oc_calibrator.plot(x_var='home_range') path = os.path.join( save_path, 'occupancy_calibration_home_range.png') ax.get_figure().savefig(path, frameon=True) ax = oc_calibrator.plot(x_var='niche_sizes') path = os.path.join( save_path, 'occupancy_calibration_niche_size.png') ax.get_figure().savefig(path, frameon=True) return model, model.parameters