Skip to content
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
2 changes: 2 additions & 0 deletions docs/source/_toc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ subtrees:
entries:
- file: api/models/soil/pools
title: The pools submodule
- file: api/models/soil/model_config
title: The model_config submodule
- file: api/models/soil/constants
title: The constants submodule
- file: api/models/soil/env_factors
Expand Down
34 changes: 34 additions & 0 deletions docs/source/api/models/soil/model_config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
jupytext:
cell_metadata_filter: -all
formats: md:myst
main_language: python
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.18.1
kernelspec:
display_name: Python 3 (ipykernel)
language: python
name: python3
language_info:
codemirror_mode:
name: ipython
version: 3
file_extension: .py
mimetype: text/x-python
name: python
nbconvert_exporter: python
pygments_lexer: ipython3
version: 3.11.9
---

# API documentation for the {mod}`~virtual_ecosystem.models.soil.model_config` module

```{eval-rst}
.. automodule:: virtual_ecosystem.models.soil.model_config
:autosummary:
:members:
:exclude-members: model_config
```
5 changes: 5 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ class MyReferenceStyle(AuthorYearReferenceStyle):
("py:class", "NegativeFloat"),
("py:class", "date"),
("py:class", "_PydanticGeneralMetadata"),
# Sphinx seems to insist that pydantic model types are classes, when they can be
# global Literals
("py:class", "SUBSTRATES"),
("py:class", "REQUIRED_MICROBIAL_GROUPS"),
("py:class", "HIGHER_TAXONOMIC_GROUPS"),
("py:class", "dir"),
# FOR PITY'S SAKE, SPHINX - why can you not find DIRPATH_PLACEHOLDER when you _can_
# find FILEPATH_PLACEHOLDER, which is defined in the same way, in the same file and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,8 @@ function](virtual_ecosystem.models.soil.microbial_groups.make_full_set_of_microb
Similarly, enzyme classes are distinguished by whether they were produced by fungi or
bacteria and by what substrate they break down ({term}`MAOM` or {term}`POM`). So, there
is a total of four enzyme classes in the model. The parameters associated with each
class are stored in an [EnzymeConstants data
class](virtual_ecosystem.models.soil.microbial_groups.EnzymeConstants), and the full set
of them can be constructed using the [make_full_set_of_enzymes
function](virtual_ecosystem.models.soil.microbial_groups.make_full_set_of_enzymes).
class are stored in an [SoilEnzymeClass data
class](virtual_ecosystem.models.soil.model_config.SoilEnzymeClass).

## Model variables

Expand Down
8 changes: 3 additions & 5 deletions tests/models/animals/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,13 +407,11 @@ def functional_group_list_instance(shared_datadir, constants_instance):


@pytest.fixture
def microbial_c_n_p_ratios(fixture_config):
def microbial_c_n_p_ratios(fixture_configuration):
"""Fixture containing the microbial C:N:P ratios for use in animal model testing."""
from virtual_ecosystem.models.soil.microbial_groups import (
find_microbial_stoichiometries,
)
from virtual_ecosystem.models.animal.cnp import find_microbial_stoichiometries

return find_microbial_stoichiometries(config=fixture_config)
return find_microbial_stoichiometries(config=fixture_configuration)


@pytest.fixture
Expand Down
1 change: 0 additions & 1 deletion tests/models/animals/test_animal_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ def test_animal_model_initialization(
does_not_raise(),
(
(INFO, "Initialised animal.AnimalConsts from config"),
(INFO, "Initialised core.CoreConsts from config"),
(
INFO,
"Information required to initialise the animal model"
Expand Down
16 changes: 16 additions & 0 deletions tests/models/animals/test_cnp.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,19 @@ def test_get_proportions_zero_handling(self):
assert proportions["carbon"] == 0.0
assert proportions["nitrogen"] == 0.0
assert proportions["phosphorus"] == 0.0


def test_find_microbial_stoichiometries(fixture_configuration):
"""Check that extraction of stoichiometries from microbial groups works."""
from virtual_ecosystem.models.animal.cnp import find_microbial_stoichiometries

expected_ratios = {
"bacteria": {"nitrogen": 5.2, "phosphorus": 16.0},
"saprotrophic_fungi": {"nitrogen": 6.5, "phosphorus": 40.0},
"arbuscular_mycorrhiza": {"nitrogen": 18.0, "phosphorus": 120.0},
"ectomycorrhiza": {"nitrogen": 18.0, "phosphorus": 120.0},
}

actual_ratios = find_microbial_stoichiometries(config=fixture_configuration)

assert expected_ratios == actual_ratios
97 changes: 58 additions & 39 deletions tests/models/soil/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,27 @@ def fixture_soil_configuration(microbial_groups_cfg):
return generate_configuration(config_data.data)


@pytest.fixture
def fixture_core_constants(fixture_soil_configuration):
"""Get the core constants instance from the config."""

return fixture_soil_configuration.core.constants


@pytest.fixture
def fixture_soil_constants(fixture_soil_configuration):
"""Get the soil constants instance from the config."""

return fixture_soil_configuration.soil.constants


@pytest.fixture
def fixture_hydrology_constants(fixture_soil_configuration):
"""Get the hydrology constants instance from the config."""

return fixture_soil_configuration.hydrology.constants


@pytest.fixture
def fixture_soil_core_components(fixture_soil_configuration):
"""Create a core components from the fixture_soil_config."""
Expand Down Expand Up @@ -180,12 +201,13 @@ def fixture_soil_model(


@pytest.fixture
def environmental_factors(dummy_carbon_data, fixture_core_components):
def environmental_factors(
dummy_carbon_data, fixture_soil_constants, fixture_core_components
):
"""Environmental factors based on dummy carbon data."""
from virtual_ecosystem.models.litter.env_factors import (
average_water_potential_over_microbially_active_layers,
)
from virtual_ecosystem.models.soil.constants import SoilConsts
from virtual_ecosystem.models.soil.env_factors import (
calculate_environmental_effect_factors,
)
Expand All @@ -197,24 +219,24 @@ def environmental_factors(dummy_carbon_data, fixture_core_components):
),
pH=dummy_carbon_data["pH"].to_numpy(),
clay_fraction=dummy_carbon_data["clay_fraction"].to_numpy(),
constants=SoilConsts,
constants=fixture_soil_constants,
)


@pytest.fixture
def carbon_supply_from_plants(dummy_carbon_data):
def carbon_supply_from_plants(
dummy_carbon_data, fixture_core_constants, fixture_soil_constants
):
"""Carbon supply from plants split between the different symbiotic groups."""
from virtual_ecosystem.core.constants import CoreConsts
from virtual_ecosystem.models.soil.constants import SoilConsts
from virtual_ecosystem.models.soil.microbial_groups import (
calculate_symbiotic_carbon_supply,
)

return calculate_symbiotic_carbon_supply(
total_plant_supply=dummy_carbon_data["plant_symbiote_carbon_supply"]
/ CoreConsts.max_depth_of_microbial_activity,
nitrogen_fixer_fraction=SoilConsts.nitrogen_fixer_supply_fraction,
ectomycorrhiza_fraction=SoilConsts.ectomycorrhiza_supply_fraction,
/ fixture_core_constants.max_depth_of_microbial_activity,
nitrogen_fixer_fraction=fixture_soil_constants.nitrogen_fixer_supply_fraction,
ectomycorrhiza_fraction=fixture_soil_constants.ectomycorrhiza_supply_fraction,
)


Expand Down Expand Up @@ -272,74 +294,71 @@ def enzyme_mediated_rates(


@pytest.fixture
def necromass_breakdown(dummy_carbon_data):
def necromass_breakdown(dummy_carbon_data, fixture_soil_constants):
"""Necromass breakdown rate based on dummy carbon data."""
from virtual_ecosystem.models.soil.constants import SoilConsts
from virtual_ecosystem.models.soil.pools import calculate_necromass_breakdown

return calculate_necromass_breakdown(
soil_c_pool_necromass=dummy_carbon_data["soil_c_pool_necromass"],
necromass_decay_rate=SoilConsts.necromass_decay_rate,
necromass_decay_rate=fixture_soil_constants.necromass_decay_rate,
)


@pytest.fixture
def necromass_sorption(dummy_carbon_data):
def necromass_sorption(dummy_carbon_data, fixture_soil_constants):
"""Necromass sorption rate based on dummy carbon data."""
from virtual_ecosystem.models.soil.constants import SoilConsts
from virtual_ecosystem.models.soil.pools import calculate_sorption_to_maom

return calculate_sorption_to_maom(
soil_c_pool=dummy_carbon_data["soil_c_pool_necromass"],
sorption_rate_constant=SoilConsts.necromass_sorption_rate,
sorption_rate_constant=fixture_soil_constants.necromass_sorption_rate,
)


@pytest.fixture
def lmwc_sorption(dummy_carbon_data):
def lmwc_sorption(dummy_carbon_data, fixture_soil_constants):
"""Low molecular weight carbon sorption rate based on dummy carbon data."""
from virtual_ecosystem.models.soil.constants import SoilConsts
from virtual_ecosystem.models.soil.pools import calculate_sorption_to_maom

return calculate_sorption_to_maom(
soil_c_pool=dummy_carbon_data["soil_c_pool_lmwc"],
sorption_rate_constant=SoilConsts.lmwc_sorption_rate,
sorption_rate_constant=fixture_soil_constants.lmwc_sorption_rate,
)


@pytest.fixture
def maom_desorption(dummy_carbon_data):
def maom_desorption(dummy_carbon_data, fixture_soil_constants):
"""MAOM desorption rate based on dummy carbon data."""
from virtual_ecosystem.models.soil.constants import SoilConsts
from virtual_ecosystem.models.soil.pools import calculate_maom_desorption

return calculate_maom_desorption(
soil_c_pool_maom=dummy_carbon_data["soil_c_pool_maom"],
desorption_rate_constant=SoilConsts.maom_desorption_rate,
desorption_rate_constant=fixture_soil_constants.maom_desorption_rate,
)


@pytest.fixture
def functional_groups(fixture_config, enzyme_classes):
def functional_groups(fixture_configuration, enzyme_classes, fixture_core_constants):
"""Set of functional groups based on the soil model constants."""
from virtual_ecosystem.core.constants import CoreConsts
from virtual_ecosystem.models.soil.microbial_groups import (
make_full_set_of_microbial_groups,
)

return make_full_set_of_microbial_groups(
config=fixture_config, enzyme_classes=enzyme_classes, core_constants=CoreConsts
config=fixture_configuration.soil,
enzyme_classes=enzyme_classes,
core_constants=fixture_core_constants,
)


@pytest.fixture
def enzyme_classes(fixture_config):
def enzyme_classes(fixture_configuration):
"""Set of functional groups based on the soil model constants."""
from virtual_ecosystem.models.soil.microbial_groups import (
make_full_set_of_enzymes,
)

return make_full_set_of_enzymes(config=fixture_config)
return {
f"{e.source}_{e.substrate}": e
for e in fixture_configuration.soil.enzyme_class_definition
}


@pytest.fixture
Expand Down Expand Up @@ -373,14 +392,15 @@ def biomass_losses(soil_pool_data, functional_groups, averaged_soil_temp):
@pytest.fixture
def growth_rates(
dummy_carbon_data,
fixture_soil_constants,
environmental_factors,
functional_groups,
soil_pool_data,
averaged_soil_temp,
carbon_supply_from_plants,
):
"""Fixture to store growth rates of all the microbial groups."""
from virtual_ecosystem.models.soil.constants import SoilConsts

from virtual_ecosystem.models.soil.pools import calculate_nutrient_uptake_rates

bacterial_growth, _ = calculate_nutrient_uptake_rates(
Expand All @@ -397,7 +417,7 @@ def growth_rates(
water_factor=environmental_factors.water,
pH_factor=environmental_factors.pH,
soil_temp=averaged_soil_temp,
constants=SoilConsts,
constants=fixture_soil_constants,
functional_group=functional_groups["bacteria"],
)
saprotrophic_fungal_growth, _ = calculate_nutrient_uptake_rates(
Expand All @@ -414,7 +434,7 @@ def growth_rates(
water_factor=environmental_factors.water,
pH_factor=environmental_factors.pH,
soil_temp=averaged_soil_temp,
constants=SoilConsts,
constants=fixture_soil_constants,
functional_group=functional_groups["saprotrophic_fungi"],
)
arbuscular_mycorrhizal_growth, _ = calculate_nutrient_uptake_rates(
Expand All @@ -431,7 +451,7 @@ def growth_rates(
water_factor=environmental_factors.water,
pH_factor=environmental_factors.pH,
soil_temp=averaged_soil_temp,
constants=SoilConsts,
constants=fixture_soil_constants,
functional_group=functional_groups["arbuscular_mycorrhiza"],
)
ectomycorrhizal_growth, _ = calculate_nutrient_uptake_rates(
Expand All @@ -448,7 +468,7 @@ def growth_rates(
water_factor=environmental_factors.water,
pH_factor=environmental_factors.pH,
soil_temp=averaged_soil_temp,
constants=SoilConsts,
constants=fixture_soil_constants,
functional_group=functional_groups["ectomycorrhiza"],
)

Expand All @@ -472,18 +492,17 @@ def enzyme_production(functional_groups, growth_rates):


@pytest.fixture
def carbon_use_efficiency(averaged_soil_temp):
def carbon_use_efficiency(averaged_soil_temp, fixture_soil_constants):
"""Fixture to store the carbon use efficiency."""
from virtual_ecosystem.models.soil.constants import SoilConsts
from virtual_ecosystem.models.soil.env_factors import (
calculate_carbon_use_efficiency,
)

return calculate_carbon_use_efficiency(
soil_temp=averaged_soil_temp,
reference_cue_logit=SoilConsts.reference_cue_logit,
cue_reference_temp=SoilConsts.cue_reference_temp,
logit_cue_with_temp=SoilConsts.logit_cue_with_temperature,
reference_cue_logit=fixture_soil_constants.reference_cue_logit,
cue_reference_temp=fixture_soil_constants.cue_reference_temp,
logit_cue_with_temp=fixture_soil_constants.logit_cue_with_temperature,
)


Expand Down
Loading