API documentation for the base_model
module
The base_model
module defines the high level API for
the different models within the Virtual Ecosystem. The module creates the
BaseModel
abstract base class (ABC) which
defines a consistent API for subclasses defining an actual model. The API defines
abstract methods for each of the key stages in the workflow of running a model:
individual subclasses are required to provide model specific implementations for
each stage, although the specific methods may simply do nothing if no action is needed
at that stage. The stages are:
Creating a model instance (
BaseModel
).Setup a model instance (
setup()
).Perform any spinup required to get a model state to equilibrate (
spinup()
).Update the model from one time step to the next
update()
).Cleanup any unneeded resources at the end of a simulation (
cleanup()
).
The BaseModel
class also provides default
implementations for the __repr__()
and __str__()
special methods.
Declaring new subclasses
The BaseModel
has four class attributes
that must be specified as arguments to the subclass declaration:
model_name
,
required_init_vars
,
model_update_bounds
and
vars_updated
. This behaviour is
defined in the BaseModel.__init_subclass__()
method, which also
gives example code for declaring a new subclass.
The usage of these four attributes is described in their docstrings and each is
validated when a new subclass is created using the following private methods of the
class:
_check_model_name()
,
_check_required_init_vars()
,
_check_model_update_bounds()
and
_check_vars_updated()
.
Model checking
The BaseModel
abstract base class defines
the __init_subclass__()
class
method. This method is called automatically whenever a subclass of the ABC is imported
and validates the class attributes for the new model class.
The BaseModel.__init__
method
Each model subclass will include an __init__
method that validates and populates
model specific attributes. That __init__
method must call the
BaseModel.__init__()
method, as this populates core shared model attrributes - see the linked method
description for details.
super().__init__(data, core_components)
The from_config
factory method
The ABC also defines the abstract class method
from_config()
. This method must be
defined by subclasses and must be a factory method that returns an instance of the model
subclass. The method must follow the signature of that method, providing:
data
as an instance ofData
.core_components
as an instance ofCoreComponents
.config
as an instance ofConfig
.
The method should provide any code to validate the configuration for that model and then use the configuration to initialise and return a new instance of the class.
Model registration
Models have three core components: the
BaseModel
subclass itself (model
),
a JSON schema for validating the model configuration (schema
) and an optional set of
user modifiable constants classes (constants
, see
ConstantsDataclass
). All model
modules must register these components when they are imported: see the
registry
module.
Classes:
|
A superclass for all Virtual Ecosystem models. |
- class virtual_ecosystem.core.base_model.BaseModel(data: Data, core_components: CoreComponents, **kwargs: Any)
A superclass for all Virtual Ecosystem models.
This abstract base class defines the shared common methods and attributes used as an API across all Virtual Ecosystem models. This includes functions to setup, spin up and update the specific model, as well as a function to cleanup redundant model data.
The base class defines the core abstract methods that must be defined in subclasses as well as shared helper functions.
- Parameters:
data – A
Data
instance containing variables to be used in the model.core_components – A
CoreComponents
instance containing shared core elements used throughout models.
Methods:
__init__
(data, core_components, **kwargs)Performs core initialisation for BaseModel subclasses.
__init_subclass__
(model_name, ...)Initialise subclasses deriving from BaseModel.
__repr__
()Represent a Model as a string from the attributes listed in _repr.
__str__
()Inform user what the model type is.
_check_model_name
(model_name)Check the model_name attribute is valid.
_check_model_update_bounds
(model_update_bounds)Check that the model_update_bounds attribute is valid.
_check_required_init_vars
(required_init_vars)Check the required_init_vars property is valid.
_check_vars_updated
(vars_updated)Check that vars_updated is valid.
Check the init data contains the required variables.
cleanup
()Function to delete objects within the class that are no longer needed.
from_config
(data, core_components, config)Factory function to unpack config and initialise a model instance.
setup
()Function to use input data to set up the model.
spinup
()Function to spin up the model.
update
(time_index, **kwargs)Function to update the model.
Attributes:
The core constants used in the model.
A Data instance providing access to the shared simulation data.
The LayerStructure details used in the model.
The model name.
The ModelTiming details used in the model.
Bounds on model update frequencies.
Required variables for model initialisation.
Variables that are updated by the model.
- __init__(data: Data, core_components: CoreComponents, **kwargs: Any)
Performs core initialisation for BaseModel subclasses.
This method must be called in the
__init__
method of all subclasses.It populates a set of shared instance attributes from the provided
CoreComponents
andData
value:data
: the providedData
instance,model_timing
: theModelTiming
instance from thecore_components
argument.layer_structure
: theLayerStructure
instance from thecore_components
argument.core_constants
: theCoreConsts
instance from thecore_components
argument.
It then uses the
check_init_data()
method to confirm that the required variables for the model are present in the provideddata
attribute.
- classmethod __init_subclass__(model_name: str, model_update_bounds: tuple[str, str], required_init_vars: tuple[tuple[str, tuple[str, ...]], ...], vars_updated: tuple[str, ...]) None
Initialise subclasses deriving from BaseModel.
This method runs when a new BaseModel subclass is imported. It adds the new subclasses to the model registry and populates the values of the class attributes.
Subclasses of the BaseModel need to provide the values for class attributes in their signatures. Those values are defined by the arguments to this method, which validates and sets the class attributes for the subclass. See
BaseModel
for details on the class attributes. For example:class ExampleModel( BaseModel, model_name='example', model_update_bounds= ("30 minutes", "3 months"), required_init_vars=(("required_variable", ("spatial",)),), vars_updated=("updated_variable"), ): ...
- Parameters:
model_name – The model name to be used
model_update_bounds – Bounds on update intervals handled by the model
required_init_vars – A tuple of the variables required to create a model instance.
vars_updated – A tuple of the variable names updated by the model.
- Raises:
ValueError – If the model_name or required_init_vars properties are not defined
TypeError – If model_name is not a string
- __repr__() str
Represent a Model as a string from the attributes listed in _repr.
Each entry in self._repr is a tuple of strings providing a path through the model hierarchy. The method assembles the tips of each path into a repr string.
- classmethod _check_model_name(model_name: str) str
Check the model_name attribute is valid.
- Parameters:
model_name – The
model_name
attribute to be used for a subclass.- Raises:
ValueError – the model_name is not a string.
- Returns:
The provided
model_name
if valid
- classmethod _check_model_update_bounds(model_update_bounds: tuple[str, str]) tuple[pint.util.Quantity, pint.util.Quantity]
Check that the model_update_bounds attribute is valid.
This is used to validate the class attribute
model_update_bounds
, which describes the lower and upper bounds on model update frequency. The lower bound must be less than the upper bound.- Parameters:
model_update_bounds – A tuple of two strings representing time periods that can be parsed using
pint.Quantity
.- Raises:
ValueError – If the provided model_update_bounds cannot be parsed as
pint.Quantity
with time units or if the lower bound is not less than the upper bound.- Returns:
The validated model_update_bounds, converted to a tuple of
pint.Quantity
values.
- classmethod _check_required_init_vars(required_init_vars: tuple[tuple[str, tuple[str, ...]], ...]) tuple[tuple[str, tuple[str, ...]], ...]
Check the required_init_vars property is valid.
- Parameters:
required_init_vars – The
required_init_vars
attribute to be used for a subclass.- Raises:
TypeError – the value of required_init_vars has the wrong type structure.
ValueError – required_init_vars uses unknown core axis names.
- Returns:
The provided
required_init_vars
if valid
- classmethod _check_vars_updated(vars_updated: tuple[str, ...]) tuple[str, ...]
Check that vars_updated is valid.
- Returns:
The provided value if valid.
- check_init_data() None
Check the init data contains the required variables.
This method is used to check that the set of variables defined in the
required_init_vars
class attribute are present in theData
instance used to create a new instance of the class.- Raises:
ValueError – If the Data instance does not contain all the required variables or if those variables do not map onto the required axes.
- core_constants: CoreConsts
The core constants used in the model.
- abstract classmethod from_config(data: Data, core_components: CoreComponents, config: Config) BaseModel
Factory function to unpack config and initialise a model instance.
- layer_structure: LayerStructure
The LayerStructure details used in the model.
- model_name: str
The model name.
This class attribute sets the name used to refer to identify the model class in the
MODULE_REGISTRY
, within the configuration settings and in logging messages.
- model_timing: ModelTiming
The ModelTiming details used in the model.
- model_update_bounds: tuple[Quantity, Quantity]
Bounds on model update frequencies.
This class attribute defines two time intervals that define a lower and upper bound on the update frequency that can reasonably be used with a model. Models updated more often than the lower bound may fail to capture transient dynamics and models updated more slowly than the upper bound may fail to capture important temporal patterns.
- required_init_vars: tuple[tuple[str, tuple[str, ...]], ...]
Required variables for model initialisation.
This class property defines a set of variable names that must be present in the
Data
instance used to initialise an instance of this class. It is a tuple containing zero or more tuples, each providing a variable name and then a tuple of zero or more core axes that the variable must map onto.For example:
(('temperature', ('spatial', 'temporal')),)
- abstract update(time_index: int, **kwargs: Any) None
Function to update the model.
- Parameters:
time_index – The index representing the current time step in the data object.
- vars_updated: tuple[str, ...]
Variables that are updated by the model.
At the moment, this tuple is used to decide which variables to output from the
Data
object, i.e. every variable updated by a model used in the specific simulation. In future, this could also be used to prevent multiple models from updating the same variable and similar problems.