Skip to content

Microbial group inputs as a csv file rather than toml configuration - #1956

Merged
Jacob Cook (jacobcook1995) merged 6 commits into
1928-not-providing-parameterisation-for-soil-microbial-groups-and-enzymes-doesnt-result-in-a-configuration-errorfrom
1542-convert-microbial-group-inputs-to-csv-format-rather-than-toml
Oct 27, 2026
Merged

Jacob Cook (jacobcook1995) merged 6 commits into
1928-not-providing-parameterisation-for-soil-microbial-groups-and-enzymes-doesnt-result-in-a-configuration-errorfrom
1542-convert-microbial-group-inputs-to-csv-format-rather-than-toml

Conversation

@jacobcook1995

@jacobcook1995 Jacob Cook (jacobcook1995) commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Description

This PR extends the work done in #1947, so that soil microbial groups are also read in from a csv file.

To make the changes clearer I'm setting this PR to merge to the branch used into #1947. My intention is to merge both of them to the feature branch, and then do a final PR against that.

Fixes #1542
Fixes #1954

Type of change

  • New feature (non-breaking change which adds functionality)
  • Optimization (back-end change that speeds up the code)
  • Bug fix (non-breaking change which fixes an issue)

Key checklist

  • Make sure you've run the pre-commit checks: $ pre-commit run -a
  • All tests pass: $ poetry run pytest

Further checks

  • Code is commented, particularly in hard-to-understand areas
  • Tests added that prove fix is effective or that feature works
  • Relevant documentation reviewed and updated
  • If this PR changes the expected model inputs, are the relevant people from the
    data science team included as reviewers?

@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Oct 26, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.73684% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.62%. Comparing base (c1f8835) to head (117f99e).
⚠️ Report is 1 commits behind head on 1928-not-providing-parameterisation-for-soil-microbial-groups-and-enzymes-doesnt-result-in-a-configuration-error.

Files with missing lines Patch % Lines
...ation_scripts/microbial_parametrisation_example.py 0.00% 6 Missing ⚠️
virtual_ecosystem/models/soil/microbial_groups.py 98.51% 2 Missing ⚠️
Additional details and impacted files
@@                                                                 Coverage Diff                                                                  @@
##           1928-not-providing-parameterisation-for-soil-microbial-groups-and-enzymes-doesnt-result-in-a-configuration-error    #1956      +/-   ##
====================================================================================================================================================
+ Coverage                                                                                                             88.91%   89.62%   +0.70%     
====================================================================================================================================================
  Files                                                                                                                    85       84       -1     
  Lines                                                                                                                  9637     9534     -103     
====================================================================================================================================================
- Hits                                                                                                                   8569     8545      -24     
+ Misses                                                                                                                 1068      989      -79     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@davidorme David Orme (davidorme) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - I'm not a huge fan of the _enzyme_details attribute and have a suggestion there, but I don't know if those details need to be embedded beyond the clear use case in synthesis_nutrient_ratios.

Comment on lines +42 to +45
````{dropdown} example_microbial_groups.csv
```{literalinclude} ../../../../../virtual_ecosystem/example_data/data/example_microbial_groups.csv
```
````

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'd be better off using dynamically generated Markdown to avoid hardcoding these paths, but this isn't the only place we do this and it's not a big deal.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep both agree that the above is a bit of a mess and also that this isn't the place to fix it

Comment on lines +285 to +311
try:
microbes = [
SoilMicrobe.model_validate(rec) for rec in data.to_dict(orient="records")
]
for microbe in microbes:
microbe._enzyme_details = enzyme_classes
except ValidationError as excep:
raise ValueError(f"Invalid data in microbe parametrisation CSV file: {excep!s}")

# Check the set of microbes for duplicates
provided_microbes = [e.name for e in microbes]
set_provided_microbes = set(provided_microbes)

if len(set_provided_microbes) != len(provided_microbes):
raise ValueError(
"Duplicated microbial groups in microbial parametrisation data"
)

if not set_provided_microbes == set(get_args(REQUIRED_MICROBIAL_GROUPS)):
raise ValueError(
f"The microbial groups provided in the microbial groups definition file "
f"({set_provided_microbes!r}) do not match the required set of microbial "
f"groups ({REQUIRED_MICROBIAL_GROUPS!r})"
)

# Package into a dict and return
return {r.name: r for r in microbes}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if _enzyme_details is accessed elsewhere, but at the moment it looks like it is stuck in purely to support a call to synthesis_nutrient_ratios.

I'd drop it as a private attribute and make enzyme_details an argument in the call to synthesis_nutrient_ratios and then have an explicit call to synthesis_nutrient_ratios(enzyme_details) here in load_microbes. That does mean you can't calculate those ratios later, but there is then an explicit point in the code that populates those values and you avoid the extra property.

@jacobcook1995 Jacob Cook (jacobcook1995) Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't that make synthesis_nutrient_ratios a method rather than an attribute/property though? So downstream code would have to go from e.g.

nitrogen_limit = (
        functional_group.synthesis_nutrient_ratios["nitrogen"] * nitrogen_gain_max
)

to

synthesis_ratios = functional_group.synthesis_nutrient_ratios(enzyme_details)
nitrogen_limit = (
        synthesis_ratios["nitrogen"] * nitrogen_gain_max
)

with the enzyme details having to be passed to wherever the attribute needs to be used

@davidorme David Orme (davidorme) Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. Yeah. That's right. OK - if enzyme details are only used at this point, I still think it's odd to attach them. I think there are two options (well, three, if you're happy to live with my unease 😁 ):

  1. Make them an attribute that defaults to None and then have a method to populate:

  2. ... but that leaves some odd holes - you have to run populate_b and you can in theory populate b at __init__ within any old junk and then not populate_b. The pydantic implementation of dataclasses may be cleaner here.

In [2]: from dataclasses import InitVar
   ...: from pydantic import BaseModel, Field
   ...: from pydantic.dataclasses import dataclass
   ...: 
   ...: class Test(BaseModel):
   ...: 
   ...:     a: int
   ...:     b: int | None = None
   ...: 
   ...:     def populate_b(self, x: int) -> None:
   ...: 
   ...:         self.b = self.a * x
   ...: 
   ...: t = Test(a=1)
   ...: t.populate_b(x=3)
   ...: t
   ...: 
Out[2]: Test(a=1, b=3)

In [3]: 
   ...: @dataclass
   ...: class Test2():
   ...: 
   ...:     a: int
   ...:     b: int = Field(init=False)
   ...:     x: InitVar[int]
   ...: 
   ...:     def __post_init__(self, x: int) -> None:
   ...: 
   ...:         self.b = self.a * x
   ...: 
   ...: t2 = Test2(a=1, x=3)
   ...: t2
Out[3]: Test2(a=1, b=3)

In [4]: 

Note that this is still a pydantic model so you get validation on the inputs.

In [4]: t2 = Test2(a=1.5, x=3)
---------------------------------------------------------------------------
ValidationError                           Traceback (most recent call last)
Cell In[4], line 1
----> 1 t2 = Test2(a=1.5, x=3)

File ~/Library/Caches/pypoetry/virtualenvs/virtual-ecosystem-In6MogPy-py3.13/lib/python3.13/site-packages/pydantic/_internal/_dataclasses.py:121, in complete_dataclass.<locals>.__init__(__dataclass_self__, *args, **kwargs)
    119 __tracebackhide__ = True
    120 s = __dataclass_self__
--> 121 s.__pydantic_validator__.validate_python(ArgsKwargs(args, kwargs), self_instance=s)

ValidationError: 1 validation error for Test2
a
  Input should be a valid integer, got a number with a fractional part [type=int_from_float, input_value=1.5, input_type=float]
    For further information visit https://errors.pydantic.dev/2.14/v/int_from_float

Base automatically changed from 1541-convert-soil-enzyme-inputs-to-csv-format-rather-than-toml to 1928-not-providing-parameterisation-for-soil-microbial-groups-and-enzymes-doesnt-result-in-a-configuration-error October 27, 2026 14:28
@jacobcook1995
Jacob Cook (jacobcook1995) merged commit 9c366e3 into 1928-not-providing-parameterisation-for-soil-microbial-groups-and-enzymes-doesnt-result-in-a-configuration-error Oct 27, 2026
12 of 13 checks passed
@jacobcook1995
Jacob Cook (jacobcook1995) deleted the 1542-convert-microbial-group-inputs-to-csv-format-rather-than-toml branch October 27, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants