Skip to content

Commit 56bb571

Browse files
committed
Remove option to keep unmodeled species in ThinLayer
The 'remove_unmodeled_species' parameter was removed from BaseThinLayer and related tests. Unmodeled species are now always removed during optimization, simplifying the API and test logic.
1 parent 382ae55 commit 56bb571

3 files changed

Lines changed: 17 additions & 56 deletions

File tree

pyenzyme/thinlayers/base.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ def __init__(
3636
enzmldoc: v2.EnzymeMLDocument,
3737
measurement_ids: Optional[List[str]] = None,
3838
df_per_measurement: bool = False,
39-
remove_unmodeled_species: bool = True,
4039
):
4140
assert isinstance(enzmldoc, v2.EnzymeMLDocument)
4241
assert isinstance(measurement_ids, list) or measurement_ids is None
@@ -49,9 +48,6 @@ def __init__(
4948
if measurement_ids is None:
5049
measurement_ids = [meas.id for meas in enzmldoc.measurements]
5150

52-
if remove_unmodeled_species:
53-
enzmldoc = self._remove_unmodeled_species(enzmldoc)
54-
5551
self.enzmldoc = enzmldoc.model_copy(deep=True)
5652
self.fitted_doc = enzmldoc.model_copy(deep=True)
5753
self.measurement_ids = measurement_ids

pyenzyme/thinlayers/psyces.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,10 @@ def _get_experimental_data(self):
309309
310310
Populates the inits, experimental_data, and cols attributes.
311311
"""
312+
enzmldoc = self._remove_unmodeled_species(self.enzmldoc)
312313
self.inits = [
313314
InitMap.from_measurement(measurement, self.df_map[measurement.id])
314-
for measurement in self.enzmldoc.measurements
315+
for measurement in enzmldoc.measurements
315316
if measurement.id in self.measurement_ids
316317
]
317318

tests/unit/test_thinlayer.py

Lines changed: 15 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,19 @@ def test_remove_unmodeled_species_reaction(self):
2929
reaction.add_to_products(species_id="Product", stoichiometry=1)
3030

3131
# Remove unmodeled species
32-
thinlayer = MockThinLayer(enzmldoc, remove_unmodeled_species=True)
32+
thinlayer = MockThinLayer(enzmldoc)
33+
tl_enzmldoc = thinlayer.optimize()
3334

34-
assert len(thinlayer.enzmldoc.small_molecules) == 2, (
35-
f"Unmodeled small molecules should be removed, but {len(thinlayer.enzmldoc.small_molecules)} remain."
35+
assert len(tl_enzmldoc.small_molecules) == 2, (
36+
f"Unmodeled small molecules should be removed, but {len(tl_enzmldoc.small_molecules)} remain."
3637
)
37-
assert len(thinlayer.enzmldoc.measurements) == 2, (
38-
f"Unmodeled measurements should be removed, but {len(thinlayer.enzmldoc.measurements)} remain."
38+
assert len(tl_enzmldoc.measurements) == 2, (
39+
f"Unmodeled measurements should be removed, but {len(tl_enzmldoc.measurements)} remain."
3940
)
4041

4142
measurement_has_unmodeled: list[str] = []
4243

43-
for measurement in thinlayer.enzmldoc.measurements:
44+
for measurement in tl_enzmldoc.measurements:
4445
for species_data in measurement.species_data:
4546
if species_data.species_id == "Unmodeled":
4647
measurement_has_unmodeled.append(measurement.id)
@@ -74,18 +75,19 @@ def test_remove_unmodeled_species_odes(self):
7475
)
7576

7677
# Remove unmodeled species
77-
thinlayer = MockThinLayer(enzmldoc, remove_unmodeled_species=True)
78+
thinlayer = MockThinLayer(enzmldoc)
79+
tl_enzmldoc = thinlayer.optimize()
7880

79-
assert len(thinlayer.enzmldoc.small_molecules) == 2, (
80-
f"Unmodeled small molecules should be removed, but {len(thinlayer.enzmldoc.small_molecules)} remain."
81+
assert len(tl_enzmldoc.small_molecules) == 2, (
82+
f"Unmodeled small molecules should be removed, but {len(tl_enzmldoc.small_molecules)} remain."
8183
)
82-
assert len(thinlayer.enzmldoc.measurements) == 2, (
83-
f"Unmodeled measurements should be removed, but {len(thinlayer.enzmldoc.measurements)} remain."
84+
assert len(tl_enzmldoc.measurements) == 2, (
85+
f"Unmodeled measurements should be removed, but {len(tl_enzmldoc.measurements)} remain."
8486
)
8587

8688
measurement_has_unmodeled: list[str] = []
8789

88-
for measurement in thinlayer.enzmldoc.measurements:
90+
for measurement in tl_enzmldoc.measurements:
8991
for species_data in measurement.species_data:
9092
if species_data.species_id == "Unmodeled":
9193
measurement_has_unmodeled.append(measurement.id)
@@ -94,44 +96,6 @@ def test_remove_unmodeled_species_odes(self):
9496
f"Unmodeled species should be removed, but appears in measurements {measurement_has_unmodeled}."
9597
)
9698

97-
def test_leave_unmodeled_species(self):
98-
"""
99-
Test that unmodeled species are preserved when remove_unmodeled_species=False.
100-
101-
This test verifies that:
102-
- All species are kept in the document regardless of modeling status
103-
- Empty measurements are still removed
104-
- Measurements with unmodeled species are preserved
105-
"""
106-
enzmldoc = self._create_enzmldoc()
107-
108-
# Add reaction with only Substrate and Product (Unmodeled remains unmodeled)
109-
reaction = enzmldoc.add_to_reactions(id="R1", name="R1")
110-
reaction.add_to_reactants(species_id="Substrate", stoichiometry=1)
111-
reaction.add_to_products(species_id="Product", stoichiometry=1)
112-
113-
# Keep unmodeled species
114-
thinlayer = MockThinLayer(enzmldoc, remove_unmodeled_species=False)
115-
116-
assert len(thinlayer.enzmldoc.small_molecules) == 3, (
117-
f"Unmodeled small molecules should not be removed, but {len(thinlayer.enzmldoc.small_molecules)} remain."
118-
)
119-
120-
assert len(thinlayer.enzmldoc.measurements) == 3, (
121-
f"Empty measurements should be removed, but {len(thinlayer.enzmldoc.measurements)} remain."
122-
)
123-
124-
measurement_has_unmodeled: list[str] = []
125-
126-
for measurement in thinlayer.enzmldoc.measurements:
127-
for species_data in measurement.species_data:
128-
if species_data.species_id == "Unmodeled":
129-
measurement_has_unmodeled.append(measurement.id)
130-
131-
assert len(measurement_has_unmodeled) == 2, (
132-
f"Unmodeled species should not be removed, but appears in measurements {measurement_has_unmodeled}."
133-
)
134-
13599
def _create_enzmldoc(self) -> EnzymeMLDocument:
136100
"""
137101
Create a test EnzymeML document with various measurement scenarios.
@@ -190,7 +154,7 @@ def integrate(self, *args, **kwargs):
190154

191155
def optimize(self, *args, **kwargs):
192156
"""Mock optimization method that does nothing."""
193-
pass
157+
return self._remove_unmodeled_species(self.enzmldoc)
194158

195159
def write(self, *args, **kwargs):
196160
"""Mock write method that does nothing."""

0 commit comments

Comments
 (0)