Skip to content

Commit

Permalink
Constants rework into dataclass format.
Browse files Browse the repository at this point in the history
TaranRallings committed Nov 24, 2023
1 parent 8a586fe commit bea6655
Showing 11 changed files with 262 additions and 90 deletions.
39 changes: 30 additions & 9 deletions tests/models/animals/conftest.py
Original file line number Diff line number Diff line change
@@ -77,31 +77,49 @@ def plant_climate_data_instance(layer_roles_fixture):


@pytest.fixture
def functional_group_list_instance(shared_datadir):
def constants_instance():
"""Fixture for an instance of animal constants."""
from virtual_rainforest.models.animals.constants import AnimalConsts

return AnimalConsts()


@pytest.fixture
def functional_group_list_instance(shared_datadir, constants_instance):
"""Fixture for an animal functional group used in tests."""
from virtual_rainforest.models.animals.functional_group import (
import_functional_groups,
)

file = shared_datadir / "example_functional_group_import.csv"
fg_list = import_functional_groups(file)
fg_list = import_functional_groups(file, constants_instance)

return fg_list


@pytest.fixture
def animal_model_instance(data_instance, functional_group_list_instance):
def animal_model_instance(
data_instance, functional_group_list_instance, constants_instance
):
"""Fixture for an animal model object used in tests."""
from pint import Quantity

from virtual_rainforest.models.animals.animal_model import AnimalModel

return AnimalModel(data_instance, Quantity("1 day"), functional_group_list_instance)
return AnimalModel(
data_instance,
Quantity("1 day"),
functional_group_list_instance,
constants_instance,
)


@pytest.fixture
def animal_community_instance(
functional_group_list_instance, animal_model_instance, plant_data_instance
functional_group_list_instance,
animal_model_instance,
plant_data_instance,
constants_instance,
):
"""Fixture for an animal community used in tests."""
from virtual_rainforest.models.animals.animal_communities import AnimalCommunity
@@ -112,28 +130,31 @@ def animal_community_instance(
community_key=4,
neighbouring_keys=[1, 3, 5, 7],
get_destination=animal_model_instance.get_community_by_key,
constants=constants_instance,
)


@pytest.fixture
def herbivore_functional_group_instance(shared_datadir):
def herbivore_functional_group_instance(shared_datadir, constants_instance):
"""Fixture for an animal functional group used in tests."""
from virtual_rainforest.models.animals.functional_group import (
import_functional_groups,
)

file = shared_datadir / "example_functional_group_import.csv"
fg_list = import_functional_groups(file)
fg_list = import_functional_groups(file, constants_instance)

return fg_list[3]


@pytest.fixture
def herbivore_cohort_instance(herbivore_functional_group_instance):
def herbivore_cohort_instance(herbivore_functional_group_instance, constants_instance):
"""Fixture for an animal cohort used in tests."""
from virtual_rainforest.models.animals.animal_cohorts import AnimalCohort

return AnimalCohort(herbivore_functional_group_instance, 10000.0, 1, 10)
return AnimalCohort(
herbivore_functional_group_instance, 10000.0, 1, 10, constants_instance
)


@pytest.fixture
54 changes: 35 additions & 19 deletions tests/models/animals/test_animal_cohorts.py
Original file line number Diff line number Diff line change
@@ -5,53 +5,59 @@


@pytest.fixture
def predator_functional_group_instance(shared_datadir):
def predator_functional_group_instance(shared_datadir, constants_instance):
"""Fixture for an animal functional group used in tests."""
from virtual_rainforest.models.animals.functional_group import (
import_functional_groups,
)

file = shared_datadir / "example_functional_group_import.csv"
fg_list = import_functional_groups(file)
fg_list = import_functional_groups(file, constants_instance)

return fg_list[2]


@pytest.fixture
def predator_cohort_instance(predator_functional_group_instance):
def predator_cohort_instance(predator_functional_group_instance, constants_instance):
"""Fixture for an animal cohort used in tests."""
from virtual_rainforest.models.animals.animal_cohorts import AnimalCohort

return AnimalCohort(predator_functional_group_instance, 10000.0, 1, 10)
return AnimalCohort(
predator_functional_group_instance, 10000.0, 1, 10, constants_instance
)


@pytest.fixture
def ectotherm_functional_group_instance(shared_datadir):
def ectotherm_functional_group_instance(shared_datadir, constants_instance):
"""Fixture for an animal functional group used in tests."""
from virtual_rainforest.models.animals.functional_group import (
import_functional_groups,
)

file = shared_datadir / "example_functional_group_import.csv"
fg_list = import_functional_groups(file)
fg_list = import_functional_groups(file, constants_instance)

return fg_list[5]


@pytest.fixture
def ectotherm_cohort_instance(ectotherm_functional_group_instance):
def ectotherm_cohort_instance(ectotherm_functional_group_instance, constants_instance):
"""Fixture for an animal cohort used in tests."""
from virtual_rainforest.models.animals.animal_cohorts import AnimalCohort

return AnimalCohort(ectotherm_functional_group_instance, 100.0, 1, 10)
return AnimalCohort(
ectotherm_functional_group_instance, 100.0, 1, 10, constants_instance
)


@pytest.fixture
def prey_cohort_instance(herbivore_functional_group_instance):
def prey_cohort_instance(herbivore_functional_group_instance, constants_instance):
"""Fixture for an animal cohort used in tests."""
from virtual_rainforest.models.animals.animal_cohorts import AnimalCohort

return AnimalCohort(herbivore_functional_group_instance, 100.0, 1, 10)
return AnimalCohort(
herbivore_functional_group_instance, 100.0, 1, 10, constants_instance
)


@pytest.fixture
@@ -85,6 +91,7 @@ def test_invalid_animal_cohort_initialization(
age,
individuals,
error_type,
constants_instance,
):
"""Test for invalid inputs during AnimalCohort initialization."""
from virtual_rainforest.models.animals.animal_cohorts import AnimalCohort
@@ -95,6 +102,7 @@ def test_invalid_animal_cohort_initialization(
mass,
age,
individuals,
constants_instance,
)

@pytest.mark.parametrize(
@@ -346,38 +354,46 @@ def test_eat(self, herbivore_cohort_instance, mocker):
)
assert herbivore_cohort_instance.mass_current == 0

def test_is_below_mass_threshold(self, herbivore_cohort_instance):
def test_is_below_mass_threshold(
self, herbivore_cohort_instance, constants_instance
):
"""Test the can_reproduce method of AnimalCohort."""
from virtual_rainforest.models.animals.constants import BIRTH_MASS_THRESHOLD

# TODO: test other mass thresholds
# 1. Test when stored_energy is exactly equal to the threshold
herbivore_cohort_instance.mass_current = (
herbivore_cohort_instance.functional_group.adult_mass * BIRTH_MASS_THRESHOLD
herbivore_cohort_instance.functional_group.adult_mass
* constants_instance.birth_mass_threshold
)
assert not herbivore_cohort_instance.is_below_mass_threshold(
BIRTH_MASS_THRESHOLD
constants_instance.birth_mass_threshold
)

# 2. Test when stored_energy is just below the threshold
herbivore_cohort_instance.mass_current = (
herbivore_cohort_instance.functional_group.adult_mass * BIRTH_MASS_THRESHOLD
herbivore_cohort_instance.functional_group.adult_mass
* constants_instance.birth_mass_threshold
- 0.01
)
assert herbivore_cohort_instance.is_below_mass_threshold(BIRTH_MASS_THRESHOLD)
assert herbivore_cohort_instance.is_below_mass_threshold(
constants_instance.birth_mass_threshold
)

# 3. Test when stored_energy is above the threshold
herbivore_cohort_instance.mass_current = (
herbivore_cohort_instance.functional_group.adult_mass * BIRTH_MASS_THRESHOLD
herbivore_cohort_instance.functional_group.adult_mass
* constants_instance.birth_mass_threshold
+ 0.01
)
assert not herbivore_cohort_instance.is_below_mass_threshold(
BIRTH_MASS_THRESHOLD
constants_instance.birth_mass_threshold
)

# 4. Test with stored_energy set to 0
herbivore_cohort_instance.mass_current = 0.0
assert herbivore_cohort_instance.is_below_mass_threshold(BIRTH_MASS_THRESHOLD)
assert herbivore_cohort_instance.is_below_mass_threshold(
constants_instance.birth_mass_threshold
)

@pytest.mark.parametrize(
"initial_individuals, number_days, mortality_prob",
33 changes: 21 additions & 12 deletions tests/models/animals/test_animal_communities.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,10 @@

@pytest.fixture
def animal_community_destination_instance(
functional_group_list_instance, animal_model_instance, plant_data_instance
functional_group_list_instance,
animal_model_instance,
plant_data_instance,
constants_instance,
):
"""Fixture for an animal community used in tests."""
from virtual_rainforest.models.animals.animal_communities import AnimalCommunity
@@ -16,29 +19,34 @@ def animal_community_destination_instance(
community_key=4,
neighbouring_keys=[1, 3, 5, 7],
get_destination=animal_model_instance.get_community_by_key,
constants=constants_instance,
)


@pytest.fixture
def functional_group_instance(shared_datadir):
def functional_group_instance(shared_datadir, constants_instance):
"""Fixture for an animal functional group used in tests."""
from virtual_rainforest.models.animals.functional_group import (
import_functional_groups,
)

file = shared_datadir / "example_functional_group_import.csv"
fg_list = import_functional_groups(file)
fg_list = import_functional_groups(file, constants_instance)

return fg_list[3]


@pytest.fixture
def animal_cohort_instance(functional_group_instance):
def animal_cohort_instance(functional_group_instance, constants_instance):
"""Fixture for an animal cohort used in tests."""
from virtual_rainforest.models.animals.animal_cohorts import AnimalCohort

return AnimalCohort(
functional_group_instance, functional_group_instance.adult_mass, 1.0, 10
functional_group_instance,
functional_group_instance.adult_mass,
1.0,
10,
constants_instance,
)


@@ -164,9 +172,10 @@ def test_die_cohort(self, animal_cohort_instance, animal_community_instance):
not in animal_community_instance.animal_cohorts["herbivorous_mammal"]
)

def test_birth(self, animal_community_instance, animal_cohort_instance):
def test_birth(
self, animal_community_instance, animal_cohort_instance, constants_instance
):
"""Test the birth method in AnimalCommunity."""
from virtual_rainforest.models.animals.constants import BIRTH_MASS_THRESHOLD

# Setup initial conditions
parent_cohort_name = animal_cohort_instance.name
@@ -179,7 +188,8 @@ def test_birth(self, animal_community_instance, animal_cohort_instance):

# Set the reproductive mass of the parent cohort to ensure it can reproduce
required_mass_for_birth = (
animal_cohort_instance.functional_group.adult_mass * BIRTH_MASS_THRESHOLD
animal_cohort_instance.functional_group.adult_mass
* constants_instance.birth_mass_threshold
- animal_cohort_instance.functional_group.adult_mass
)

@@ -198,13 +208,11 @@ def test_birth(self, animal_community_instance, animal_cohort_instance):
# 2. Check that the reproductive mass of the parent cohort is reduced to 0
assert animal_cohort_instance.reproductive_mass == 0

def test_birth_community(self, animal_community_instance):
def test_birth_community(self, animal_community_instance, constants_instance):
"""Test the thresholding behavior of birth_community."""

from itertools import chain

from virtual_rainforest.models.animals.constants import BIRTH_MASS_THRESHOLD

# Preparation: populate the community
animal_community_instance.populate_community()

@@ -216,7 +224,8 @@ def test_birth_community(self, animal_community_instance):

# Set mass to just below the threshold
threshold_mass = (
initial_cohort.functional_group.adult_mass * BIRTH_MASS_THRESHOLD
initial_cohort.functional_group.adult_mass
* constants_instance.birth_mass_threshold
- initial_cohort.functional_group.adult_mass
)

16 changes: 11 additions & 5 deletions tests/models/animals/test_animal_model.py
Original file line number Diff line number Diff line change
@@ -11,7 +11,10 @@


def test_animal_model_initialization(
caplog, plant_climate_data_instance, functional_group_list_instance
caplog,
plant_climate_data_instance,
functional_group_list_instance,
constants_instance,
):
"""Test `AnimalModel` initialization."""
from virtual_rainforest.core.base_model import BaseModel
@@ -22,6 +25,7 @@ def test_animal_model_initialization(
plant_climate_data_instance,
pint.Quantity("1 week"),
functional_group_list_instance,
constants=constants_instance,
)

# In cases where it passes then checks that the object has the right properties
@@ -108,16 +112,17 @@ def test_generate_animal_model(
time_interval,
raises,
expected_log_entries,
constants_instance,
):
"""Test that the function to initialise the animal model behaves as expected."""
from virtual_rainforest.models.animals.animal_model import AnimalModel

# Check whether model is initialised (or not) as expected
with raises:
model = AnimalModel.from_config(
plant_climate_data_instance,
config,
pint.Quantity(config["core"]["timing"]["update_interval"]),
data=plant_climate_data_instance,
config=config,
update_interval=pint.Quantity(config["core"]["timing"]["update_interval"]),
)
assert model.update_interval == time_interval
# Run the update step (once this does something should check output)
@@ -152,7 +157,7 @@ def test_get_community_by_key(animal_model_instance):


def test_update_method_sequence(
plant_climate_data_instance, functional_group_list_instance
plant_climate_data_instance, functional_group_list_instance, constants_instance
):
"""Test update to ensure it runs the community methods in order.
@@ -166,6 +171,7 @@ def test_update_method_sequence(
plant_climate_data_instance,
pint.Quantity("1 week"),
functional_group_list_instance,
constants=constants_instance,
)

# Mock all the methods that are supposed to be called by update
Loading

0 comments on commit bea6655

Please sign in to comment.