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

Andreas Tille gitlab at salsa.debian.org
Thu Feb 7 09:12:48 GMT 2019


Andreas Tille pushed to branch upstream at Debian Med / python-cobra


Commits:
6827160c by Andreas Tille at 2019-02-01T14:59:37Z
New upstream version 0.14.2
- - - - -


8 changed files:

- cobra/__init__.py
- cobra/core/model.py
- + cobra/medium/annotations.py
- cobra/medium/boundary_types.py
- cobra/test/test_medium.py
- + release-notes/0.14.2.md
- setup.cfg
- setup.py


Changes:

=====================================
cobra/__init__.py
=====================================
@@ -15,7 +15,7 @@ from cobra import flux_analysis
 from cobra import io
 from cobra.util import show_versions
 
-__version__ = "0.14.1"
+__version__ = "0.14.2"
 
 # set the warning format to be prettier and fit on one line
 _cobra_path = _dirname(_abspath(__file__))


=====================================
cobra/core/model.py
=====================================
@@ -19,7 +19,8 @@ from cobra.core.object import Object
 from cobra.core.reaction import Reaction
 from cobra.core.solution import get_solution
 from cobra.exceptions import SolverNotFound
-from cobra.medium import find_boundary_types, sbo_terms
+from cobra.medium import (
+    find_boundary_types, find_external_compartment, sbo_terms)
 from cobra.util.context import HistoryManager, get_context, resettable
 from cobra.util.solver import (
     add_cons_vars_to_problem, assert_optimal, interface_to_str,
@@ -505,15 +506,22 @@ class Model(Object):
         >>> demand.build_reaction_string()
         'atp_c --> '
         """
-        if ub is None:
-            ub = CONFIGURATION.upper_bound
-        if lb is None:
-            lb = CONFIGURATION.lower_bound
+        ub = CONFIGURATION.upper_bound if ub is None else ub
+        lb = CONFIGURATION.lower_bound if lb is None else lb
         types = {
             "exchange": ("EX", lb, ub, sbo_terms["exchange"]),
             "demand": ("DM", 0, ub, sbo_terms["demand"]),
             "sink": ("SK", lb, ub, sbo_terms["sink"])
         }
+        if type == "exchange":
+            external = find_external_compartment(self)
+            if metabolite.compartment != external:
+                raise ValueError("The metabolite is not an external metabolite"
+                                 " (compartment is `%s` but should be `%s`). "
+                                 "Did you mean to add a demand or sink? "
+                                 "If not, either change its compartment or "
+                                 "rename the model compartments to fix this." %
+                                 (metabolite.compartment, external))
         if type in types:
             prefix, lb, ub, default_term = types[type]
             if reaction_id is None:


=====================================
cobra/medium/annotations.py
=====================================
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+"""Lists and annotations for compartment names and reactions.
+
+Please send a PR if you want to add something here :)
+"""
+
+excludes = {
+    "demand": ["SN_", "SK_", "sink", "EX_", "exchange"],
+    "exchange": ["demand", "DM_", "biosynthesis", "transcription",
+                 "replication", "SN_", "SK_", "sink"],
+    "sink": ["demand", "DM_", "biosynthesis", "transcription",
+             "replication", "EX_", "exchange"]
+}
+"""A list of sub-strings in reaction IDs that usually indicate
+that the reaction is *not* a reaction of the specified type."""
+
+sbo_terms = {"demand": "SBO:0000628",
+             "exchange": "SBO:0000627",
+             "sink": "SBO:0000632",
+             "biomass": "SBO:0000629",
+             "pseudoreaction": "SBO:0000631"}
+"""SBO term identifiers for various boundary types."""
+
+compartment_shortlist = {
+    "ce": ["cell envelope"],
+    "c": ["cytoplasm", "cytosol", "default", "in", "intra cellular",
+          "intracellular", "intracellular region", "intracellular space"],
+    "er": ["endoplasmic reticulum"],
+    "erm": ["endoplasmic reticulum membrane"],
+    "e": ["extracellular", "extraorganism", "out", "extracellular space",
+          "extra organism", "extra cellular", "extra-organism", "external",
+          "external medium"],
+    "f": ["flagellum", "bacterial-type flagellum"],
+    "g": ["golgi", "golgi apparatus"],
+    "gm": ["golgi membrane"],
+    "h": ["chloroplast"],
+    "l": ["lysosome"],
+    "im": ["mitochondrial intermembrane space"],
+    "mm": ["mitochondrial membrane"],
+    "m": ["mitochondrion", "mitochondria"],
+    "n": ["nucleus"],
+    "p": ["periplasm", "periplasmic space"],
+    "x": ["peroxisome", "glyoxysome"],
+    "u": ["thylakoid"],
+    "vm": ["vacuolar membrane"],
+    "v": ["vacuole"],
+    "w": ["cell wall"],
+    "s": ["eyespot", "eyespot apparatus", "stigma"]
+}
+"""A list of common compartment abbreviations and alternative names."""


=====================================
cobra/medium/boundary_types.py
=====================================
@@ -15,23 +15,12 @@ http://doi.org/10.1038/nprot.2009.203
 import logging
 from collections import Counter
 
+import pandas as pd
 
-LOGGER = logging.getLogger(__name__)
+from cobra.medium.annotations import compartment_shortlist, excludes, sbo_terms
 
-excludes = {"demand": ["SN_", "SK_", "sink", "EX_", "exchange"],
-            "exchange": ["demand", "DM_", "biosynthesis", "transcription",
-                         "replication", "SN_", "SK_", "sink"],
-            "sink": ["demand", "DM_", "biosynthesis", "transcription",
-                     "replication", "EX_", "exchange"]}
-"""A list of sub-strings in reaction IDs that usually indicate
-that the reaction is *not* a reaction of the specified type."""
 
-sbo_terms = {"demand": "SBO:0000628",
-             "exchange": "SBO:0000627",
-             "sink": "SBO:0000632",
-             "biomass": "SBO:0000629",
-             "pseudoreaction": "SBO:0000631"}
-"""SBO term identifiers for various boundary types."""
+LOGGER = logging.getLogger(__name__)
 
 
 def find_external_compartment(model):
@@ -50,25 +39,47 @@ def find_external_compartment(model):
     str
         The putative external compartment.
     """
-    if not model.boundary:
-        LOGGER.error("The heuristic for discovering an external compartment "
-                     "relies on boundary reactions. Yet, there are no "
-                     "boundary reactions in this model.")
-        raise RuntimeError(
-            "The external compartment cannot be identified. "
-            "The heuristic for discovering an external compartment "
-            "relies on boundary reactions. Yet, there are no "
-            "boundary reactions in this model.")
-    counts = Counter(tuple(r.compartments)[0] for r in model.boundary)
-    most = counts.most_common(1)[0][0]
-    if "e" in model.compartments:
-        if most == "e":
-            return "e"
-        else:
-            LOGGER.warning("There is an `e` compartment but it does not look "
-                           "like it is the actual external compartment.")
-        return most
-    return most
+    if model.boundary:
+        counts = pd.Series(tuple(r.compartments)[0] for r in model.boundary)
+        most = counts.value_counts()
+        most = most.index[most == most.max()].to_series()
+    else:
+        most = None
+    like_external = compartment_shortlist["e"] + ["e"]
+    matches = pd.Series([co in like_external for co in model.compartments],
+                        index=model.compartments)
+
+    if matches.sum() == 1:
+        compartment = matches.index[matches][0]
+        LOGGER.info("Compartment `%s` sounds like an external compartment. "
+                    "Using this one without counting boundary reactions" %
+                    compartment)
+        return compartment
+    elif most is not None and matches.sum() > 1 and matches[most].sum() == 1:
+        compartment = most[matches[most]][0]
+        LOGGER.warning("There are several compartments that look like an "
+                       "external compartment but `%s` has the most boundary "
+                       "reactions, so using that as the external "
+                       "compartment." % compartment)
+        return compartment
+    elif matches.sum() > 1:
+        raise RuntimeError("There are several compartments (%s) that look "
+                           "like external compartments but we can't tell "
+                           "which one to use. Consider renaming your "
+                           "compartments please.")
+
+    if most is not None:
+        return most[0]
+        LOGGER.warning("Could not identify an external compartment by name and"
+                       " choosing one with the most boundary reactions. That "
+                       "might be complete nonsense or change suddenly. "
+                       "Consider renaming your compartments using "
+                       "`Model.compartments` to fix this.")
+    # No info in the model, so give up
+    raise RuntimeError("The heuristic for discovering an external compartment "
+                       "relies on names and boundary reactions. Yet, there "
+                       "are neither compartments with recognized names nor "
+                       "boundary reactions in the model.")
 
 
 def is_boundary_type(reaction, boundary_type, external_compartment):


=====================================
cobra/test/test_medium.py
=====================================
@@ -6,7 +6,7 @@ import pandas as pd
 import pytest
 
 import cobra.medium as medium
-from cobra import Reaction
+from cobra import Metabolite, Reaction
 
 
 class TestModelMedium:
@@ -54,7 +54,30 @@ class TestModelMedium:
 class TestTypeDetection:
 
     def test_external_compartment(self, model):
+        # by name
         assert medium.find_external_compartment(model) == "e"
+        # from boundary counts
+        for m in model.metabolites:
+            if m.compartment == "e":
+                m.compartment = "outside"
+        for r in model.reactions:
+            r._compartments = None
+        assert medium.find_external_compartment(model) == "outside"
+        # names are always right
+        model.exchanges[0].reactants[0].compartment = "extracellular"
+        assert medium.find_external_compartment(model) == "extracellular"
+
+    def test_multi_external(self, model):
+        for r in model.reactions:
+            r._compartments = None
+        model.exchanges[0].reactants[0].compartment = "extracellular"
+        # still works due to different boundary numbers
+        assert medium.find_external_compartment(model) == "e"
+        model.exchanges[1].reactants[0].compartment = "extra cellular"
+        model.remove_reactions(model.exchanges)
+        # Now fails because same boundary count
+        with pytest.raises(RuntimeError):
+            medium.find_external_compartment(model)
 
     def test_exchange(self, model):
         ex = model.exchanges
@@ -145,6 +168,14 @@ class TestErrorsAndExceptions:
     def test_no_boundary_reactions(self, empty_model):
         assert medium.find_boundary_types(empty_model, 'e', None) == []
 
-    def test_no_boundary_reactions(self, empty_model):
+    def test_no_names_or_boundary_reactions(self, empty_model):
         with pytest.raises(RuntimeError):
             medium.find_external_compartment(empty_model)
+
+    def test_bad_exchange(self, model):
+        with pytest.raises(ValueError):
+            m = Metabolite("baddy", compartment="nonsense")
+            model.add_boundary(m, type="exchange")
+        m = Metabolite("goody", compartment="e")
+        rxn = model.add_boundary(m, type="exchange")
+        assert isinstance(rxn, Reaction)


=====================================
release-notes/0.14.2.md
=====================================
@@ -0,0 +1,7 @@
+# Release notes for cobrapy 0.14.2
+
+## Fixes
+
+* Better identification of the external compartment.
+* Fix the installation of all optional dependencies, i.e., `pip install cobra[all]`.
+


=====================================
setup.cfg
=====================================
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 0.14.1
+current_version = 0.14.2
 commit = True
 tag = True
 parse = (?P<major>\d+)


=====================================
setup.py
=====================================
@@ -2,10 +2,11 @@
 
 from __future__ import absolute_import
 
-from warnings import warn
 from sys import argv, version_info
+from warnings import warn
+
+from setuptools import find_packages, setup
 
-from setuptools import setup, find_packages
 
 if version_info[:2] == (3, 4):
     warn("Support for Python 3.4 was dropped by pandas. Since cobrapy is a "
@@ -23,7 +24,7 @@ extras = {
     'array': ["scipy"],
     'sbml': ["python-libsbml", "lxml"]
 }
-extras["all"] = sorted(list(extras))
+extras["all"] = sorted(extras.values())
 
 try:
     with open('README.rst') as handle:
@@ -37,7 +38,7 @@ except IOError:
 if __name__ == "__main__":
     setup(
         name="cobra",
-        version="0.14.1",
+        version="0.14.2",
         packages=find_packages(),
         setup_requires=setup_requirements,
         install_requires=[



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

-- 
View it on GitLab: https://salsa.debian.org/med-team/python-cobra/commit/6827160c7e8599626c94fe38b262b0ce78009c5b
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/20190207/b182c918/attachment-0001.html>


More information about the debian-med-commit mailing list