Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

666 repair model attribute typing and docstrings #692

Merged
merged 6 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/source/api/models/abiotic/abiotic_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ language_info:
:autosummary:
:members:
:exclude-members: model_name
:inherited-members:
```
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ language_info:
:autosummary:
:members:
:exclude-members: model_name
:inherited-members:
```
1 change: 1 addition & 0 deletions docs/source/api/models/animal/animal_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ language_info:
:autosummary:
:members:
:exclude-members: model_name, random
:inherited-members:
```
1 change: 1 addition & 0 deletions docs/source/api/models/hydrology/hydrology_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ language_info:
:autosummary:
:members:
:exclude-members: model_name
:inherited-members:
```
1 change: 1 addition & 0 deletions docs/source/api/models/litter/litter_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ language_info:
:autosummary:
:members:
:exclude-members: model_name
:inherited-members:
```
1 change: 1 addition & 0 deletions docs/source/api/models/plants/plants_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ language_info:
:autosummary:
:members:
:exclude-members: model_name
:inherited-members:
```

## The plants {mod}`~virtual_ecosystem.models.plants.constants` module
Expand Down
1 change: 1 addition & 0 deletions docs/source/api/models/soil/soil_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ language_info:
:autosummary:
:members:
:exclude-members: model_name
:inherited-members:
```
2 changes: 2 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ class MyReferenceStyle(AuthorYearReferenceStyle):
("py:class", "numpy.bool_"),
("py:class", "np.float32"),
("py:class", "np.datetime64"),
("py:class", "np.ndarray"),
("py:class", "np.timedelta64"),
("py:class", "timedelta64"),
("py:class", "InitVar"),
("py:class", "dataclasses.InitVar"),
("py:class", "Quantity"),
Expand Down
10 changes: 6 additions & 4 deletions virtual_ecosystem/core/base_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

* Creating a model instance (:class:`~virtual_ecosystem.core.base_model.BaseModel`).
* Setup a model instance (:meth:`~virtual_ecosystem.core.base_model.BaseModel._setup`).
This method should include any initialization logic including validating and
populating class attributes.
* Perform any spinup required to get a model state to equilibrate
(:meth:`~virtual_ecosystem.core.base_model.BaseModel.spinup`).
* Update the model from one time step to the next
Expand Down Expand Up @@ -56,8 +58,10 @@
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
Each model subclass should include an ``__init__`` method that defines all
model specific attributes. The ``__init__`` should not contain any further
initialization logic, which should happen in the subclass ``_setup`` method instead.
The ``__init__`` method **must** call the
:meth:`BaseModel.__init__() <virtual_ecosystem.core.base_model.BaseModel.__init__>`
method, as this populates core shared model attrributes - see the linked method
description for details.
Expand Down Expand Up @@ -594,8 +598,6 @@ class ExampleModel(
defined
TypeError: If model_name is not a string
"""
if cls.__init__ != BaseModel.__init__:
raise NotImplementedError("Model subclasses cannot override __init__.")

if cls.update != BaseModel.update:
raise NotImplementedError(
Expand Down
26 changes: 22 additions & 4 deletions virtual_ecosystem/models/abiotic/abiotic_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,26 @@ class AbioticModel(
model_constants: Set of constants for the abiotic model.
"""

def __init__(
self,
data: Data,
core_components: CoreComponents,
static: bool = False,
**kwargs: Any,
):
"""Abiotic init function.

The init function is used only to define class attributes. Any logic should be
handeled in :fun:`~virtual_ecosystem.abiotic.abiotic_model._setup`.
"""

super().__init__(data, core_components, static, **kwargs)

self.model_constants: AbioticConsts
"""Set of constants for the abiotic model."""
self.simple_constants: AbioticSimpleConsts
"""Set of constants for simple abiotic model."""

@classmethod
def from_config(
cls, data: Data, core_components: CoreComponents, config: Config
Expand Down Expand Up @@ -193,10 +213,8 @@ def _setup(
**kwargs: Further arguments to the setup method.
"""

self.model_constants: AbioticConsts = model_constants
"""Set of constants for the abiotic model."""
self.simple_constants: AbioticSimpleConsts = AbioticSimpleConsts()
"""Set of constants for simple abiotic model."""
self.model_constants = model_constants
self.simple_constants = AbioticSimpleConsts()

# create soil temperature array
self.data["soil_temperature"] = self.layer_structure.from_template()
Expand Down
24 changes: 20 additions & 4 deletions virtual_ecosystem/models/abiotic_simple/abiotic_simple_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,26 @@ class AbioticSimpleModel(
model_constants: Set of constants for the abiotic_simple model.
"""

model_constants: AbioticSimpleConsts
"""Set of constants for the abiotic simple model"""
bounds: AbioticSimpleBounds
"""Upper and lower bounds for abiotic variables."""
def __init__(
self,
data: Data,
core_components: CoreComponents,
static: bool = False,
**kwargs: Any,
):
"""Abiotic simple init.

The init function is used only to define class attributes. Any logic should be
handeled in
:fun:`~virtual_ecosystem.abiotic_simple.abiotic_simple_model._setup`.
"""

super().__init__(data, core_components, static, **kwargs)

self.model_constants: AbioticSimpleConsts
"""Set of constants for the abiotic simple model"""
self.bounds: AbioticSimpleBounds
"""Upper and lower bounds for abiotic variables."""

@classmethod
def from_config(
Expand Down
58 changes: 39 additions & 19 deletions virtual_ecosystem/models/animal/animal_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,39 @@ class AnimalModel(
model_constants: Set of constants for the animal model.
"""

communities: dict[int, list[AnimalCohort]]
"""Animal communities with grid cell IDs and lists of AnimalCohorts."""
def __init__(
self,
data: Data,
core_components: CoreComponents,
static: bool = False,
**kwargs: Any,
):
"""Animal init function.

The init function is used only to define class attributes. Any logic should be
handeled in :fun:`~virtual_ecosystem.animal.animal_model._setup`.
"""

cohorts: dict[uuid.UUID, AnimalCohort]
"""A dictionary of all animal cohorts and their unique ids."""
super().__init__(data, core_components, static, **kwargs)

self.communities: dict[int, list[AnimalCohort]]
"""Animal communities with grid cell IDs and lists of AnimalCohorts."""
self.cohorts: dict[uuid.UUID, AnimalCohort]
"""A dictionary of all animal cohorts and their unique ids."""
self.update_interval_timedelta: timedelta64
"""Convert pint update_interval to timedelta64 once during initialization."""
self.functional_groups: list[FunctionalGroup]
"""List of functional groups in the model."""
self.model_constants: AnimalConsts
"""Animal constants."""
self.plant_resources: dict[int, list[Resource]]
"""The plant resource pools in the model with associated grid cell ids."""
self.excrement_pools: dict[int, list[ExcrementPool]]
"""The excrement pools in the model with associated grid cell ids."""
self.carcass_pools: dict[int, list[CarcassPool]]
"""The carcass pools in the model with associated grid cell ids."""
self.leaf_waste_pools: dict[int, HerbivoryWaste]
"""A pool for leaves removed by herbivory but not actually consumed."""

def _setup_grid_neighbours(self) -> None:
"""Set up grid neighbours for the model.
Expand Down Expand Up @@ -231,22 +259,19 @@ def _setup(
self._setup_grid_neighbours()
"""Determine grid square adjacency."""
self.functional_groups = functional_groups
"""List of functional groups in the model."""
self.model_constants = model_constants
"""Animal constants."""
self.plant_resources: dict[int, list[Resource]] = {
self.plant_resources = {
cell_id: [
PlantResources(
data=self.data, cell_id=cell_id, constants=self.model_constants
)
]
for cell_id in self.data.grid.cell_id
}
"""The plant resource pools in the model with associated grid cell ids."""
# TODO - In future, need to take in data on average size of excrement and
# carcasses pools and their stoichiometries for the initial scavengeable pool
# parameterisations
self.excrement_pools: dict[int, list[ExcrementPool]] = {
self.excrement_pools = {
cell_id: [
ExcrementPool(
scavengeable_carbon=1e-3,
Expand All @@ -259,8 +284,7 @@ def _setup(
]
for cell_id in self.data.grid.cell_id
}
"""The excrement pools in the model with associated grid cell ids."""
self.carcass_pools: dict[int, list[CarcassPool]] = {
self.carcass_pools = {
cell_id: [
CarcassPool(
scavengeable_carbon=1e-3,
Expand All @@ -273,17 +297,13 @@ def _setup(
]
for cell_id in self.data.grid.cell_id
}
"""The carcass pools in the model with associated grid cell ids."""
self.leaf_waste_pools: dict[int, HerbivoryWaste] = {

self.leaf_waste_pools = {
cell_id: HerbivoryWaste(plant_matter_type="leaf")
for cell_id in self.data.grid.cell_id
}
"""A pool for leaves removed by herbivory but not actually consumed."""
self.cohorts: dict[uuid.UUID, AnimalCohort] = {}
"""A dictionary of all animal cohorts and their unique ids."""
self.communities: dict[int, list[AnimalCohort]] = {
cell_id: list() for cell_id in self.data.grid.cell_id
}
self.cohorts = {}
self.communities = {cell_id: list() for cell_id in self.data.grid.cell_id}

self._initialize_communities(functional_groups)
"""Create the dictionary of animal communities and populate each community with
Expand Down
44 changes: 33 additions & 11 deletions virtual_ecosystem/models/hydrology/hydrology_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,35 @@ class HydrologyModel(
or out of [0, 1] bounds.
"""

def __init__(
self,
data: Data,
core_components: CoreComponents,
static: bool = False,
**kwargs: Any,
):
"""Hydrology init function.

The init function is used only to define class attributes. Any logic should be
handeled in :fun:`~virtual_ecosystem.hydrology.hydrology_model._setup`.
"""

super().__init__(data, core_components, static, **kwargs)

self.initial_soil_moisture: float
"""Initial volumetric relative water content [unitless] for all layers and grid
cells identical."""
self.initial_groundwater_saturation: float
"""Initial level of groundwater saturation for all layers identical."""
self.model_constants: HydroConsts
"""Set of constants for the hydrology model"""
self.drainage_map: dict
"""Upstream neighbours for the calculation of accumulated horizontal flow."""
self.soil_layer_thickness_mm: np.ndarray
"""Soil layer thickness in mm."""
self.surface_layer_index: int
"""Surface layer index."""

@classmethod
def from_config(
cls, data: Data, core_components: CoreComponents, config: Config
Expand Down Expand Up @@ -220,20 +249,15 @@ def _setup(
LOGGER.error(to_raise)
raise to_raise

self.initial_soil_moisture: float = initial_soil_moisture
"""Initial volumetric relative water content [unitless] for all layers and grid
cells identical."""
self.initial_groundwater_saturation: float = initial_groundwater_saturation
"""Initial level of groundwater saturation for all layers identical."""
self.model_constants: HydroConsts = model_constants
"""Set of constants for the hydrology model"""
self.initial_soil_moisture = initial_soil_moisture
self.initial_groundwater_saturation = initial_groundwater_saturation
self.model_constants = model_constants
self.grid.set_neighbours(distance=sqrt(self.grid.cell_area))
"""Set neighbours."""
self.drainage_map = above_ground.calculate_drainage_map(
grid=self.data.grid,
elevation=np.array(self.data["elevation"]),
)
"""Upstream neighbours for the calculation of accumulated horizontal flow."""

# Calculate layer thickness for soil moisture unit conversion and set structures
# and tile across grid cells
Expand All @@ -244,12 +268,10 @@ def _setup(
)[:, None],
self.grid.n_cells,
)
"""Soil layer thickness in mm."""

# Select aboveground layer for surface evaporation calculation
# TODO this needs to be replaced with 2m above ground value
self.surface_layer_index: int = self.layer_structure.index_surface_scalar
"""Surface layer index."""
self.surface_layer_index = self.layer_structure.index_surface_scalar

# Calculate initial soil moisture, [mm]
self.data["soil_moisture"] = hydrology_tools.initialise_soil_moisture_mm(
Expand Down
23 changes: 20 additions & 3 deletions virtual_ecosystem/models/litter/litter_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,26 @@ class LitterModel(
model_constants: Set of constants for the litter model.
"""

def __init__(
self,
data: Data,
core_components: CoreComponents,
static: bool = False,
**kwargs: Any,
):
"""Litter init function.

The init function is used only to define class attributes. Any logic should be
handeled in :fun:`~virtual_ecosystem.litter.litter_model._setup`.
"""

super().__init__(data, core_components, static, **kwargs)

self.litter_chemistry: LitterChemistry
"""Litter chemistry object for tracking of litter pool chemistries."""
self.model_constants: LitterConsts
"""Set of constants for the litter model."""

@classmethod
def from_config(
cls, data: Data, core_components: CoreComponents, config: Config
Expand Down Expand Up @@ -267,10 +287,7 @@ def _setup(
raise to_raise

self.litter_chemistry = LitterChemistry(self.data, constants=model_constants)
"""Litter chemistry object for tracking of litter pool chemistries."""

self.model_constants = model_constants
"""Set of constants for the litter model."""

def spinup(self) -> None:
"""Placeholder function to spin up the litter model."""
Expand Down
Loading
Loading