Source code for virtual_ecosystem.models.plants.communities
"""The :mod:`~virtual_ecosystem.models.plants.communities` submodule provides the
:class:`~virtual_ecosystem.models.plants.communities.PlantCommunities` class. This
provides a dictionary mapping each grid cell id to the plant community growing within
the cell.
There is a one-to-one mapping of grid cells to plant communities, with the individual
community for a grid cell being represented as a
:class:`pyrealm.demography.community.Community` instance. The community is then made up
of size-structured plant cohorts using :class:`pyrealm.demography.community.Cohorts`
instances.
""" # noqa: D205
from collections.abc import Mapping
import pandas as pd
from pyrealm.demography.community import Cohorts, Community
from pyrealm.demography.flora import Flora
from virtual_ecosystem.core.grid import Grid
from virtual_ecosystem.core.logger import LOGGER
[docs]
class PlantCommunities(dict, Mapping[int, Community]):
"""Records the plant community with each grid cell across a simulation.
A ``PlantCommunities`` instance provides a dictionary mapping each grid cell onto a
single :class:`pyrealm.demography.community.Community` instance, containing a set of
:class:`pyrealm.demography.community.Cohorts` instances.
A class instance must be initialised using :class:`pandas.DataFrame` instance
containing the required cohort data. Each row in the data frame defines a cohort
located in one of the cells, so required data frame fields are:
* the cell id in which the cohort is located (``plant_cohorts_cell_id``),
* the plant functional type of the cohort (``plant_cohorts_pft``),
* the number of individuals within the cohort (``plant_cohorts_n``), and
* the diameter at breast height of the individuals (``plant_cohorts_dbh``).
The data are validated and then compiled into lists of cohorts keyed by grid cell
id. The class is a subclass of dictionary, so has the ``__get_item__`` method,
allowing access to the community for a given cell id using ``plants_inst[cell_id]``.
.. todo::
This function will need updating if the grid cell area implementation is changed
to allow variable cell area .
Args:
cohort_data: A data frame containing the initial cohort data.
flora: A flora containing the plant functional types used in the cohorts.
grid: The grid for the simulation, providing the area of the grid cells and the
expected cell ids.
"""
def __init__(self, cohort_data: pd.DataFrame, flora: Flora, grid: Grid):
"""Initialise the community object.
Args:
cohort_data: A pandas dataframe of cohort data.
flora: A flora object.
grid: A grid object
"""
# Validate the data being used to generate the Plants object form a dataframe
cohort_data_vars = {
"plant_cohorts_n",
"plant_cohorts_pft",
"plant_cohorts_cell_id",
"plant_cohorts_dbh",
}
missing_vars = cohort_data_vars.difference(cohort_data.columns)
if missing_vars:
msg = (
f"Cannot initialise plant communities from cohort data. Missing "
f"variables: {', '.join(sorted(list(missing_vars)))}"
)
LOGGER.critical(msg)
raise ValueError(msg)
# Split data into cell ids:
cohort_data_grouped = cohort_data.groupby("plant_cohorts_cell_id")
# Check the grid cell ids are known
bad_cids = set(cohort_data_grouped.groups.keys()).difference(grid.cell_id)
if bad_cids:
msg = (
"Plant cohort data includes cell ids not in grid definition: "
+ ",".join([str(c) for c in bad_cids])
)
LOGGER.critical(msg)
raise ValueError(msg)
# Check the PFTs are known
bad_pfts = set(cohort_data["plant_cohorts_pft"]).difference(flora.name.tolist())
if bad_pfts:
msg = "Plant cohort data includes PFT names not in flora: " + ",".join(
bad_pfts
)
LOGGER.critical(msg)
raise ValueError(msg)
# Now build the pyrealm community objects for each cell
for cell_id, cell_cohort_data in cohort_data_grouped:
self[cell_id] = Community(
cell_id=cell_id,
cell_area=grid.cell_area, # Note this is constant
flora=flora,
cohorts=Cohorts(
n_individuals=cell_cohort_data["plant_cohorts_n"].to_numpy(),
pft_names=cell_cohort_data["plant_cohorts_pft"].to_numpy(),
dbh_values=cell_cohort_data["plant_cohorts_dbh"].to_numpy(),
),
)
LOGGER.info("Plant cohort data loaded")