Skip to content

Commit

Permalink
Merge pull request #482 from ImperialCollegeLondon/474-animal-remove-…
Browse files Browse the repository at this point in the history
…unused-functions-and-constants

Removed a handful of now defunct constants and methods.
  • Loading branch information
TaranRallings authored Jul 3, 2024
2 parents 48e4b0a + c92e94b commit 038de10
Show file tree
Hide file tree
Showing 6 changed files with 0 additions and 280 deletions.
114 changes: 0 additions & 114 deletions tests/models/animals/test_scaling_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,78 +89,6 @@ def test_metabolic_rate(mass, temperature, terms, metabolic_type, met_rate):
assert testing_rate == pytest.approx(met_rate, rel=1e-6)


@pytest.mark.parametrize(
"mass, muscle, terms",
[
pytest.param(0.0, 0.0, (1.0, 0.38), id="zero_mass"),
pytest.param(1.0, 380.0, (1.0, 0.38), id="small_mass"),
pytest.param(1000.0, 380000.0, (1.0, 0.38), id="large_mass"),
],
)
def test_muscle_mass_scaling(mass, muscle, terms):
"""Testing muscle mass scaling for various body-masses."""

from virtual_ecosystem.models.animal.scaling_functions import muscle_mass_scaling

gains = muscle_mass_scaling(mass, terms)
assert gains == pytest.approx(muscle, rel=1e-6)


@pytest.mark.parametrize(
"mass, fat, terms",
[
pytest.param(0.0, 0.0, (1.19, 0.02), id="zero_mass"),
pytest.param(1.0, 74.307045, (1.19, 0.02), id="low_mass"),
pytest.param(1000.0, 276076.852920, (1.19, 0.02), id="large_mass"),
],
)
def test_fat_mass_scaling(mass, fat, terms):
"""Testing fat mass scaling for various body-masses."""

from virtual_ecosystem.models.animal.scaling_functions import fat_mass_scaling

gains = fat_mass_scaling(mass, terms)
assert gains == pytest.approx(fat, rel=1e-6)


@pytest.mark.parametrize(
"mass, energy, muscle_terms, fat_terms",
[
pytest.param(0.0, 0.0, (1.0, 0.38), (1.19, 0.02), id="zerp_mass"),
pytest.param(1.0, 3180149.320736, (1.0, 0.38), (1.19, 0.02), id="low_mass"),
pytest.param(
1000.0, 4592537970.444037, (1.0, 0.38), (1.19, 0.02), id="high_mass"
),
],
)
def test_energetic_reserve_scaling(mass, energy, muscle_terms, fat_terms):
"""Testing energetic reserve scaling for various body-masses."""

from virtual_ecosystem.models.animal.scaling_functions import (
energetic_reserve_scaling,
)

gains = energetic_reserve_scaling(mass, muscle_terms, fat_terms)
assert gains == pytest.approx(energy, rel=1e-6)


@pytest.mark.parametrize(
"mass, intake_rate, terms",
[
pytest.param(0.0, 0.0, (0.71, 0.63), id="zero_mass"),
pytest.param(1.0, 0.3024, (0.71, 0.63), id="low_mass"),
pytest.param(1000.0, 40.792637, (0.71, 0.63), id="high_mass"),
],
)
def test_intake_rate_scaling(mass, intake_rate, terms):
"""Testing intake rate scaling for various body-masses."""

from virtual_ecosystem.models.animal.scaling_functions import intake_rate_scaling

test_rate = intake_rate_scaling(mass, terms)
assert test_rate == pytest.approx(intake_rate, rel=1e-6)


def test_herbivore_prey_group_selection():
"""Test for herbivore diet type selection."""
from virtual_ecosystem.models.animal.scaling_functions import (
Expand Down Expand Up @@ -214,48 +142,6 @@ def test_prey_group_selection_mass_and_terms_impact():
assert result_default == result_diff_mass == result_diff_terms


@pytest.mark.parametrize(
"mass, terms, expected, error_type",
[
pytest.param(1.0, (0.25, 0.05), 0.2055623, None, id="low_mass_valid"),
pytest.param(1000.0, (0.01, 0.1), 0.1018162, None, id="high_mass_valid"),
pytest.param(
0.0,
(0.71, 0.63),
None,
ZeroDivisionError,
id="zero_mass_error",
),
pytest.param(
-1.0,
(0.71, 0.63),
None,
TypeError,
id="negative_mass_error",
),
pytest.param(
1.0,
(0.71,),
None,
IndexError,
id="invalid_terms_error",
),
],
)
def test_natural_mortality_scaling(mass, terms, expected, error_type):
"""Testing natural mortality scaling for various body-masses."""
from virtual_ecosystem.models.animal.scaling_functions import (
natural_mortality_scaling,
)

if error_type:
with pytest.raises(error_type):
natural_mortality_scaling(mass, terms)
else:
result = natural_mortality_scaling(mass, terms)
assert result == pytest.approx(expected, rel=1e-6)


@pytest.mark.parametrize(
"input_value, expected_output",
[
Expand Down
6 changes: 0 additions & 6 deletions virtual_ecosystem/models/animal/animal_cohorts.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,6 @@ def __init__(
"""The amount of time [days] since reaching adult body-mass."""
self.reproductive_mass: float = 0.0
"""The pool of biomass from which the material of reproduction is drawn."""

self.intake_rate: float = sf.intake_rate_scaling(
self.functional_group.adult_mass, self.functional_group.intake_rate_terms
)
"""The individual rate of plant mass consumption over an 8hr foraging day
[kg/day]."""
self.prey_groups = sf.prey_group_selection(
self.functional_group.diet,
self.functional_group.adult_mass,
Expand Down
32 changes: 0 additions & 32 deletions virtual_ecosystem/models/animal/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,30 +53,6 @@ class AnimalConsts(ConstantsDataclass):
}
)

fat_mass_terms: dict[TaxaType, tuple[float, float]] = field(
default_factory=lambda: {
TaxaType.MAMMAL: (1.19, 0.02), # Scaling of mammalian herbivore fat mass
TaxaType.BIRD: (1.19, 0.05), # Toy Values
TaxaType.INSECT: (1.19, 0.05), # Toy Values
}
)

muscle_mass_terms: dict[TaxaType, tuple[float, float]] = field(
default_factory=lambda: {
TaxaType.MAMMAL: (1.0, 0.38), # Scaling of mammalian herbivore muscle mass
TaxaType.BIRD: (1.0, 0.40), # Toy Values
TaxaType.INSECT: (1.0, 0.40), # Toy Values
}
)

intake_rate_terms: dict[TaxaType, tuple[float, float]] = field(
default_factory=lambda: {
TaxaType.MAMMAL: (0.71, 0.63), # Mammalian maximum intake rate
TaxaType.BIRD: (0.7, 0.50), # Toy Values
TaxaType.INSECT: (0.7, 0.50), # Toy Values
}
)

energy_density: dict[str, float] = field(
default_factory=lambda: {
"meat": 7000.0, # Energy of mammal meat [J/g]
Expand Down Expand Up @@ -110,14 +86,6 @@ class AnimalConsts(ConstantsDataclass):
}
)

longevity_scaling_terms: dict[TaxaType, tuple[float, float]] = field(
default_factory=lambda: {
TaxaType.MAMMAL: (0.25, 0.02), # Toy values
TaxaType.BIRD: (0.25, 0.05), # Toy values
TaxaType.INSECT: (0.25, 0.05), # Toy values
}
)

birth_mass_threshold: float = 1.5 # Threshold for reproduction
flow_to_reproductive_mass_threshold: float = (
1.0 # Threshold of trophic flow to reproductive mass
Expand Down
8 changes: 0 additions & 8 deletions virtual_ecosystem/models/animal/functional_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,6 @@ def __init__(
"""The coefficient and exponent of metabolic rate."""
self.damuths_law_terms = self.constants.damuths_law_terms[self.taxa][self.diet]
"""The coefficient and exponent of damuth's law for population density."""
self.muscle_mass_terms = self.constants.muscle_mass_terms[self.taxa]
"""The coefficient and exponent of muscle mass allometry."""
self.fat_mass_terms = self.constants.fat_mass_terms[self.taxa]
"""The coefficient and exponent of fat mass allometry."""
self.intake_rate_terms = self.constants.intake_rate_terms[self.taxa]
"""The coefficient and exponent of intake allometry."""
self.conversion_efficiency = self.constants.conversion_efficiency[self.diet]
"""The conversion efficiency of the functional group based on diet."""
self.mechanical_efficiency = self.constants.mechanical_efficiency[self.diet]
Expand All @@ -98,8 +92,6 @@ def __init__(
self.taxa
]
"""The predator-prey mass ratio scaling relationship."""
self.longevity_scaling = self.constants.longevity_scaling_terms[self.taxa]
"""The coefficient and exponent for lifespan allometry."""


def import_functional_groups(
Expand Down
1 change: 0 additions & 1 deletion virtual_ecosystem/models/animal/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
class Consumer(Protocol):
"""This is the protocol for defining consumers (currently just AnimalCohort)."""

intake_rate: float
functional_group: FunctionalGroup
individuals: int

Expand Down
119 changes: 0 additions & 119 deletions virtual_ecosystem/models/animal/scaling_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,94 +94,6 @@ def metabolic_rate(
raise ValueError("Invalid metabolic type: {metabolic_type}")


def muscle_mass_scaling(mass: float, terms: tuple) -> float:
"""The function to set the amount of muscle mass on individual in an AnimalCohort.
Currently, this scaling relationship is only accurate for terrestrial mammals.
This will later be updated for additional functional types.
TODO: Remove if unused.
Args:
mass: The body-mass [kg] of an AnimalCohort.
terms: The tuple of muscle scaling terms used.
Returns:
The mass [g] of muscle on an individual of the animal cohort.
"""

return terms[1] * (mass * 1000) ** terms[0]


def fat_mass_scaling(mass: float, terms: tuple) -> float:
"""The function to set the amount of fat mass on individual in an AnimalCohort.
Currently, this scaling relationship is only accurate for terrestrial mammals.
This will later be updated for additional functional types.
TODO: Remove if unused.
Args:
mass: The body-mass [kg] of an AnimalCohort.
terms: The tuple of fat scaling terms used.
Returns:
The mass [g] of fat on an individual of the animal cohort.
"""

return terms[1] * (mass * 1000) ** terms[0]


def energetic_reserve_scaling(
mass: float, muscle_terms: tuple, fat_terms: tuple
) -> float:
"""The function to set the energetic reserve of an individual in an AnimalCohort.
Currently, this scaling relationship is only accurate for terrestrial mammals.
This will later be updated for additional functional types.
TODO: Remove if unused.
Args:
mass: The body-mass [kg] of an AnimalCohort.
muscle_terms: The tuple of muscle scaling terms used.
fat_terms: The tuple of fat scaling terms used.
Returns:
The energetic reserve [J] of an individual of the animal cohort.
"""
return (
muscle_mass_scaling(mass, muscle_terms) + fat_mass_scaling(mass, fat_terms)
) * 7000.0 # j/g


def intake_rate_scaling(mass: float, terms: tuple) -> float:
"""The function to set the intake rate of an individual in an AnimalCohort.
Currently, this scaling relationship is only accurate for terrestrial
herbivorous mammals interacting with plant foods. This will later be updated
for additional functional types and interactions.
The function form converts the original g/min rate into a kg/day rate, where a
day is an 8hr foraging window.
TODO: Remove if unused.
Args:
mass: The body-mass [kg] of an AnimalCohort.
terms: The tuple of intake rate terms used.
Returns:
The intake rate [kg/day] of an individual of the animal cohort.
"""

return terms[1] * mass ** terms[0] * 480 * (1 / 1000)


def prey_group_selection(
diet_type: DietType, mass: float, terms: tuple
) -> dict[str, tuple[float, float]]:
Expand Down Expand Up @@ -221,37 +133,6 @@ def prey_group_selection(
raise ValueError("Invalid diet type: {diet_type}")


def natural_mortality_scaling(mass: float, terms: tuple) -> float:
"""Determine the natural mortality rate of animal cohorts.
Relationship from: Dureuil & Froese 2021
M = - ln(P) / tmax (annual, year^-1, instantaneous rate)
tmax = mean maximum age
P = 0.015 # proportion surviving to tmax
Transform yearly rate to daily rate
transform daily rate to daily probability
prob = 1 - e^-M
TODO: Remove if unused.
Args:
mass: The body-mass [kg] of an AnimalCohort.
terms: The terms of the mean maximum age equation.
Returns:
The allometric natural mortality rate as a daily probability of death.
"""
tmax = terms[1] * mass ** terms[0]
annual_mortality_rate = -log(0.015) / tmax
daily_mortality_rate = annual_mortality_rate / 365.0
daily_mortality_prob = 1 - exp(-daily_mortality_rate)

return daily_mortality_prob


def background_mortality(u_bg: float) -> float:
"""Constant background rate of wastebasket mortality.
Expand Down

0 comments on commit 038de10

Please sign in to comment.