From c018f279a786540eee345bb66ed7c74057ebe41a Mon Sep 17 00:00:00 2001 From: Joshua Forrest Date: Tue, 15 Apr 2025 17:09:18 +1000 Subject: [PATCH 1/3] filter check_mass_balance zeros with a floating point comparison --- src/cobra/core/reaction.py | 4 ++-- tests/test_core/test_core_reaction.py | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/cobra/core/reaction.py b/src/cobra/core/reaction.py index 9b1755dfe..f25f295ca 100644 --- a/src/cobra/core/reaction.py +++ b/src/cobra/core/reaction.py @@ -5,7 +5,7 @@ from collections import defaultdict from copy import copy, deepcopy from functools import partial -from math import isinf +from math import isinf, isclose from operator import attrgetter from typing import ( TYPE_CHECKING, @@ -1451,7 +1451,7 @@ def check_mass_balance(self) -> Dict[str, float]: for element, amount in metabolite.elements.items(): reaction_element_dict[element] += coefficient * amount # filter out 0 values - return {k: v for k, v in reaction_element_dict.items() if v != 0} + return {k: v for k, v in reaction_element_dict.items() if not isclose(v, 0.0, abs_tol=1e-12)} @property def compartments(self) -> Set: diff --git a/tests/test_core/test_core_reaction.py b/tests/test_core/test_core_reaction.py index d4813599e..24e7731f0 100644 --- a/tests/test_core/test_core_reaction.py +++ b/tests/test_core/test_core_reaction.py @@ -333,7 +333,10 @@ def test_mass_balance(model: Model) -> None: imbalance = reaction.check_mass_balance() assert "H" in imbalance assert imbalance["H"] == 1 - + # Should be balanced even when coefficients are non-integer + reaction_scaled = model.reactions.get_by_id("ATPS4r") * 1.3 + assert len(reaction_scaled.check_mass_balance()) == 0 + def test_build_from_string(model: Model) -> None: """Test reaction building from string evaluation.""" From c16fd2542acd25358941a7386898b3e0ea8da977 Mon Sep 17 00:00:00 2001 From: Joshua Forrest Date: Thu, 8 May 2025 14:14:00 +1000 Subject: [PATCH 2/3] code review changes --- src/cobra/core/reaction.py | 8 ++++++-- tests/test_core/test_core_reaction.py | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cobra/core/reaction.py b/src/cobra/core/reaction.py index f25f295ca..b6951ffd4 100644 --- a/src/cobra/core/reaction.py +++ b/src/cobra/core/reaction.py @@ -5,7 +5,7 @@ from collections import defaultdict from copy import copy, deepcopy from functools import partial -from math import isinf, isclose +from math import isclose, isinf from operator import attrgetter from typing import ( TYPE_CHECKING, @@ -1451,7 +1451,11 @@ def check_mass_balance(self) -> Dict[str, float]: for element, amount in metabolite.elements.items(): reaction_element_dict[element] += coefficient * amount # filter out 0 values - return {k: v for k, v in reaction_element_dict.items() if not isclose(v, 0.0, abs_tol=1e-12)} + return { + k: v + for k, v in reaction_element_dict.items() + if not isclose(v, 0.0, abs_tol=config.tolerance) + } @property def compartments(self) -> Set: diff --git a/tests/test_core/test_core_reaction.py b/tests/test_core/test_core_reaction.py index 24e7731f0..40068ba31 100644 --- a/tests/test_core/test_core_reaction.py +++ b/tests/test_core/test_core_reaction.py @@ -336,7 +336,7 @@ def test_mass_balance(model: Model) -> None: # Should be balanced even when coefficients are non-integer reaction_scaled = model.reactions.get_by_id("ATPS4r") * 1.3 assert len(reaction_scaled.check_mass_balance()) == 0 - + def test_build_from_string(model: Model) -> None: """Test reaction building from string evaluation.""" From 2398c4c4d5c0eec5bb8b882e58562d5c9723b66c Mon Sep 17 00:00:00 2001 From: Joshua Forrest Date: Fri, 16 May 2025 11:28:05 +1000 Subject: [PATCH 3/3] Update next-release.md --- release-notes/next-release.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release-notes/next-release.md b/release-notes/next-release.md index 65d76e291..8a5a5cd37 100644 --- a/release-notes/next-release.md +++ b/release-notes/next-release.md @@ -9,6 +9,8 @@ Fixes failures of GPR.copy() in Python 3.13. Fix compartment not being stored for metabolites created during reaction.build_reaction_from_string +Fix `reaction.check_mass_balance` giving incorrect results for reactions with floating point coefficients. + ## Other ## Deprecated features