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

Update traits data structures #300

Merged
merged 6 commits into from
Sep 28, 2024
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
16 changes: 8 additions & 8 deletions pyrealm/demography/canopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ def _calculate_canopy(self, community: Community) -> None:
args=(
community.cohort_data["stem_height"],
community.cohort_data["crown_area"],
community.cohort_data["m"],
community.cohort_data["n"],
community.cohort_data["q_m"],
community.stem_traits.m,
community.stem_traits.n,
community.stem_traits.q_m,
community.cohort_data["canopy_z_max"],
community.cohort_data["n_individuals"],
target_area,
Expand All @@ -137,8 +137,8 @@ def _calculate_canopy(self, community: Community) -> None:
self.stem_relative_radius = calculate_relative_canopy_radius_at_z(
z=self.layer_heights,
stem_height=community.cohort_data["stem_height"],
m=community.cohort_data["m"],
n=community.cohort_data["n"],
m=community.stem_traits.m,
n=community.stem_traits.n,
validate=False,
)

Expand All @@ -148,7 +148,7 @@ def _calculate_canopy(self, community: Community) -> None:
q_z=self.stem_relative_radius,
crown_area=community.cohort_data["crown_area"],
stem_height=community.cohort_data["stem_height"],
q_m=community.cohort_data["q_m"],
q_m=community.stem_traits.q_m,
z_max=community.cohort_data["canopy_z_max"],
validate=False,
)
Expand All @@ -159,8 +159,8 @@ def _calculate_canopy(self, community: Community) -> None:
q_z=self.stem_relative_radius,
crown_area=community.cohort_data["crown_area"],
stem_height=community.cohort_data["stem_height"],
f_g=community.cohort_data["f_g"],
q_m=community.cohort_data["q_m"],
f_g=community.stem_traits.f_g,
q_m=community.stem_traits.q_m,
z_max=community.cohort_data["canopy_z_max"],
validate=False,
)
55 changes: 16 additions & 39 deletions pyrealm/demography/community.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
from pyrealm.core.utilities import check_input_shapes
from pyrealm.demography import canopy_functions
from pyrealm.demography import t_model_functions as t_model
from pyrealm.demography.flora import Flora
from pyrealm.demography.flora import Flora, StemTraits

if sys.version_info[:2] >= (3, 11):
import tomllib
Expand Down Expand Up @@ -355,6 +355,7 @@ class Community:

# Post init properties
number_of_cohorts: int = field(init=False)
stem_traits: StemTraits = field(init=False)
cohort_data: dict[str, NDArray] = field(init=False)

def __post_init__(
Expand Down Expand Up @@ -392,45 +393,21 @@ def __post_init__(
except ValueError:
raise ValueError("Cohort arrays are of unequal length")

# Check the initial PFT values are known
unknown_pfts = set(cohort_pft_names).difference(self.flora.keys())

if unknown_pfts:
raise ValueError(
f"Plant functional types unknown in flora: {','.join(unknown_pfts)}"
)

# Store as a dictionary
self.cohort_data: dict[str, NDArray] = {
"name": cohort_pft_names,
"dbh": cohort_dbh_values,
"n_individuals": cohort_n_individuals,
}

# Duplicate the pft trait data to match the cohort data and add to the cohort
# data dictionary.
self.cohort_data.update(self._unpack_pft_data(cohort_pft_names))
# Get the stem traits for the cohorts
self.stem_traits = self.flora.get_stem_traits(cohort_pft_names)

self.number_of_cohorts = len(cohort_pft_names)

# Populate the T model fields
self._calculate_t_model()

def _unpack_pft_data(
self, cohort_pft_names: NDArray[np.str_]
) -> dict[str, NDArray]:
"""Creates a dictionary of PFT data for a set of cohorts.

Args:
cohort_pft_names: The PFT name for each cohort
"""
# Get the indices for the cohort PFT names in the flora PFT data
pft_index = [self.flora.pft_indices[str(nm)] for nm in cohort_pft_names]

# Use that index to duplicate the PFT specific data into a per cohort entry for
# each of the PFT traits
return {k: v[pft_index] for k, v in self.flora.data.items()}

def _calculate_t_model(self) -> None:
"""Calculate T Model predictions across cohort data.

Expand All @@ -442,51 +419,51 @@ def _calculate_t_model(self) -> None:
# Add data to cohort dataframes capturing the T Model geometry
# - Classic T Model scaling
self.cohort_data["stem_height"] = t_model.calculate_heights(
h_max=self.cohort_data["h_max"],
a_hd=self.cohort_data["a_hd"],
h_max=self.stem_traits.h_max,
a_hd=self.stem_traits.a_hd,
dbh=self.cohort_data["dbh"],
)

self.cohort_data["crown_area"] = t_model.calculate_crown_areas(
ca_ratio=self.cohort_data["ca_ratio"],
a_hd=self.cohort_data["a_hd"],
ca_ratio=self.stem_traits.ca_ratio,
a_hd=self.stem_traits.a_hd,
dbh=self.cohort_data["dbh"],
stem_height=self.cohort_data["stem_height"],
)

self.cohort_data["crown_fraction"] = t_model.calculate_crown_fractions(
a_hd=self.cohort_data["a_hd"],
a_hd=self.stem_traits.a_hd,
dbh=self.cohort_data["dbh"],
stem_height=self.cohort_data["stem_height"],
)

self.cohort_data["stem_mass"] = t_model.calculate_stem_masses(
rho_s=self.cohort_data["rho_s"],
rho_s=self.stem_traits.rho_s,
dbh=self.cohort_data["dbh"],
stem_height=self.cohort_data["stem_height"],
)

self.cohort_data["foliage_mass"] = t_model.calculate_foliage_masses(
sla=self.cohort_data["sla"],
lai=self.cohort_data["lai"],
sla=self.stem_traits.sla,
lai=self.stem_traits.lai,
crown_area=self.cohort_data["crown_area"],
)

self.cohort_data["sapwood_mass"] = t_model.calculate_sapwood_masses(
rho_s=self.cohort_data["rho_s"],
ca_ratio=self.cohort_data["ca_ratio"],
rho_s=self.stem_traits.rho_s,
ca_ratio=self.stem_traits.ca_ratio,
stem_height=self.cohort_data["stem_height"],
crown_area=self.cohort_data["crown_area"],
crown_fraction=self.cohort_data["crown_fraction"],
)

# Canopy shape extension to T Model from PlantFATE
self.cohort_data["canopy_z_max"] = canopy_functions.calculate_canopy_z_max(
z_max_prop=self.cohort_data["z_max_prop"],
z_max_prop=self.stem_traits.z_max_prop,
stem_height=self.cohort_data["stem_height"],
)
self.cohort_data["canopy_r0"] = canopy_functions.calculate_canopy_r0(
q_m=self.cohort_data["q_m"],
q_m=self.stem_traits.q_m,
crown_area=self.cohort_data["crown_area"],
)

Expand Down
Loading
Loading