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

Updated TODOs across animal module code. #475

Merged
merged 2 commits into from
Jul 1, 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
41 changes: 35 additions & 6 deletions virtual_ecosystem/models/animal/animal_cohorts.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ def metabolize(self, temperature: float, dt: timedelta64) -> float:
This method will later drive the processing of carbon and nitrogen metabolic
products.

TODO: Update with stoichiometry

Args:
temperature: Current air temperature (K)
dt: Number of days over which the metabolic costs should be calculated.
Expand Down Expand Up @@ -134,6 +136,8 @@ def excrete(self, excreta_mass: float, excrement_pool: DecayPool) -> None:
current metabolic wastes are carbonaceous and so all this does is provide a link
joining metabolism to a soil pool for later use.

TODO: Update with stoichiometry

Args:
excreta_mass: The total mass of carbonaceous wastes excreted by the cohort.
excrement_pool: The pool of wastes to which the excreted nitrogenous wastes
Expand All @@ -152,6 +156,8 @@ def respire(self, excreta_mass: float) -> float:
excreta mass for updating data["total_animal_respiration"] in metabolize
community.

TODO: Update with stoichiometry

Args:
excreta_mass: The total mass of carbonaceous wastes excreted by the cohort.

Expand All @@ -174,6 +180,7 @@ def defecate(

TODO: Rework after update litter pools for mass
TODO: update for current conversion efficiency
TODO: Update with stoichiometry

Args:
excrement_pool: The local ExcrementSoil pool in which waste is deposited.
Expand Down Expand Up @@ -310,6 +317,8 @@ def calculate_alpha(self) -> float:
which an individual herbivore searches its environment, factoring in the
herbivore's current mass.

TODO: update name

Returns:
A float representing the search efficiency rate in [ha/(day*g)].
"""
Expand All @@ -325,6 +334,8 @@ def calculate_potential_consumed_biomass(
efficiency (alpha),the fraction of the total plant stock available to the cohort
(phi), and the biomass of the target plant.

TODO: give A_cell a grid size reference

Args:
target_plant: The plant resource being targeted by the herbivore cohort.
alpha: The search efficiency rate of the herbivore cohort.
Expand All @@ -347,6 +358,8 @@ def calculate_total_handling_time_for_herbivory(
list, incorporating the search efficiency and other scaling factors to compute
the total handling time required by the cohort.

TODO: give A_cell a grid size reference.

Args:
plant_list: A sequence of plant resources available for consumption by the
cohort.
Expand Down Expand Up @@ -378,6 +391,8 @@ def F_i_k(self, plant_list: Sequence[Resource], target_plant: Resource) -> float
plant resources to determine the rate at which the target plant is consumed by
the cohort.

TODO: update name

Args:
plant_list: A sequence of plant resources available for consumption by the
cohort.
Expand All @@ -400,6 +415,8 @@ def F_i_k(self, plant_list: Sequence[Resource], target_plant: Resource) -> float
def calculate_theta_opt_i(self) -> float:
"""Calculate the optimal predation param based on predator-prey mass ratio.

TODO: update name

Returns:
Float value of the optimal predation parameter for use in calculating the
probability of a predation event being successful.
Expand Down Expand Up @@ -447,6 +464,8 @@ def calculate_potential_prey_consumed(
) -> float:
"""Calculate the potential number of prey consumed.

TODO: give A_cell a grid size reference

Args:
alpha: the predation search rate
theta_i_j: The cumulative density of organisms with a mass lying within the
Expand Down Expand Up @@ -507,6 +526,8 @@ def calculate_consumed_mass_predation(
the target cohort is consumed, and then calculates the actual mass to be
consumed based on this rate and other model parameters.

TODO: Replace delta_t with time step reference

Args:
animal_list: A sequence of animal cohorts that can be consumed by the
predator.
Expand All @@ -516,7 +537,7 @@ def calculate_consumed_mass_predation(
The mass to be consumed from the target cohort by the predator (in kg).
"""
F = self.F_i_j_individual(animal_list, target_cohort)
delta_t = 30.0 # days, TODO: Replace with actual reference or model parameter
delta_t = 30.0 # days

# Calculate the consumed mass based on Mad. formula for delta_mass_predation
consumed_mass = (
Expand Down Expand Up @@ -573,6 +594,8 @@ def calculate_consumed_mass_herbivory(
plant is consumed, and then calculates the actual mass to be consumed based on
this rate and other model parameters.

TODO: Replace delta_t with actual time step reference

Args:
plant_list: A sequence of plant resources that can be consumed by the
herbivore.
Expand All @@ -582,7 +605,7 @@ def calculate_consumed_mass_herbivory(
The mass to be consumed from the target plant by the herbivore (in kg).
"""
F = self.F_i_k(plant_list, target_plant) # Adjusting this call as necessary
delta_t = 30.0 # days, TODO: Replace with actual reference or model parameter
delta_t = 30.0 # days

consumed_mass = target_plant.mass_current * (
1 - exp(-(F * delta_t * self.constants.tau_f * self.constants.sigma_f_t))
Expand All @@ -594,6 +617,8 @@ def delta_mass_herbivory(
) -> float:
"""This method handles mass assimilation from herbivory.

TODO: update name

Args:
plant_list: A sequence of plant resources available for herbivory.
excrement_pool: A pool representing the excrement in the grid cell.
Expand Down Expand Up @@ -661,7 +686,8 @@ def theta_i_j(self, animal_list: Sequence[AnimalCohort]) -> float:
Madingley

TODO: current format makes no sense, dig up the details in the supp
TODO: update A_cell with real reference
TODO: update A_cell with real reference to grid zie
TODO: update name

Args:
animal_list: A sequence of animal cohorts that can be consumed by the
Expand All @@ -685,7 +711,7 @@ def eat(self, mass_consumed: float) -> None:
It assumes the `mass_consumed` has already been calculated and processed
through `get_eaten`.

TODO: nonreproductive functional groups should not store any reproductive mass
TODO: non-reproductive functional groups should not store any reproductive mass

Args:
mass_consumed: The mass consumed by this consumer, calculated externally.
Expand Down Expand Up @@ -727,6 +753,7 @@ def migrate_juvenile_probability(self) -> float:
"""The probability that a juvenile cohort will migrate to a new grid cell.

TODO: This does not hold for diagonal moves or non-square grids.
TODO: update A_cell to grid size reference

Following Madingley's assumption that the probability of juvenile dispersal is
equal to the proportion of the cohort individuals that would arrive in the
Expand All @@ -752,7 +779,7 @@ def migrate_juvenile_probability(self) -> float:

"""

A_cell = 1.0 # TODO: update this to actual grid reference
A_cell = 1.0 # temporary
grid_side = sqrt(A_cell)
velocity = sf.juvenile_dispersal_speed(
self.mass_current,
Expand All @@ -771,6 +798,9 @@ def inflict_non_predation_mortality(
) -> None:
"""Inflict combined background, senescence, and starvation mortalities.

TODO: Review logic of mass_max = adult_mass
TODO: Review the use of ceil in number_dead, it fails for large animals.

Args:
dt: The time passed in the timestep (days).
carcass_pool: The local carcass pool to which dead individuals go.
Expand Down Expand Up @@ -807,7 +837,6 @@ def inflict_non_predation_mortality(
u_t = u_bg + u_se + u_st

# Calculate the total number of dead individuals
# TODO: the use of ceil here might have unintended outcomes, keep an eye on it
number_dead = ceil(pop_size * (1 - exp(-u_t * dt)))

# Remove the dead individuals from the cohort
Expand Down
11 changes: 7 additions & 4 deletions virtual_ecosystem/models/animal/animal_communities.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ def populate_community(self) -> None:
Currently, the number of individuals in a cohort is handled using Damuth's Law,
which only holds for mammals.

TODO: Move populate_community to following Madingley instead of damuth

"""
for functional_group in self.functional_groups:
individuals = damuths_law(
Expand All @@ -121,8 +123,8 @@ def migrate(self, migrant: AnimalCohort, destination: AnimalCommunity) -> None:
This function should take a cohort and a destination community and then pop the
cohort from this community to the destination.

Travel distance is not currently a function of body-size or locomotion for
starvation dispersal.
TODO: travel distance should be a function of body-size or locomotion once
multi-grid occupancy is integrated.

Args:
migrant: The AnimalCohort moving between AnimalCommunities.
Expand Down Expand Up @@ -282,8 +284,7 @@ def collect_prey(self, consumer_cohort: AnimalCohort) -> list[AnimalCohort]:
"""Collect suitable prey for a given consumer cohort.

This is a helper function for forage_community to isolate the prey selection
functionality. It was already getting confusing and it will get much more so
as the Animal Module develops.
functionality.

Args:
consumer_cohort: The AnimalCohort for which a prey list is being collected
Expand Down Expand Up @@ -327,6 +328,8 @@ def metabolize_community(self, temperature: float, dt: timedelta64) -> None:
Excretion wastes are handled cohort by cohort because they will need to be
spatially explicit with multi-grid occupancy.

TODO: Rework with stoichiometry

Args:
temperature: Current air temperature (K).
dt: Number of days over which the metabolic costs should be calculated.
Expand Down
5 changes: 0 additions & 5 deletions virtual_ecosystem/models/animal/animal_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,17 +224,12 @@ def setup(self) -> None:
# initialize values
self.update_population_densities()

# Debugging output
# print("Data variables after setup:", list(self.data.data.data_vars))

def spinup(self) -> None:
"""Placeholder function to spin up the animal model."""

def update(self, time_index: int, **kwargs: Any) -> None:
"""Function to step the animal model through time.

Temporary solution.

This method sets the order of operations for the animal module. In nature, these
events would be simultaneous. The ordering within the method is less a question
of the science and more a question of computational logic and stability.
Expand Down
11 changes: 5 additions & 6 deletions virtual_ecosystem/models/animal/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@
constants" (fitting relationships taken from the literature) required by the broader
:mod:`~virtual_ecosystem.models.animal` module

The near-future intention is to rework the relationship between these constants and the
AnimalCohort objects in which they are used such that there is a FunctionalType class
in-between them. This class will hold the specific scaling, rate, and conversion
parameters required for determining the function of a specific AnimalCohort and will
avoid frequent searches through this constants file for values.
""" # noqa: D205, D415

from dataclasses import dataclass, field
Expand All @@ -21,7 +16,11 @@

@dataclass(frozen=True)
class AnimalConsts(ConstantsDataclass):
"""Dataclass to store all constants related to metabolic rates."""
"""Dataclass to store all constants related to metabolic rates.

TODO: Remove unused constants.

"""

metabolic_rate_terms: dict[MetabolicType, dict[str, tuple[float, float]]] = field(
default_factory=lambda: {
Expand Down
13 changes: 7 additions & 6 deletions virtual_ecosystem/models/animal/functional_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ def __init__(
adult_mass: float,
constants: AnimalConsts = AnimalConsts(),
) -> None:
"""The constructor for the FunctionalGroup class."""
"""The constructor for the FunctionalGroup class.

TODO: Remove unused attributes.

"""

self.name = name
"""The name of the functional group."""
Expand Down Expand Up @@ -103,15 +107,12 @@ def import_functional_groups(
) -> list[FunctionalGroup]:
"""The function to import pre-defined functional groups.

This function is a first-pass of how we might import pre-defined functional groups.
The current expected csv structure is:
- ["name", "taxa", "diet", "metabolic_type", "birth_mass", "adult_mass"]
This function is a first-pass of how we might import pre-defined functional groups,
the specific options of which can be found in functional_group.py.
This allows a user to set out a basic outline of functional groups that accept our
definitions of parameters and scaling relationships based on those traits.

We will need a structure for users changing those underlying definitions but that
can be constructed later.
TODO: A structure for user-selection of which traits to employ.

Args:
fg_csv_file: The location of the csv file holding the functional group
Expand Down
Loading
Loading