[med-svn] [Git][med-team/python-cobra][upstream] New upstream version 0.26.3

Étienne Mollier (@emollier) gitlab at salsa.debian.org
Thu Jun 22 21:06:22 BST 2023



Étienne Mollier pushed to branch upstream at Debian Med / python-cobra


Commits:
7c25ffb1 by Étienne Mollier at 2023-06-22T21:20:48+02:00
New upstream version 0.26.3
- - - - -


17 changed files:

- + release-notes/0.26.3.md
- setup.cfg
- setup.py
- src/cobra/__init__.py
- src/cobra/core/dictlist.py
- src/cobra/core/formula.py
- src/cobra/core/metabolite.py
- src/cobra/core/model.py
- src/cobra/core/reaction.py
- src/cobra/core/solution.py
- src/cobra/io/dict.py
- src/cobra/io/sbml.py
- src/cobra/io/web/cobrapy_repository.py
- src/cobra/sampling/hr_sampler.py
- tests/test_flux_analysis/test_deletion.py
- tests/test_io/test_sbml.py
- tests/test_util/test_context.py


Changes:

=====================================
release-notes/0.26.3.md
=====================================
@@ -0,0 +1,20 @@
+# Release notes for cobrapy x.y.z
+
+## New features
+
+## Fixes
+
+Fixed an issue where reaction bounds were being overwritten by global model min/max values
+when writing sbml model to file. See [#1300](https://github.com/opencobra/cobrapy/pull/1312).
+
+Fix an issue where [`runfrog`](https://github.com/matthiaskoenig/fbc_curation/issues/98) does
+not work via github actions or local installation by removing the use of obsolete numpy
+aliases for `float` and `bool`.
+
+Fix a bug where installing httpx>=0.24 would break cobrapy IO.
+
+## Other
+
+## Deprecated features
+
+## Backwards incompatible changes


=====================================
setup.cfg
=====================================
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 0.26.2
+current_version = 0.26.3
 commit = True
 tag = True
 parse = (?P<major>\d+)
@@ -58,7 +58,7 @@ install_requires =
 	depinfo ~=1.7
 	diskcache ~=5.0
 	future
-	httpx ~=0.14
+	httpx ~=0.24
 	importlib_resources
 	numpy >=1.13,<1.24
 	optlang ~=1.5


=====================================
setup.py
=====================================
@@ -19,4 +19,4 @@ if version_info[:2] < (3, 6):
 
 # All other arguments are defined in `setup.cfg`.
 if __name__ == "__main__":
-    setup(version="0.26.2")
+    setup(version="0.26.3")


=====================================
src/cobra/__init__.py
=====================================
@@ -1,5 +1,5 @@
 __author__ = "The cobrapy core development team."
-__version__ = "0.26.2"
+__version__ = "0.26.3"
 
 
 from cobra.core import (


=====================================
src/cobra/core/dictlist.py
=====================================
@@ -15,8 +15,6 @@ from typing import (
     Union,
 )
 
-import numpy as np
-
 from .object import Object
 
 
@@ -457,7 +455,7 @@ class DictList(list):
             selection._extend_nocheck(list.__getitem__(self, i))
             return selection
         elif hasattr(i, "__len__"):
-            if len(i) == len(self) and isinstance(i[0], (bool, np.bool)):
+            if len(i) == len(self) and isinstance(i[0], (bool, bool)):
                 selection = self.__class__()
                 result = (o for j, o in enumerate(self) if i[j])
                 selection._extend_nocheck(result)


=====================================
src/cobra/core/formula.py
=====================================
@@ -63,7 +63,7 @@ class Formula(Object):
             return
         composition = {}
         parsed = element_re.findall(tmp_formula)
-        for (element, count) in parsed:
+        for element, count in parsed:
             if count == "":
                 count = 1
             else:


=====================================
src/cobra/core/metabolite.py
=====================================
@@ -133,7 +133,7 @@ class Metabolite(Species):
             return None
         composition = {}
         parsed = element_re.findall(tmp_formula)
-        for (element, count) in parsed:
+        for element, count in parsed:
             if count == "":
                 count = 1
             else:


=====================================
src/cobra/core/model.py
=====================================
@@ -32,7 +32,6 @@ from .solution import get_solution
 
 
 if TYPE_CHECKING:
-
     import pandas as pd
     from optlang.container import Container
 
@@ -781,7 +780,6 @@ class Model(Object):
         context = get_context(self)
 
         for reaction in reactions:
-
             # Make sure the reaction is in the model
             try:
                 reaction = self.reactions[self.reactions.index(reaction)]
@@ -793,7 +791,6 @@ class Model(Object):
                 reverse = reaction.reverse_variable
 
                 if context:
-
                     obj_coef = reaction.objective_coefficient
 
                     if obj_coef != 0:


=====================================
src/cobra/core/reaction.py
=====================================
@@ -1228,7 +1228,6 @@ class Reaction(Object):
         _id_to_metabolites = dict([(x.id, x) for x in self._metabolites])
 
         for metabolite, coefficient in metabolites_to_add.items():
-
             # Make sure metabolites being added belong to the same model, or
             # else copy them.
             if isinstance(metabolite, Metabolite):


=====================================
src/cobra/core/solution.py
=====================================
@@ -177,13 +177,13 @@ def get_solution(
     if model.solver.is_integer:
         reduced.fill(np.nan)
         shadow.fill(np.nan)
-        for (i, rxn) in enumerate(reactions):
+        for i, rxn in enumerate(reactions):
             rxn_index.append(rxn.id)
             fluxes[i] = var_primals[rxn.id] - var_primals[rxn.reverse_id]
         met_index = [met.id for met in metabolites]
     else:
         var_duals = model.solver.reduced_costs
-        for (i, rxn) in enumerate(reactions):
+        for i, rxn in enumerate(reactions):
             forward = rxn.id
             reverse = rxn.reverse_id
             rxn_index.append(forward)
@@ -191,7 +191,7 @@ def get_solution(
             reduced[i] = var_duals[forward] - var_duals[reverse]
         met_index = []
         constr_duals = model.solver.shadow_prices
-        for (i, met) in enumerate(metabolites):
+        for i, met in enumerate(metabolites):
             met_index.append(met.id)
             shadow[i] = constr_duals[met.id]
     return Solution(


=====================================
src/cobra/io/dict.py
=====================================
@@ -68,13 +68,13 @@ _OPTIONAL_MODEL_ATTRIBUTES = {
 
 
 def _fix_type(
-    value: Union[str, np.float, np.bool, Set, Dict]
+    value: Union[str, float, bool, Set, Dict]
 ) -> Union[str, float, bool, List, OrderedDict]:
     """Convert possible types to correct Python types.
 
     Parameters
     ----------
-    value : str, np.float, np.bool, set, dict
+    value : str, float, bool, set, dict
         The value to fix type for.
 
     Returns
@@ -86,9 +86,9 @@ def _fix_type(
     # Because numpy floats can not be pickled to json
     if isinstance(value, str):
         return str(value)
-    if isinstance(value, np.float):
+    if isinstance(value, float):
         return float(value)
-    if isinstance(value, np.bool):
+    if isinstance(value, bool):
         return bool(value)
     if isinstance(value, set):
         return list(value)


=====================================
src/cobra/io/sbml.py
=====================================
@@ -1038,7 +1038,6 @@ def _sbml_to_model(
             model.getListOfReactions(),
             model_groups.getListOfGroups(),
         ]:
-
             sbase: "libsbml.SBase"
             for sbase in obj_list:
                 if sbase.isSetId():
@@ -1277,13 +1276,8 @@ def _model_to_sbml(
             unit.setScale(u.scale)
             unit.setMultiplier(u.multiplier)
 
-    # minimum and maximum value from model
-    if len(cobra_model.reactions) > 0:
-        min_value = min(cobra_model.reactions.list_attr("lower_bound"))
-        max_value = max(cobra_model.reactions.list_attr("upper_bound"))
-    else:
-        min_value = config.lower_bound
-        max_value = config.upper_bound
+    min_value = config.lower_bound
+    max_value = config.upper_bound
 
     _create_parameter(
         model, pid=LOWER_BOUND_ID, value=min_value, sbo=SBO_DEFAULT_FLUX_BOUND
@@ -1875,7 +1869,6 @@ def _sbase_annotations(sbase: libsbml.SBase, annotation: dict) -> None:
 
     # rdf_items = []
     for provider, data in annotation_data.items():
-
         # set SBOTerm
         if provider in ["SBO", "sbo"]:
             if provider == "SBO":


=====================================
src/cobra/io/web/cobrapy_repository.py
=====================================
@@ -33,7 +33,7 @@ class Cobrapy(AbstractModelRepository):
             Passed to the parent constructor in order to enable multiple inheritance.
 
         """
-        super().__init__(url="file:////", **kwargs)
+        super().__init__(url="file://", **kwargs)
 
     def get_sbml(self, model_id: str) -> bytes:
         """


=====================================
src/cobra/sampling/hr_sampler.py
=====================================
@@ -323,9 +323,7 @@ class HRSampler(ABC):
 
                 primals = self.model.solver.primal_values
                 sol = [primals[v.name] for v in self.model.variables]
-                self.warmup[
-                    self.n_warmup,
-                ] = sol
+                self.warmup[self.n_warmup,] = sol
                 self.n_warmup += 1
 
                 # Reset objective
@@ -425,33 +423,13 @@ class HRSampler(ABC):
     def _bounds_dist(self, p: np.ndarray) -> np.ndarray:
         """Get the lower and upper bound distances. Negative is bad."""
         prob = self.problem
-        lb_dist = (
-            p
-            - prob.variable_bounds[
-                0,
-            ]
-        ).min()
-        ub_dist = (
-            prob.variable_bounds[
-                1,
-            ]
-            - p
-        ).min()
+        lb_dist = (p - prob.variable_bounds[0,]).min()
+        ub_dist = (prob.variable_bounds[1,] - p).min()
 
         if prob.bounds.shape[0] > 0:
             const = prob.inequalities.dot(p)
-            const_lb_dist = (
-                const
-                - prob.bounds[
-                    0,
-                ]
-            ).min()
-            const_ub_dist = (
-                prob.bounds[
-                    1,
-                ]
-                - const
-            ).min()
+            const_lb_dist = (const - prob.bounds[0,]).min()
+            const_ub_dist = (prob.bounds[1,] - const).min()
             lb_dist = min(lb_dist, const_lb_dist)
             ub_dist = min(ub_dist, const_ub_dist)
 
@@ -564,38 +542,18 @@ class HRSampler(ABC):
             )
 
         feasibility = np.abs(S.dot(samples.T).T - b).max(axis=1)
-        lb_error = (
-            samples
-            - bounds[
-                0,
-            ]
-        ).min(axis=1)
-        ub_error = (
-            bounds[
-                1,
-            ]
-            - samples
-        ).min(axis=1)
+        lb_error = (samples - bounds[0,]).min(axis=1)
+        ub_error = (bounds[1,] - samples).min(axis=1)
 
         if samples.shape[1] == len(self.model.variables) and prob.inequalities.shape[0]:
             consts = prob.inequalities.dot(samples.T)
             lb_error = np.minimum(
                 lb_error,
-                (
-                    consts
-                    - prob.bounds[
-                        0,
-                    ]
-                ).min(axis=1),
+                (consts - prob.bounds[0,]).min(axis=1),
             )
             ub_error = np.minimum(
                 ub_error,
-                (
-                    prob.bounds[
-                        1,
-                    ]
-                    - consts
-                ).min(axis=1),
+                (prob.bounds[1,] - consts).min(axis=1),
             )
 
         valid = (


=====================================
tests/test_flux_analysis/test_deletion.py
=====================================
@@ -428,7 +428,7 @@ def test_double_reaction_deletion(model: Model) -> None:
     solution_one_process = double_reaction_deletion(
         model, reaction_list1=reactions, processes=1
     )
-    for (rxn_a, sub) in growth_dict.items():
+    for rxn_a, sub in growth_dict.items():
         for rxn_b, growth in sub.items():
             sol = solution.knockout[{rxn_a, rxn_b}]
             sol_one = solution_one_process.knockout[{rxn_a, rxn_b}]


=====================================
tests/test_io/test_sbml.py
=====================================
@@ -511,6 +511,45 @@ def test_boundary_conditions(data_directory: Path) -> None:
     assert sol1.objective_value == sol2.objective_value
 
 
+def test_bounds_on_write(data_directory: Path, tmp_path: Path) -> None:
+    """Test infinity bound example.
+
+    Parameters
+    ----------
+    data_directory: Path
+        Directory where the data is.
+    """
+    sbml_path1 = data_directory / "fbc_ex1.xml"
+    model1 = read_sbml_model(sbml_path1)
+
+    r_x = model1.reactions.get_by_id("EX_X")
+    r_y = model1.reactions.get_by_id("EX_Ac")
+
+    r_x.bounds = (config.lower_bound - 1000, config.upper_bound + 1000)
+    assert r_x.lower_bound == config.lower_bound - 1000
+    assert r_x.upper_bound == config.upper_bound + 1000
+
+    # Global min/max bounds for other reactions should not change before & after write!
+    r_y.bounds = (config.lower_bound, config.upper_bound)
+    assert r_y.lower_bound == config.lower_bound
+    assert r_y.upper_bound == config.upper_bound
+
+    sbml_path = tmp_path / "test.xml"
+    with open(sbml_path, "w") as f_out:
+        write_sbml_model(model1, f_out)
+
+    with open(sbml_path, "r") as f_in:
+        model2 = read_sbml_model(f_in)
+
+    r2_x = model2.reactions.get_by_id("EX_X")
+    r2_y = model2.reactions.get_by_id("EX_Ac")
+
+    assert r2_x.lower_bound == r_x.lower_bound
+    assert r2_x.upper_bound == r_x.upper_bound
+    assert r2_y.lower_bound == r_y.lower_bound  # before fix #1300, this would fail
+    assert r2_y.upper_bound == r_y.upper_bound  # before fix #1300, this would fail
+
+
 def test_gprs(large_model: Model, tmp_path: Path) -> None:
     """Test that GPRs are written and read correctly.
 


=====================================
tests/test_util/test_context.py
=====================================
@@ -39,6 +39,7 @@ def test_get_context(model: "Model") -> None:
 
 def test_resettable() -> None:
     """Test if resettable decorator is functional."""
+
     # decorate a dummy function
     @resettable
     def change_my_name(old_name, new_name):



View it on GitLab: https://salsa.debian.org/med-team/python-cobra/-/commit/7c25ffb143e459c6ffb4c1c669292adc43b1b74c

-- 
View it on GitLab: https://salsa.debian.org/med-team/python-cobra/-/commit/7c25ffb143e459c6ffb4c1c669292adc43b1b74c
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20230622/c1b76511/attachment-0001.htm>


More information about the debian-med-commit mailing list