[med-svn] [python-cobra] 01/11: Imported Upstream version 0.4.0b7

Afif Elghraoui afif-guest at moszumanska.debian.org
Sat Feb 20 09:20:59 UTC 2016


This is an automated email from the git hooks/post-receive script.

afif-guest pushed a commit to branch master
in repository python-cobra.

commit 65201bdd5e55df669e4758b2424c9ea3ad07bf9e
Author: Afif Elghraoui <afif at ghraoui.name>
Date:   Fri Feb 19 20:48:28 2016 -0800

    Imported Upstream version 0.4.0b7
---
 .travis.yml                                       |   3 +-
 cobra/VERSION                                     |   2 +-
 cobra/core/ArrayBasedModel.py                     |   7 +-
 cobra/core/DictList.py                            |   3 +-
 cobra/core/Formula.py                             |   3 +-
 cobra/core/Gene.py                                |   4 +-
 cobra/core/Metabolite.py                          |   1 -
 cobra/core/Object.py                              |   3 -
 cobra/core/Reaction.py                            |  66 +++--
 cobra/core/Solution.py                            |   2 +-
 cobra/design/design_algorithms.py                 |   6 +-
 cobra/flux_analysis/phenotype_phase_plane.py      |   7 +-
 cobra/io/sbml.py                                  |   4 +
 cobra/manipulation/annotate.py                    |   2 +-
 cobra/test/data/mini.json                         |   2 +
 cobra/test/data/mini.mat                          | Bin 14600 -> 14600 bytes
 cobra/test/data/mini.pickle                       | Bin 25060 -> 25128 bytes
 cobra/test/data/mini_fbc1.xml                     |  20 +-
 cobra/test/data/mini_fbc2.xml                     |   5 +-
 cobra/test/data/mini_fbc2.xml.bz2                 | Bin 4957 -> 5008 bytes
 cobra/test/data/mini_fbc2.xml.gz                  | Bin 5670 -> 5719 bytes
 cobra/test/unit_tests.py                          |  25 +-
 cobra/topology/__init__.py                        |   2 +-
 documentation_builder/building_model.ipynb        | 107 ++++----
 documentation_builder/deletions.ipynb             | 306 ++++------------------
 documentation_builder/gapfilling.ipynb            |   3 +-
 documentation_builder/getting_started.ipynb       |  74 ++++--
 documentation_builder/io.ipynb                    |  33 ++-
 documentation_builder/loopless.ipynb              |  40 +--
 documentation_builder/milp.ipynb                  |  21 +-
 documentation_builder/phenotype_phase_plane.ipynb |  48 ++--
 documentation_builder/plot_helper.py              |  81 ++++++
 documentation_builder/pymatbridge.ipynb           |   2 +-
 documentation_builder/qp.ipynb                    |  48 +---
 documentation_builder/simulating.ipynb            |  77 ++++--
 documentation_builder/solvers.ipynb               |  46 ++--
 36 files changed, 509 insertions(+), 544 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 18c5fa3..8a45213 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,8 +24,7 @@ env:
 before_install:
   - pip install pip --upgrade
   # These get cached
-  - pip install numpy scipy python-libsbml -v  # verbose for long-running compiles
-  - pip install cython coveralls jsonschema six matplotlib
+  - pip install numpy scipy python-libsbml cython coveralls jsonschema six matplotlib
   - if [[ $TRAVIS_PYTHON_VERSION == 2* ]]; then pip install lxml glpk pep8 palettable; fi
   # Download esolver and add it to the path
   - wget https://opencobra.github.io/pypi_cobrapy_travis/esolver.gz
diff --git a/cobra/VERSION b/cobra/VERSION
index c259ae3..a9e3532 100644
--- a/cobra/VERSION
+++ b/cobra/VERSION
@@ -1 +1 @@
-0.4.0b6
+0.4.0b7
diff --git a/cobra/core/ArrayBasedModel.py b/cobra/core/ArrayBasedModel.py
index 696b2bc..71d463d 100644
--- a/cobra/core/ArrayBasedModel.py
+++ b/cobra/core/ArrayBasedModel.py
@@ -1,12 +1,11 @@
 from sys import maxsize
-from copy import deepcopy
 from warnings import warn
+from six import iteritems
 
-from numpy import array, hstack, ndarray
+from numpy import array, ndarray
 from scipy.sparse import lil_matrix, dok_matrix
 
 from .Model import Model
-from six import iteritems
 
 
 class ArrayBasedModel(Model):
@@ -76,7 +75,7 @@ class ArrayBasedModel(Model):
         return self._b
 
     @b.setter
-    def b(self, b):
+    def b(self, vector):
         self._update_from_vector("b", vector)
 
     @property
diff --git a/cobra/core/DictList.py b/cobra/core/DictList.py
index 70619a5..8925965 100644
--- a/cobra/core/DictList.py
+++ b/cobra/core/DictList.py
@@ -1,7 +1,6 @@
-from copy import copy, deepcopy
 import re
-from six import string_types, iteritems, PY3
 from itertools import islice
+from six import string_types, iteritems, PY3
 
 try:
     from numpy import bool_
diff --git a/cobra/core/Formula.py b/cobra/core/Formula.py
index d17f72f..005bb49 100644
--- a/cobra/core/Formula.py
+++ b/cobra/core/Formula.py
@@ -1,6 +1,6 @@
 import re
 from warnings import warn
-from copy import deepcopy
+
 from .Object import Object
 
 # Numbers are not required because of the |(?=[A-Z])? block. See the
@@ -68,7 +68,6 @@ class Formula(Object):
     @property
     def weight(self):
         """Calculate the formula weight"""
-        weight_dict = elements_and_molecular_weights
         try:
             return sum([count * elements_and_molecular_weights[element]
                         for element, count in self.elements.items()])
diff --git a/cobra/core/Gene.py b/cobra/core/Gene.py
index 7e97534..797c24d 100644
--- a/cobra/core/Gene.py
+++ b/cobra/core/Gene.py
@@ -1,7 +1,7 @@
 import re
 from warnings import warn
-from ast import parse as ast_parse, Name, And, Or, BitOr, BitAnd, BinOp, \
-    BoolOp, Attribute, Expression, NodeTransformer
+from ast import parse as ast_parse, Name, And, Or, BitOr, BitAnd, \
+    BoolOp, Expression, NodeTransformer
 from keyword import kwlist
 
 from .Species import Species
diff --git a/cobra/core/Metabolite.py b/cobra/core/Metabolite.py
index e1a46fb..4a5875d 100644
--- a/cobra/core/Metabolite.py
+++ b/cobra/core/Metabolite.py
@@ -82,7 +82,6 @@ class Metabolite(Species):
     @property
     def formula_weight(self):
         """Calculate the formula weight"""
-        weight_dict = elements_and_molecular_weights
         try:
             return sum([count * elements_and_molecular_weights[element]
                         for element, count in self.elements.items()])
diff --git a/cobra/core/Object.py b/cobra/core/Object.py
index 667c4e1..ab23ed3 100644
--- a/cobra/core/Object.py
+++ b/cobra/core/Object.py
@@ -1,6 +1,3 @@
-from six import iteritems
-
-
 class Object(object):
     """Defines common behavior of object in cobra.core"""
 
diff --git a/cobra/core/Reaction.py b/cobra/core/Reaction.py
index 119db1f..d8f80fc 100644
--- a/cobra/core/Reaction.py
+++ b/cobra/core/Reaction.py
@@ -28,6 +28,15 @@ class Frozendict(dict):
         raise NotImplementedError("read-only")
 
 
+def _is_positive(n):
+    try:
+        if n >= 0:
+            return True
+        else:
+            return False
+    except:
+        return True
+
 # precompiled regular expressions
 # Matches and/or in a gene reaction rule
 and_or_search = re.compile(r'\(| and| or|\+|\)', re.IGNORECASE)
@@ -394,12 +403,12 @@ class Reaction(Object):
     @property
     def reactants(self):
         """Return a list of reactants for the reaction."""
-        return [k for k, v in self._metabolites.items() if v < 0]
+        return [k for k, v in self._metabolites.items() if not _is_positive(v)]
 
     @property
     def products(self):
         """Return a list of products for the reaction"""
-        return [k for k, v in self._metabolites.items() if v > 0]
+        return [k for k, v in self._metabolites.items() if _is_positive(v)]
 
     def get_coefficient(self, metabolite_id):
         """Return the stoichiometric coefficient for a metabolite in
@@ -432,7 +441,7 @@ class Reaction(Object):
         from the reaction.
 
         metabolites: dict
-            {:class:`~cobra.core.Metabolite.Metabolite`: coefficient}
+            {str or :class:`~cobra.core.Metabolite.Metabolite`: coefficient}
 
         combine: Boolean.
             Describes behavior a metabolite already exists in the reaction.
@@ -445,13 +454,14 @@ class Reaction(Object):
             the reaction is associated with (i.e. self.model)
 
         """
-        _id_to_metabolites = {x.id: x for x in self._metabolites}
+        _id_to_metabolites = {str(x): x for x in self._metabolites}
         new_metabolites = []
         for metabolite, coefficient in iteritems(metabolites):
+            met_id = str(metabolite)
             # If a metabolite already exists in the reaction then
             # just add them.
-            if metabolite.id in _id_to_metabolites:
-                reaction_metabolite = _id_to_metabolites[metabolite.id]
+            if met_id in _id_to_metabolites:
+                reaction_metabolite = _id_to_metabolites[met_id]
                 if combine:
                     self._metabolites[reaction_metabolite] += coefficient
                 else:
@@ -459,11 +469,20 @@ class Reaction(Object):
             else:
                 # If the reaction is in a model, ensure we aren't using
                 # a duplicate metabolite.
-                try:
-                    metabolite = \
-                        self._model.metabolites.get_by_id(metabolite.id)
-                except:
-                    new_metabolites.append(metabolite)
+                if self._model:
+                    try:
+                        metabolite = \
+                            self._model.metabolites.get_by_id(met_id)
+                    except KeyError as e:
+                        if isinstance(metabolite, Metabolite):
+                            new_metabolites.append(metabolite)
+                        else:
+                            # do we want to handle creation here?
+                            raise e
+                elif isinstance(metabolite, string_types):
+                    # if we want to handle creation, this should be changed
+                    raise ValueError("reaction '%s' does not belong to a model"
+                                     % self.id)
                 self._metabolites[metabolite] = coefficient
                 # make the metabolite aware that it is involved in this
                 # reaction
@@ -508,8 +527,6 @@ class Reaction(Object):
         """Generate a human readable reaction string"""
         def format(number):
             return "" if number == 1 else str(number).rstrip(".") + " "
-        reactant_dict = {}
-        product_dict = {}
         id_type = 'id'
         if use_metabolite_names:
             id_type = 'name'
@@ -517,7 +534,7 @@ class Reaction(Object):
         product_bits = []
         for the_metabolite, coefficient in iteritems(self._metabolites):
             name = str(getattr(the_metabolite, id_type))
-            if coefficient > 0:
+            if _is_positive(coefficient):
                 product_bits.append(format(coefficient) + name)
             else:
                 reactant_bits.append(format(abs(coefficient)) + name)
@@ -581,6 +598,26 @@ class Reaction(Object):
     def build_reaction_from_string(self, reaction_str, verbose=True,
                                    fwd_arrow=None, rev_arrow=None,
                                    reversible_arrow=None, term_split="+"):
+        """Builds reaction from reaction equation reaction_str using parser
+
+        Takes a string and using the specifications supplied in the optional
+        arguments infers a set of metabolites, metabolite compartments and
+        stoichiometries for the reaction.  It also infers the reversibility
+        of the reaction from the reaction arrow.
+
+        Args:
+            reaction_str: a string containing a reaction formula (equation)
+            verbose: Boolean setting verbosity of function
+                (optional, default=True)
+            fwd_arrow: re.compile for forward irreversible reaction arrows
+                (optional, default=_forward_arrow_finder)
+            reverse_arrow: re.compile for backward irreversible reaction arrows
+                (optional, default=_reverse_arrow_finder)
+            fwd_arrow: re.compile for reversible reaction arrows
+                (optional, default=_reversible_arrow_finder)
+            term_split: String dividing individual metabolite entries
+                (optional, default='+')
+        """
         # set the arrows
         forward_arrow_finder = _forward_arrow_finder if fwd_arrow is None \
             else re.compile(re.escape(fwd_arrow))
@@ -594,7 +631,6 @@ class Reaction(Object):
             model = None
         else:
             model = self._model
-        original_str = "" + reaction_str  # copy
         found_compartments = compartment_finder.findall(reaction_str)
         if len(found_compartments) == 1:
             compartment = found_compartments[0]
diff --git a/cobra/core/Solution.py b/cobra/core/Solution.py
index a912ddd..c7ca72f 100644
--- a/cobra/core/Solution.py
+++ b/cobra/core/Solution.py
@@ -30,7 +30,7 @@ class Solution(object):
 
     def dress_results(self, model):
         """.. warning :: deprecated"""
-        from warning import warn
+        from warnings import warn
         warn("unnecessary to call this deprecated function")
 
     def __repr__(self):
diff --git a/cobra/design/design_algorithms.py b/cobra/design/design_algorithms.py
index 4a6c345..cd38b43 100644
--- a/cobra/design/design_algorithms.py
+++ b/cobra/design/design_algorithms.py
@@ -100,7 +100,7 @@ def set_up_optknock(model, chemical_objective, knockable_reactions,
         reaction.objective_coefficient = 0
         if reaction.id in model.reactions:
             existing_reaction = model.reactions.get_by_id(reaction.id)
-            for met, coeff in iteritems(reaction.metabolites):
+            for met, coeff in iteritems(reaction._metabolites):
                 if met.id in model.metabolites:
                     existing_reaction.add_metabolites(
                         {model.metabolites.get_by_id(met.id): coeff})
@@ -346,7 +346,7 @@ def dual_problem(model, objective_sense="maximize",
                                 reaction.id)  # (6)
             constr._constraint_sense = "L"
             constr._bound = - reaction.objective_coefficient
-            for met, coeff in iteritems(reaction.metabolites):
+            for met, coeff in iteritems(reaction._metabolites):
                 dual_var = dual_var_for_met[met.id]
                 dual_var.add_metabolites({constr: - coeff})
 
@@ -363,7 +363,7 @@ def dual_problem(model, objective_sense="maximize",
 
     # add auxiliary variables
     for integer_var, original_reaction in integer_vars_added:
-        for metabolite, coeff in iteritems(original_reaction.metabolites):
+        for metabolite, coeff in iteritems(original_reaction._metabolites):
             dual_var = dual_var_for_met[metabolite.id]
             # create an auxiliary variable
             aux_var = Reaction("%s__auxiliary__%s" % (integer_var.id,
diff --git a/cobra/flux_analysis/phenotype_phase_plane.py b/cobra/flux_analysis/phenotype_phase_plane.py
index aeb937d..b82d6f7 100644
--- a/cobra/flux_analysis/phenotype_phase_plane.py
+++ b/cobra/flux_analysis/phenotype_phase_plane.py
@@ -93,10 +93,11 @@ class phenotypePhasePlaneData:
                           antialiased=False)
         axes.plot_wireframe(xgrid, ygrid, self.growth_rates, color="black",
                             rstride=xgrid_scale, cstride=ygrid_scale)
-        axes.set_xlabel(self.reaction1_name)
-        axes.set_ylabel(self.reaction2_name)
-        axes.set_zlabel("Growth rate")
+        axes.set_xlabel(self.reaction1_name, size="x-large")
+        axes.set_ylabel(self.reaction2_name, size="x-large")
+        axes.set_zlabel("Growth rate", size="x-large")
         axes.view_init(elev=30, azim=-135)
+        figure.tight_layout()
         return axes
 
     def plot_mayavi(self):
diff --git a/cobra/io/sbml.py b/cobra/io/sbml.py
index eb5ecde..c4cf4cf 100644
--- a/cobra/io/sbml.py
+++ b/cobra/io/sbml.py
@@ -154,6 +154,10 @@ def create_cobra_model_from_sbml_file(sbml_filename, old_sbml=False, legacy_meta
                     msg = "different charges specified for %s (%d and %d)"
                     msg = msg % (tmp_metabolite.id, tmp_metabolite.charge, note_charge)
                     warn(msg)
+                    # Chances are a 0 note charge was written by mistake. We
+                    # will default to the note_charge in this case.
+                    if tmp_metabolite.charge == 0:
+                        tmp_metabolite.charge = note_charge
 
         for the_key in tmp_metabolite.notes.keys():
             if the_key.lower() == 'formula':
diff --git a/cobra/manipulation/annotate.py b/cobra/manipulation/annotate.py
index 715107a..a6fd785 100644
--- a/cobra/manipulation/annotate.py
+++ b/cobra/manipulation/annotate.py
@@ -17,7 +17,7 @@ def add_SBO(model):
         # only doing exchanges
         if len(r.metabolites) != 1:
             continue
-        met_id = list(r.metabolites)[0].id
+        met_id = list(r._metabolites)[0].id
         if r.id.startswith("EX_") and r.id == "EX_" + met_id:
             r.annotation["SBO"] = "SBO:0000627"
         elif r.id.startswith("DM_") and r.id == "DM_" + met_id:
diff --git a/cobra/test/data/mini.json b/cobra/test/data/mini.json
index 85ea068..a6234f9 100644
--- a/cobra/test/data/mini.json
+++ b/cobra/test/data/mini.json
@@ -1140,6 +1140,7 @@
         },
         {
             "annotation": {
+                "SBO": "SBO:0000627",
                 "bigg.reaction": "glc"
             },
             "gene_reaction_rule": "",
@@ -1153,6 +1154,7 @@
         },
         {
             "annotation": {
+                "SBO": "SBO:0000627",
                 "bigg.reaction": "h"
             },
             "gene_reaction_rule": "",
diff --git a/cobra/test/data/mini.mat b/cobra/test/data/mini.mat
index d0f5128..5c3e857 100644
Binary files a/cobra/test/data/mini.mat and b/cobra/test/data/mini.mat differ
diff --git a/cobra/test/data/mini.pickle b/cobra/test/data/mini.pickle
index 5b5cb8a..922c455 100644
Binary files a/cobra/test/data/mini.pickle and b/cobra/test/data/mini.pickle differ
diff --git a/cobra/test/data/mini_fbc1.xml b/cobra/test/data/mini_fbc1.xml
index ae48616..9209063 100644
--- a/cobra/test/data/mini_fbc1.xml
+++ b/cobra/test/data/mini_fbc1.xml
@@ -312,9 +312,9 @@
           <speciesReference species="M_h2o_c" stoichiometry="1" constant="true"/>
         </listOfReactants>
         <listOfProducts>
-          <speciesReference species="M_adp_c" stoichiometry="1" constant="true"/>
-          <speciesReference species="M_h_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_pi_c" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_h_c" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_adp_c" stoichiometry="1" constant="true"/>
         </listOfProducts>
       </reaction>
       <reaction id="R_D_LACt2" name="D_LACt2" reversible="true" fast="false">
@@ -328,8 +328,8 @@
           <speciesReference species="M_lac__D_e" stoichiometry="1" constant="true"/>
         </listOfReactants>
         <listOfProducts>
-          <speciesReference species="M_lac__D_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_h_c" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_lac__D_c" stoichiometry="1" constant="true"/>
         </listOfProducts>
       </reaction>
       <reaction id="R_ENO" name="enolase" reversible="true" fast="false">
@@ -342,8 +342,8 @@
           <speciesReference species="M_2pg_c" stoichiometry="1" constant="true"/>
         </listOfReactants>
         <listOfProducts>
-          <speciesReference species="M_pep_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_h2o_c" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_pep_c" stoichiometry="1" constant="true"/>
         </listOfProducts>
       </reaction>
       <reaction id="R_EX_glc__D_e" name="D-Glucose exchange" reversible="true" fast="false">
@@ -391,13 +391,13 @@
           </html>
         </notes>
         <listOfReactants>
-          <speciesReference species="M_g3p_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_nad_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_pi_c" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_g3p_c" stoichiometry="1" constant="true"/>
         </listOfReactants>
         <listOfProducts>
-          <speciesReference species="M_h_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_13dpg_c" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_h_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_nadh_c" stoichiometry="1" constant="true"/>
         </listOfProducts>
       </reaction>
@@ -408,12 +408,12 @@
           </html>
         </notes>
         <listOfReactants>
-          <speciesReference species="M_pep_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_glc__D_e" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_pep_c" stoichiometry="1" constant="true"/>
         </listOfReactants>
         <listOfProducts>
-          <speciesReference species="M_pyr_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_g6p_c" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_pyr_c" stoichiometry="1" constant="true"/>
         </listOfProducts>
       </reaction>
       <reaction id="R_H2Ot" name="R H2O transport via - diffusion" reversible="true" fast="false">
@@ -436,8 +436,8 @@
           </html>
         </notes>
         <listOfReactants>
-          <speciesReference species="M_lac__D_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_nad_c" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_lac__D_c" stoichiometry="1" constant="true"/>
         </listOfReactants>
         <listOfProducts>
           <speciesReference species="M_h_c" stoichiometry="1" constant="true"/>
@@ -524,8 +524,8 @@
           </html>
         </notes>
         <listOfReactants>
-          <speciesReference species="M_adp_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_h_c" stoichiometry="1" constant="true"/>
+          <speciesReference species="M_adp_c" stoichiometry="1" constant="true"/>
           <speciesReference species="M_pep_c" stoichiometry="1" constant="true"/>
         </listOfReactants>
         <listOfProducts>
diff --git a/cobra/test/data/mini_fbc2.xml b/cobra/test/data/mini_fbc2.xml
index fb0f57f..303499b 100644
--- a/cobra/test/data/mini_fbc2.xml
+++ b/cobra/test/data/mini_fbc2.xml
@@ -1,3 +1,4 @@
+<?xml version='1.0' encoding='UTF-8'?>
 <sbml xmlns:fbc="http://www.sbml.org/sbml/level3/version1/fbc/version2" level="3" sboTerm="SBO:0000624" version="1" xmlns="http://www.sbml.org/sbml/level3/version1/core" fbc:required="false">
   <model fbc:strict="true" id="mini_textbook">
     <listOfUnitDefinitions>
@@ -1011,7 +1012,7 @@
           <fbc:geneProductRef fbc:geneProduct="G_b2779"/>
         </fbc:geneProductAssociation>
       </reaction>
-      <reaction fast="false" id="R_EX_glc__D_e" reversible="true" name="D-Glucose exchange" metaid="R_EX_glc__D_e" fbc:upperFluxBound="cobra_default_ub" fbc:lowerFluxBound="R_EX_glc__D_e_lower_bound">
+      <reaction fast="false" id="R_EX_glc__D_e" reversible="true" name="D-Glucose exchange" metaid="R_EX_glc__D_e" sboTerm="SBO:0000627" fbc:upperFluxBound="cobra_default_ub" fbc:lowerFluxBound="R_EX_glc__D_e_lower_bound">
         <sbml:annotation xmlns:sbml="http://www.sbml.org/sbml/level3/version1/core">
           <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
             <rdf:Description rdf:about="#R_EX_glc__D_e">
@@ -1027,7 +1028,7 @@
           <speciesReference constant="true" species="M_glc__D_e" stoichiometry="1"/>
         </listOfReactants>
       </reaction>
-      <reaction fast="false" id="R_EX_h_e" reversible="true" name="H+ exchange" metaid="R_EX_h_e" fbc:upperFluxBound="cobra_default_ub" fbc:lowerFluxBound="cobra_default_lb">
+      <reaction fast="false" id="R_EX_h_e" reversible="true" name="H+ exchange" metaid="R_EX_h_e" sboTerm="SBO:0000627" fbc:upperFluxBound="cobra_default_ub" fbc:lowerFluxBound="cobra_default_lb">
         <sbml:annotation xmlns:sbml="http://www.sbml.org/sbml/level3/version1/core">
           <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
             <rdf:Description rdf:about="#R_EX_h_e">
diff --git a/cobra/test/data/mini_fbc2.xml.bz2 b/cobra/test/data/mini_fbc2.xml.bz2
index b121d7d..7fe05c6 100644
Binary files a/cobra/test/data/mini_fbc2.xml.bz2 and b/cobra/test/data/mini_fbc2.xml.bz2 differ
diff --git a/cobra/test/data/mini_fbc2.xml.gz b/cobra/test/data/mini_fbc2.xml.gz
index 7ce91bc..89af7b4 100644
Binary files a/cobra/test/data/mini_fbc2.xml.gz and b/cobra/test/data/mini_fbc2.xml.gz differ
diff --git a/cobra/test/unit_tests.py b/cobra/test/unit_tests.py
index 1edc147..f673d50 100644
--- a/cobra/test/unit_tests.py
+++ b/cobra/test/unit_tests.py
@@ -293,17 +293,32 @@ class TestReactions(CobraTestCase):
         self.assertEqual(reaction.gene_name_reaction_rule, fake_gene.name)
 
     def test_add_metabolite(self):
-        """adding a metabolite to a reaction in a model"""
         model = self.model
         reaction = model.reactions.get_by_id("PGI")
         reaction.add_metabolites({model.metabolites[0]: 1})
-        self.assertIn(model.metabolites[0], reaction.metabolites)
+        self.assertIn(model.metabolites[0], reaction._metabolites)
         fake_metabolite = Metabolite("fake")
         reaction.add_metabolites({fake_metabolite: 1})
-        self.assertIn(fake_metabolite, reaction.metabolites)
+        self.assertIn(fake_metabolite, reaction._metabolites)
         self.assertTrue(model.metabolites.has_id("fake"))
         self.assertIs(model.metabolites.get_by_id("fake"), fake_metabolite)
 
+        # test adding by string
+        reaction.add_metabolites({"g6p_c": -1})  # already in reaction
+        self.assertTrue(
+            reaction._metabolites[model.metabolites.get_by_id("g6p_c")], -2)
+        reaction.add_metabolites({"h_c": 1})  # not currently in reaction
+        self.assertTrue(
+            reaction._metabolites[model.metabolites.get_by_id("h_c")], 1)
+        with self.assertRaises(KeyError):
+            reaction.add_metabolites({"missing": 1})
+
+        # test adding to a new Reaction
+        reaction = Reaction("test")
+        self.assertEqual(len(reaction._metabolites), 0)
+        reaction.add_metabolites({Metabolite("test_met"): -1})
+        self.assertEqual(len(reaction._metabolites), 1)
+
     def test_subtract_metabolite(self):
         model = self.model
         reaction = model.reactions.get_by_id("PGI")
@@ -538,7 +553,7 @@ class TestCobraModel(CobraTestCase):
         _metabolites = []
         for x in _model.reactions:
             _genes.extend(x.genes)
-            _metabolites.extend(x.metabolites)
+            _metabolites.extend(x._metabolites)
 
         orphan_genes = [x for x in _genes if x.model is not _model]
         orphan_metabolites = [x for x in _metabolites if x.model is not _model]
@@ -595,7 +610,7 @@ class TestCobraArrayModel(TestCobraModel):
             model.S[43, 0] = 1
             assertEqual(model.S[43, 0], 1)
             assertEqual(
-                model.reactions[0].metabolites[model.metabolites[43]], 1)
+                model.reactions[0]._metabolites[model.metabolites[43]], 1)
             model.S[43, 0] = 0
             assertEqual(model.lower_bounds[0], model.reactions[0].lower_bound)
             assertEqual(model.lower_bounds[5], model.reactions[5].lower_bound)
diff --git a/cobra/topology/__init__.py b/cobra/topology/__init__.py
index 03a7c46..6446300 100644
--- a/cobra/topology/__init__.py
+++ b/cobra/topology/__init__.py
@@ -5,5 +5,5 @@ if __name == 'java':
     warn("%s is not yet supported on jython"%__modules[__name__])
 
 else:
-    from reporter_metabolites import *
+    from .reporter_metabolites import *
 del __name, __modules
diff --git a/documentation_builder/building_model.ipynb b/documentation_builder/building_model.ipynb
index 0afc2af..9ff3d19 100644
--- a/documentation_builder/building_model.ipynb
+++ b/documentation_builder/building_model.ipynb
@@ -50,30 +50,36 @@
    },
    "outputs": [],
    "source": [
-    "ACP_c = Metabolite('ACP_c',\n",
-    "                   formula='C11H21N2O7PRS',\n",
-    "                   name='acyl-carrier-protein',\n",
-    "                   compartment='c')\n",
-    "omrsACP_c = Metabolite('3omrsACP_c',\n",
-    "                       formula='C25H45N2O9PRS',\n",
-    "                       name='3-Oxotetradecanoyl-acyl-carrier-protein',\n",
-    "                       compartment='c')\n",
-    "co2_c = Metabolite('co2_c',\n",
-    "                   formula='CO2',\n",
-    "                   name='CO2',\n",
-    "                   compartment='c')\n",
-    "malACP_c = Metabolite('malACP_c',\n",
-    "                      formula='C14H22N2O10PRS',\n",
-    "                      name='Malonyl-acyl-carrier-protein',\n",
-    "                      compartment='c')\n",
-    "h_c = Metabolite('h_c',\n",
-    "                 formula='H',\n",
-    "                 name='H',\n",
-    "                 compartment='c')\n",
-    "ddcaACP_c = Metabolite('ddcaACP_c',\n",
-    "                       formula='C23H43N2O8PRS',\n",
-    "                       name='Dodecanoyl-ACP-n-C120ACP',\n",
-    "                       compartment='c')"
+    "ACP_c = Metabolite(\n",
+    "    'ACP_c',\n",
+    "    formula='C11H21N2O7PRS',\n",
+    "    name='acyl-carrier-protein',\n",
+    "    compartment='c')\n",
+    "omrsACP_c = Metabolite(\n",
+    "    '3omrsACP_c',\n",
+    "    formula='C25H45N2O9PRS',\n",
+    "    name='3-Oxotetradecanoyl-acyl-carrier-protein',\n",
+    "    compartment='c')\n",
+    "co2_c = Metabolite(\n",
+    "    'co2_c',\n",
+    "    formula='CO2',\n",
+    "    name='CO2',\n",
+    "    compartment='c')\n",
+    "malACP_c = Metabolite(\n",
+    "    'malACP_c',\n",
+    "    formula='C14H22N2O10PRS',\n",
+    "    name='Malonyl-acyl-carrier-protein',\n",
+    "    compartment='c')\n",
+    "h_c = Metabolite(\n",
+    "    'h_c',\n",
+    "    formula='H',\n",
+    "    name='H',\n",
+    "    compartment='c')\n",
+    "ddcaACP_c = Metabolite(\n",
+    "    'ddcaACP_c',\n",
+    "    formula='C23H43N2O8PRS',\n",
+    "    name='Dodecanoyl-ACP-n-C120ACP',\n",
+    "    compartment='c')"
    ]
   },
   {
@@ -93,7 +99,7 @@
     {
      "data": {
       "text/plain": [
-       "'malACP_c + h_c + ddcaACP_c --> 3omrsACP_c + ACP_c + co2_c'"
+       "'malACP_c + h_c + ddcaACP_c --> co2_c + 3omrsACP_c + ACP_c'"
       ]
      },
      "execution_count": 3,
@@ -130,7 +136,7 @@
     {
      "data": {
       "text/plain": [
-       "frozenset({<Gene STM1197 at 0x7feea0ae9850>, <Gene STM2378 at 0x7feea0ae9b10>})"
+       "frozenset({<Gene STM2378 at 0x7ff664f45490>, <Gene STM1197 at 0x7ff664f45950>})"
       ]
      },
      "execution_count": 4,
@@ -161,16 +167,16 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "0 reactions in initial model\n",
-      "0 metabolites in initial model\n",
-      "0 genes in initial model\n"
+      "0 reactions initially\n",
+      "0 metabolites initially\n",
+      "0 genes initially\n"
      ]
     }
    ],
    "source": [
-    "print('%i reactions in initial model' % len(cobra_model.reactions))\n",
-    "print('%i metabolites in initial model' % len(cobra_model.metabolites))\n",
-    "print('%i genes in initial model' % len(cobra_model.genes))"
+    "print('%i reactions initially' % len(cobra_model.reactions))\n",
+    "print('%i metabolites initially' % len(cobra_model.metabolites))\n",
+    "print('%i genes initially' % len(cobra_model.genes))"
    ]
   },
   {
@@ -191,9 +197,9 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "1 reaction in model\n",
-      "6 metabolites in model\n",
-      "2 genes in model\n"
+      "1 reaction\n",
+      "6 metabolites\n",
+      "2 genes\n"
      ]
     }
    ],
@@ -201,9 +207,9 @@
     "cobra_model.add_reaction(reaction)\n",
     "\n",
     "# Now there are things in the model\n",
-    "print('%i reaction in model' % len(cobra_model.reactions))\n",
-    "print('%i metabolites in model' % len(cobra_model.metabolites))\n",
-    "print('%i genes in model' % len(cobra_model.genes))"
+    "print('%i reaction' % len(cobra_model.reactions))\n",
+    "print('%i metabolites' % len(cobra_model.metabolites))\n",
+    "print('%i genes' % len(cobra_model.genes))"
    ]
   },
   {
@@ -226,15 +232,17 @@
      "text": [
       "Reactions\n",
       "---------\n",
-      "3OAS140 : malACP_c + h_c + ddcaACP_c --> 3omrsACP_c + ACP_c + co2_c\n",
+      "3OAS140 : malACP_c + h_c + ddcaACP_c --> co2_c + 3omrsACP_c + ACP_c\n",
+      "\n",
       "Metabolites\n",
       "-----------\n",
-      "3omrsACP_c : C25H45N2O9PRS\n",
-      "ACP_c : C11H21N2O7PRS\n",
-      "co2_c : CO2\n",
-      "malACP_c : C14H22N2O10PRS\n",
-      "h_c : H\n",
+      "    co2_c : CO2\n",
+      " malACP_c : C14H22N2O10PRS\n",
+      "      h_c : H\n",
       "ddcaACP_c : C23H43N2O8PRS\n",
+      "3omrsACP_c : C25H45N2O9PRS\n",
+      "    ACP_c : C11H21N2O7PRS\n",
+      "\n",
       "Genes\n",
       "-----\n",
       "STM2378 is associated with reactions: {3OAS140}\n",
@@ -248,15 +256,20 @@
     "print(\"---------\")\n",
     "for x in cobra_model.reactions:\n",
     "    print(\"%s : %s\" % (x.id, x.reaction))\n",
+    "\n",
+    "print(\"\")\n",
     "print(\"Metabolites\")\n",
     "print(\"-----------\")\n",
     "for x in cobra_model.metabolites:\n",
-    "    print('%s : %s' % (x.id, x.formula))\n",
+    "    print('%9s : %s' % (x.id, x.formula))\n",
+    "\n",
+    "print(\"\")\n",
     "print(\"Genes\")\n",
     "print(\"-----\")\n",
     "for x in cobra_model.genes:\n",
-    "    reactions_list_str = \"{\" + \", \".join((i.id for i in x.reactions)) + \"}\"\n",
-    "    print(\"%s is associated with reactions: %s\" % (x.id, reactions_list_str))"
+    "    associated_ids = (i.id for i in x.reactions)\n",
+    "    print(\"%s is associated with reactions: %s\" %\n",
+    "          (x.id, \"{\" + \", \".join(associated_ids) + \"}\"))"
    ]
   }
  ],
diff --git a/documentation_builder/deletions.ipynb b/documentation_builder/deletions.ipynb
index b55bfb3..bcf1e4e 100644
--- a/documentation_builder/deletions.ipynb
+++ b/documentation_builder/deletions.ipynb
@@ -19,6 +19,9 @@
     "from time import time\n",
     "\n",
     "import cobra.test\n",
+    "from cobra.flux_analysis import \\\n",
+    "    single_gene_deletion, single_reaction_deletion, \\\n",
+    "    double_gene_deletion, double_reaction_deletion\n",
     "\n",
     "cobra_model = cobra.test.create_test_model(\"textbook\")\n",
     "ecoli_model = cobra.test.create_test_model(\"ecoli\")"
@@ -46,7 +49,7 @@
    },
    "outputs": [],
    "source": [
-    "growth_rates, statuses = cobra.flux_analysis.single_gene_deletion(cobra_model)"
+    "growth_rates, statuses = single_gene_deletion(cobra_model)"
    ]
   },
   {
@@ -147,27 +150,27 @@
        "      <td>optimal</td>\n",
        "    </tr>\n",
        "    <tr>\n",
-       "      <th>b3734</th>\n",
+       "      <th>b3732</th>\n",
        "      <td>0.374230</td>\n",
        "      <td>optimal</td>\n",
        "    </tr>\n",
        "    <tr>\n",
-       "      <th>b3735</th>\n",
+       "      <th>b3733</th>\n",
        "      <td>0.374230</td>\n",
        "      <td>optimal</td>\n",
        "    </tr>\n",
        "    <tr>\n",
-       "      <th>b3736</th>\n",
+       "      <th>b3734</th>\n",
        "      <td>0.374230</td>\n",
        "      <td>optimal</td>\n",
        "    </tr>\n",
        "    <tr>\n",
-       "      <th>b3737</th>\n",
+       "      <th>b3735</th>\n",
        "      <td>0.374230</td>\n",
        "      <td>optimal</td>\n",
        "    </tr>\n",
        "    <tr>\n",
-       "      <th>b3738</th>\n",
+       "      <th>b3736</th>\n",
        "      <td>0.374230</td>\n",
        "      <td>optimal</td>\n",
        "    </tr>\n",
@@ -196,11 +199,11 @@
        "b2296      0.873922  optimal\n",
        "b2587      0.873922  optimal\n",
        "b3115      0.873922  optimal\n",
+       "b3732      0.374230  optimal\n",
+       "b3733      0.374230  optimal\n",
        "b3734      0.374230  optimal\n",
        "b3735      0.374230  optimal\n",
        "b3736      0.374230  optimal\n",
-       "b3737      0.374230  optimal\n",
-       "b3738      0.374230  optimal\n",
        "s0001      0.211141  optimal"
       ]
      },
@@ -210,8 +213,10 @@
     }
    ],
    "source": [
-    "growth_rates, statuses = cobra.flux_analysis.single_gene_deletion(cobra_model, cobra_model.genes[:20])\n",
-    "pandas.DataFrame.from_dict({\"growth_rates\": growth_rates, \"status\": statuses})"
+    "gr, st = single_gene_deletion(cobra_model,\n",
+    "                              cobra_model.genes[:20])\n",
+    "pandas.DataFrame.from_dict({\"growth_rates\": gr,\n",
+    "                            \"status\": st})"
    ]
   },
   {
@@ -375,8 +380,10 @@
     }
    ],
    "source": [
-    "growth_rates, statuses = cobra.flux_analysis.single_reaction_deletion(cobra_model, cobra_model.reactions[:20])\n",
-    "pandas.DataFrame.from_dict({\"growth_rates\": growth_rates, \"status\": statuses})"
+    "gr, st = single_reaction_deletion(cobra_model,\n",
+    "                                  cobra_model.reactions[:20])\n",
+    "pandas.DataFrame.from_dict({\"growth_rates\": gr,\n",
+    "                            \"status\": st})"
    ]
   },
   {
@@ -403,11 +410,6 @@
        "  <thead>\n",
        "    <tr style=\"text-align: right;\">\n",
        "      <th></th>\n",
-       "      <th>b0724</th>\n",
-       "      <th>b0723</th>\n",
-       "      <th>b0721</th>\n",
-       "      <th>b0729</th>\n",
-       "      <th>b0728</th>\n",
        "      <th>b2464</th>\n",
        "      <th>b0008</th>\n",
        "      <th>b2935</th>\n",
@@ -417,77 +419,7 @@
        "  </thead>\n",
        "  <tbody>\n",
        "    <tr>\n",
-       "      <th>b0724</th>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.704037</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>b0723</th>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.704037</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>b0721</th>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.704037</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>b0729</th>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.704037</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>b0728</th>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.704037</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
        "      <th>b2464</th>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
        "      <td>0.873922</td>\n",
        "      <td>0.864759</td>\n",
        "      <td>0.873922</td>\n",
@@ -496,11 +428,6 @@
        "    </tr>\n",
        "    <tr>\n",
        "      <th>b0008</th>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
        "      <td>0.864759</td>\n",
        "      <td>0.873922</td>\n",
        "      <td>0.873922</td>\n",
@@ -509,11 +436,6 @@
        "    </tr>\n",
        "    <tr>\n",
        "      <th>b2935</th>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
        "      <td>0.873922</td>\n",
        "      <td>0.873922</td>\n",
        "      <td>0.873922</td>\n",
@@ -522,11 +444,6 @@
        "    </tr>\n",
        "    <tr>\n",
        "      <th>b2465</th>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.814298</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
        "      <td>0.873922</td>\n",
        "      <td>0.873922</td>\n",
        "      <td>0.000000</td>\n",
@@ -540,40 +457,18 @@
        "      <td>0.704037</td>\n",
        "      <td>0.704037</td>\n",
        "      <td>0.704037</td>\n",
-       "      <td>0.704037</td>\n",
-       "      <td>0.704037</td>\n",
-       "      <td>0.704037</td>\n",
-       "      <td>0.704037</td>\n",
-       "      <td>0.704037</td>\n",
        "    </tr>\n",
        "  </tbody>\n",
        "</table>\n",
        "</div>"
       ],
       "text/plain": [
-       "          b0724     b0723     b0721     b0729     b0728     b2464     b0008  \\\n",
-       "b0724  0.814298  0.814298  0.814298  0.814298  0.814298  0.814298  0.814298   \n",
-       "b0723  0.814298  0.814298  0.814298  0.814298  0.814298  0.814298  0.814298   \n",
-       "b0721  0.814298  0.814298  0.814298  0.814298  0.814298  0.814298  0.814298   \n",
-       "b0729  0.814298  0.814298  0.814298  0.858307  0.858307  0.858307  0.858307   \n",
-       "b0728  0.814298  0.814298  0.814298  0.858307  0.858307  0.858307  0.858307   \n",
-       "b2464  0.814298  0.814298  0.814298  0.858307  0.858307  0.873922  0.864759   \n",
-       "b0008  0.814298  0.814298  0.814298  0.858307  0.858307  0.864759  0.873922   \n",
-       "b2935  0.814298  0.814298  0.814298  0.858307  0.858307  0.873922  0.873922   \n",
-       "b2465  0.814298  0.814298  0.814298  0.858307  0.858307  0.873922  0.873922   \n",
-       "b3919  0.704037  0.704037  0.704037  0.704037  0.704037  0.704037  0.704037   \n",
-       "\n",
-       "          b2935     b2465     b3919  \n",
-       "b0724  0.814298  0.814298  0.704037  \n",
-       "b0723  0.814298  0.814298  0.704037  \n",
-       "b0721  0.814298  0.814298  0.704037  \n",
-       "b0729  0.858307  0.858307  0.704037  \n",
-       "b0728  0.858307  0.858307  0.704037  \n",
-       "b2464  0.873922  0.873922  0.704037  \n",
-       "b0008  0.873922  0.873922  0.704037  \n",
-       "b2935  0.873922  0.000000  0.704037  \n",
-       "b2465  0.000000  0.873922  0.704037  \n",
-       "b3919  0.704037  0.704037  0.704037  "
+       "          b2464     b0008     b2935     b2465     b3919\n",
+       "b2464  0.873922  0.864759  0.873922  0.873922  0.704037\n",
+       "b0008  0.864759  0.873922  0.873922  0.873922  0.704037\n",
+       "b2935  0.873922  0.873922  0.873922  0.000000  0.704037\n",
+       "b2465  0.873922  0.873922  0.000000  0.873922  0.704037\n",
+       "b3919  0.704037  0.704037  0.704037  0.704037  0.704037"
       ]
      },
      "execution_count": 5,
@@ -582,7 +477,8 @@
     }
    ],
    "source": [
-    "cobra.flux_analysis.double_gene_deletion(cobra_model, cobra_model.genes[-10:], return_frame=True)"
+    "double_gene_deletion(cobra_model, cobra_model.genes[-5:],\n",
+    "                     return_frame=True)"
    ]
   },
   {
@@ -603,24 +499,28 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Double gene deletions for 100 genes completed in 1.69 sec with 2 cores\n",
-      "Double gene deletions for 100 genes completed in 2.02 sec with 1 core\n",
-      "Speedup of 1.20x\n"
+      "Double gene deletions for 200 genes completed in 11.13 sec with 2 cores\n",
+      "Double gene deletions for 200 genes completed in 14.14 sec with 1 core\n",
+      "Speedup of 1.27x\n"
      ]
     }
    ],
    "source": [
     "start = time()  # start timer()\n",
-    "cobra.flux_analysis.double_gene_deletion(ecoli_model, ecoli_model.genes[:100], number_of_processes=2)\n",
+    "double_gene_deletion(ecoli_model, ecoli_model.genes[:200],\n",
+    "                     number_of_processes=2)\n",
     "t1 = time() - start\n",
-    "print(\"Double gene deletions for 100 genes completed in %.2f sec with 2 cores\" % t1)\n",
+    "print(\"Double gene deletions for 200 genes completed in \"\n",
+    "      \"%.2f sec with 2 cores\" % t1)\n",
     "\n",
     "start = time()  # start timer()\n",
-    "cobra.flux_analysis.double_gene_deletion(ecoli_model, ecoli_model.genes[:100], number_of_processes=1)\n",
+    "double_gene_deletion(ecoli_model, ecoli_model.genes[:200],\n",
+    "                     number_of_processes=1)\n",
     "t2 = time() - start\n",
-    "print(\"Double gene deletions for 100 genes completed in %.2f sec with 1 core\" % t2)\n",
+    "print(\"Double gene deletions for 200 genes completed in \"\n",
+    "      \"%.2f sec with 1 core\" % t2)\n",
     "\n",
-    "print(\"Speedup of %.2fx\" % (t2/t1))"
+    "print(\"Speedup of %.2fx\" % (t2 / t1))"
    ]
   },
   {
@@ -645,146 +545,51 @@
        "  <thead>\n",
        "    <tr style=\"text-align: right;\">\n",
        "      <th></th>\n",
-       "      <th>ACALD</th>\n",
-       "      <th>ACALDt</th>\n",
        "      <th>ACKr</th>\n",
        "      <th>ACONTa</th>\n",
        "      <th>ACONTb</th>\n",
        "      <th>ACt2r</th>\n",
        "      <th>ADK1</th>\n",
-       "      <th>AKGDH</th>\n",
-       "      <th>AKGt2r</th>\n",
-       "      <th>ALCD2x</th>\n",
        "    </tr>\n",
        "  </thead>\n",
        "  <tbody>\n",
        "    <tr>\n",
-       "      <th>ACALD</th>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0</td>\n",
-       "      <td>0</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>ACALDt</th>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0</td>\n",
-       "      <td>0</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
        "      <th>ACKr</th>\n",
        "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
        "      <td>0</td>\n",
        "      <td>0</td>\n",
        "      <td>0.873922</td>\n",
        "      <td>0.873922</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>ACONTa</th>\n",
        "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
        "      <td>0</td>\n",
        "      <td>0</td>\n",
        "      <td>0.000000</td>\n",
        "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>ACONTb</th>\n",
        "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
        "      <td>0</td>\n",
        "      <td>0</td>\n",
        "      <td>0.000000</td>\n",
        "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
-       "      <td>0.000000</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>ACt2r</th>\n",
        "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
        "      <td>0</td>\n",
        "      <td>0</td>\n",
        "      <td>0.873922</td>\n",
        "      <td>0.873922</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
        "    </tr>\n",
        "    <tr>\n",
        "      <th>ADK1</th>\n",
        "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0</td>\n",
-       "      <td>0</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>AKGDH</th>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0</td>\n",
        "      <td>0</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.858307</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>AKGt2r</th>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
        "      <td>0</td>\n",
-       "      <td>0</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.858307</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "    </tr>\n",
-       "    <tr>\n",
-       "      <th>ALCD2x</th>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0</td>\n",
-       "      <td>0</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.873922</td>\n",
-       "      <td>0.858307</td>\n",
        "      <td>0.873922</td>\n",
        "      <td>0.873922</td>\n",
        "    </tr>\n",
@@ -793,29 +598,12 @@
        "</div>"
       ],
       "text/plain": [
-       "           ACALD    ACALDt      ACKr  ACONTa  ACONTb     ACt2r      ADK1  \\\n",
-       "ACALD   0.873922  0.873922  0.873922       0       0  0.873922  0.873922   \n",
-       "ACALDt  0.873922  0.873922  0.873922       0       0  0.873922  0.873922   \n",
-       "ACKr    0.873922  0.873922  0.873922       0       0  0.873922  0.873922   \n",
-       "ACONTa  0.000000  0.000000  0.000000       0       0  0.000000  0.000000   \n",
-       "ACONTb  0.000000  0.000000  0.000000       0       0  0.000000  0.000000   \n",
-       "ACt2r   0.873922  0.873922  0.873922       0       0  0.873922  0.873922   \n",
-       "ADK1    0.873922  0.873922  0.873922       0       0  0.873922  0.873922   \n",
-       "AKGDH   0.858307  0.858307  0.858307       0       0  0.858307  0.858307   \n",
-       "AKGt2r  0.873922  0.873922  0.873922       0       0  0.873922  0.873922   \n",
-       "ALCD2x  0.873922  0.873922  0.873922       0       0  0.873922  0.873922   \n",
-       "\n",
-       "           AKGDH    AKGt2r    ALCD2x  \n",
-       "ACALD   0.858307  0.873922  0.873922  \n",
-       "ACALDt  0.858307  0.873922  0.873922  \n",
-       "ACKr    0.858307  0.873922  0.873922  \n",
-       "ACONTa  0.000000  0.000000  0.000000  \n",
-       "ACONTb  0.000000  0.000000  0.000000  \n",
-       "ACt2r   0.858307  0.873922  0.873922  \n",
-       "ADK1    0.858307  0.873922  0.873922  \n",
-       "AKGDH   0.858307  0.858307  0.858307  \n",
-       "AKGt2r  0.858307  0.873922  0.873922  \n",
-       "ALCD2x  0.858307  0.873922  0.873922  "
+       "            ACKr  ACONTa  ACONTb     ACt2r      ADK1\n",
+       "ACKr    0.873922       0       0  0.873922  0.873922\n",
+       "ACONTa  0.000000       0       0  0.000000  0.000000\n",
+       "ACONTb  0.000000       0       0  0.000000  0.000000\n",
+       "ACt2r   0.873922       0       0  0.873922  0.873922\n",
+       "ADK1    0.873922       0       0  0.873922  0.873922"
       ]
      },
      "execution_count": 7,
@@ -824,7 +612,9 @@
     }
    ],
    "source": [
-    "cobra.flux_analysis.double_reaction_deletion(cobra_model, cobra_model.reactions[:10], return_frame=True)"
+    "double_reaction_deletion(cobra_model,\n",
+    "                         cobra_model.reactions[2:7],\n",
+    "                         return_frame=True)"
    ]
   }
  ],
diff --git a/documentation_builder/gapfilling.ipynb b/documentation_builder/gapfilling.ipynb
index 3394995..2962827 100644
--- a/documentation_builder/gapfilling.ipynb
+++ b/documentation_builder/gapfilling.ipynb
@@ -153,7 +153,8 @@
     }
    ],
    "source": [
-    "result = cobra.flux_analysis.growMatch(model, Universal, iterations=4)\n",
+    "result = cobra.flux_analysis.growMatch(model, Universal,\n",
+    "                                       iterations=4)\n",
     "for i, entries in enumerate(result):\n",
     "    print(\"---- Run %d ----\" % (i + 1))\n",
     "    for e in entries:\n",
diff --git a/documentation_builder/getting_started.ipynb b/documentation_builder/getting_started.ipynb
index bfd093a..d4dd70a 100644
--- a/documentation_builder/getting_started.ipynb
+++ b/documentation_builder/getting_started.ipynb
@@ -20,7 +20,8 @@
     "from __future__ import print_function\n",
     "import cobra.test\n",
     "\n",
-    "model = cobra.test.create_test_model(\"textbook\")  # \"ecoli\" and \"salmonella\" are also valid arguments"
+    "# \"ecoli\" and \"salmonella\" are also valid arguments\n",
+    "model = cobra.test.create_test_model(\"textbook\")"
    ]
   },
   {
@@ -70,7 +71,7 @@
     {
      "data": {
       "text/plain": [
-       "<Reaction EX_glu__L_e at 0x7fbbe05e5590>"
+       "<Reaction EX_glu__L_e at 0x7f9b62fcf650>"
       ]
      },
      "execution_count": 3,
@@ -99,7 +100,7 @@
     {
      "data": {
       "text/plain": [
-       "<Metabolite atp_c at 0x7fbbe0617350>"
+       "<Metabolite atp_c at 0x7f9b6305ded0>"
       ]
      },
      "execution_count": 4,
@@ -164,7 +165,7 @@
     {
      "data": {
       "text/plain": [
-       "<Reaction PGI at 0x7fbbe0611790>"
+       "<Reaction PGI at 0x7f9b63050910>"
       ]
      },
      "execution_count": 6,
@@ -309,7 +310,7 @@
     {
      "data": {
       "text/plain": [
-       "{'H': -1.0}"
+       "{'H': -1.0, 'charge': -1.0}"
       ]
      },
      "execution_count": 11,
@@ -387,7 +388,7 @@
     {
      "data": {
       "text/plain": [
-       "'g6p_c --> green_eggs + ham + h_c + f6p_c'"
+       "'g6p_c --> ham + h_c + green_eggs + f6p_c'"
       ]
      },
      "execution_count": 14,
@@ -446,7 +447,7 @@
     {
      "data": {
       "text/plain": [
-       "<Metabolite atp_c at 0x7fbbe0617350>"
+       "<Metabolite atp_c at 0x7f9b6305ded0>"
       ]
      },
      "execution_count": 16,
@@ -588,10 +589,10 @@
     {
      "data": {
       "text/plain": [
-       "frozenset({<Reaction G6PDH2r at 0x7fbbe05fd050>,\n",
-       "           <Reaction GLCpts at 0x7fbbe05fd150>,\n",
-       "           <Reaction PGI at 0x7fbbe0611790>,\n",
-       "           <Reaction Biomass_Ecoli_core at 0x7fbbe0650ed0>})"
+       "frozenset({<Reaction Biomass_Ecoli_core at 0x7f9b62fbcbd0>,\n",
+       "           <Reaction G6PDH2r at 0x7f9b62fcff50>,\n",
+       "           <Reaction PGI at 0x7f9b63050910>,\n",
+       "           <Reaction GLCpts at 0x7f9b631ccad0>})"
       ]
      },
      "execution_count": 21,
@@ -659,7 +660,7 @@
     {
      "data": {
       "text/plain": [
-       "frozenset({<Gene b4025 at 0x7fbbe063dc90>})"
+       "frozenset({<Gene b4025 at 0x7f9b63027bd0>})"
       ]
      },
      "execution_count": 23,
@@ -681,7 +682,7 @@
     {
      "data": {
       "text/plain": [
-       "<Gene b4025 at 0x7fbbe063dc90>"
+       "<Gene b4025 at 0x7f9b63027bd0>"
       ]
      },
      "execution_count": 24,
@@ -711,7 +712,7 @@
     {
      "data": {
       "text/plain": [
-       "frozenset({<Reaction PGI at 0x7fbbe0611790>})"
+       "frozenset({<Reaction PGI at 0x7f9b63050910>})"
       ]
      },
      "execution_count": 25,
@@ -740,7 +741,7 @@
     {
      "data": {
       "text/plain": [
-       "frozenset({<Gene eggs at 0x7fbbe0611b50>, <Gene spam at 0x7fbbe0611e90>})"
+       "frozenset({<Gene eggs at 0x7f9b63057310>, <Gene spam at 0x7f9b63057590>})"
       ]
      },
      "execution_count": 26,
@@ -792,7 +793,7 @@
     {
      "data": {
       "text/plain": [
-       "<Gene spam at 0x7fbbe0611e90>"
+       "<Gene spam at 0x7f9b63057590>"
       ]
      },
      "execution_count": 28,
@@ -819,19 +820,46 @@
    },
    "outputs": [
     {
+     "data": {
+      "text/plain": [
+       "3"
+      ]
+     },
+     "execution_count": 29,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "len(\"%3d\"% 0)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "-1000 < pgi < 1000\n",
-      "0.0 < pgi < 0.0\n"
+      "after 1 KO: -1000 < flux_PGI < 1000\n",
+      "after 2 KO:     0 < flux_PGI <    0\n"
      ]
     }
    ],
    "source": [
-    "cobra.manipulation.delete_model_genes(model, [\"spam\"], cumulative_deletions=True)\n",
-    "print(pgi.lower_bound, \"< pgi <\", pgi.upper_bound)\n",
-    "cobra.manipulation.delete_model_genes(model, [\"eggs\"], cumulative_deletions=True)\n",
-    "print(pgi.lower_bound, \"< pgi <\", pgi.upper_bound)"
+    "cobra.manipulation.delete_model_genes(model, [\"spam\"],\n",
+    "                                      cumulative_deletions=True)\n",
+    "print(\"after 1 KO: %4d < flux_PGI < %4d\" %\n",
+    "      (pgi.lower_bound, pgi.upper_bound))\n",
+    "\n",
+    "cobra.manipulation.delete_model_genes(model, [\"eggs\"],\n",
+    "                                      cumulative_deletions=True)\n",
+    "print(\"after 2 KO:  %4d < flux_PGI < %4d\" %\n",
+    "      (pgi.lower_bound, pgi.upper_bound))"
    ]
   },
   {
@@ -843,7 +871,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 31,
    "metadata": {
     "collapsed": false
    },
diff --git a/documentation_builder/io.ipynb b/documentation_builder/io.ipynb
index 295bde1..0eaca37 100644
--- a/documentation_builder/io.ipynb
+++ b/documentation_builder/io.ipynb
@@ -30,9 +30,15 @@
    "source": [
     "import cobra.test\n",
     "import os\n",
+    "from os.path import join\n",
+    "\n",
+    "data_dir = cobra.test.data_directory\n",
     "\n",
     "print(\"mini test files: \")\n",
-    "print(\", \".join([i for i in os.listdir(cobra.test.data_directory) if i.startswith(\"mini\")]))\n",
+    "print(\", \".join(i for i in os.listdir(data_dir)\n",
+    "                if i.startswith(\"mini\")))\n",
+    "\n",
+    "\n",
     "\n",
     "textbook_model = cobra.test.create_test_model(\"textbook\")\n",
     "ecoli_model = cobra.test.create_test_model(\"ecoli\")\n",
@@ -65,7 +71,7 @@
     {
      "data": {
       "text/plain": [
-       "<Model mini_textbook at 0x7f246d4e2e50>"
+       "<Model mini_textbook at 0x7f1a5462e290>"
       ]
      },
      "execution_count": 2,
@@ -74,7 +80,7 @@
     }
    ],
    "source": [
-    "cobra.io.read_sbml_model(os.path.join(cobra.test.data_directory, \"mini_fbc2.xml\"))"
+    "cobra.io.read_sbml_model(join(data_dir, \"mini_fbc2.xml\"))"
    ]
   },
   {
@@ -94,7 +100,7 @@
    "source": [
     "There are other dialects of SBML prior to FBC 2 which have previously been use to encode COBRA models. The primary ones is the \"COBRA\" dialect which used the \"notes\" fields in SBML files.\n",
     "\n",
-    "Cobrapy can use [libsbml](http://sbml.org/Software/libSBML), which must be installed separately (see installation instructions) to read and write these files. When reading in a model, it will automatically detect whether fbc was used or not. When writing a model, the use_fbc_package flag can be used can be used."
+    "Cobrapy can use [libsbml](http://sbml.org/Software/libSBML), which must be installed separately (see installation instructions) to read and write these files. When reading in a model, it will automatically detect whether fbc was used or not. When writing a model, the use_fbc_package flag can be used can be used to write files in this legacy \"cobra\" format."
    ]
   },
   {
@@ -107,7 +113,7 @@
     {
      "data": {
       "text/plain": [
-       "<Model mini_textbook at 0x7f2436c65a10>"
+       "<Model mini_textbook at 0x7f1a2291a610>"
       ]
      },
      "execution_count": 4,
@@ -116,7 +122,7 @@
     }
    ],
    "source": [
-    "cobra.io.read_sbml_model(os.path.join(cobra.test.data_directory, \"mini_cobra.xml\"))"
+    "cobra.io.read_sbml_model(join(data_dir, \"mini_cobra.xml\"))"
    ]
   },
   {
@@ -127,7 +133,8 @@
    },
    "outputs": [],
    "source": [
-    "cobra.io.write_sbml_model(textbook_model, \"test_cobra.xml\", use_fbc_package=False)"
+    "cobra.io.write_sbml_model(textbook_model, \"test_cobra.xml\",\n",
+    "                          use_fbc_package=False)"
    ]
   },
   {
@@ -149,7 +156,7 @@
     {
      "data": {
       "text/plain": [
-       "<Model mini_textbook at 0x7f2436c7c850>"
+       "<Model mini_textbook at 0x7f1a2292ae90>"
       ]
      },
      "execution_count": 6,
@@ -158,7 +165,7 @@
     }
    ],
    "source": [
-    "cobra.io.load_json_model(os.path.join(cobra.test.data_directory, \"mini.json\"))"
+    "cobra.io.load_json_model(join(data_dir, \"mini.json\"))"
    ]
   },
   {
@@ -198,7 +205,7 @@
     {
      "data": {
       "text/plain": [
-       "<Model mini_textbook at 0x7f2436c7c810>"
+       "<Model mini_textbook at 0x7f1a5462e150>"
       ]
      },
      "execution_count": 8,
@@ -207,7 +214,7 @@
     }
    ],
    "source": [
-    "cobra.io.load_matlab_model(os.path.join(cobra.test.data_directory, \"mini.mat\"),\n",
+    "cobra.io.load_matlab_model(join(data_dir, \"mini.mat\"),\n",
     "                           variable_name=\"mini_textbook\")"
    ]
   },
@@ -228,7 +235,7 @@
     {
      "data": {
       "text/plain": [
-       "<Model mini_textbook at 0x7f2436c65510>"
+       "<Model mini_textbook at 0x7f1a54e93f90>"
       ]
      },
      "execution_count": 9,
@@ -237,7 +244,7 @@
     }
    ],
    "source": [
-    "cobra.io.load_matlab_model(os.path.join(cobra.test.data_directory, \"mini.mat\"))"
+    "cobra.io.load_matlab_model(join(data_dir, \"mini.mat\"))"
    ]
   },
   {
diff --git a/documentation_builder/loopless.ipynb b/documentation_builder/loopless.ipynb
index 1c8da93..ea33bc6 100644
--- a/documentation_builder/loopless.ipynb
+++ b/documentation_builder/loopless.ipynb
@@ -59,8 +59,8 @@
    },
    "outputs": [],
    "source": [
-    "from matplotlib.pylab import *\n",
     "%matplotlib inline\n",
+    "import plot_helper\n",
     "\n",
     "import cobra.test\n",
     "from cobra import Reaction, Metabolite, Model\n",
@@ -84,9 +84,10 @@
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnIAAAEcCAYAAABDOFkiAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xe4JFWd//H3dzJpQJAMC6K4iLCoKEmMgLoSBBVBJaNr\nIKzgT8UsioHFrKMrCijiKmYxYQDMzM6CCREVBFQERIkyAxO/vz/qNHO53Hy7u7q636/nuU/d6lvd\n9R3o8Olz6pwTmYkkSZKaZ0bdBUiSJGlqDHKSJEkNZZCTJElqKIOcJElSQxnkJEmSGsogJ0mS1FAG\nOUmSpIYyyEmSJDWUQU6SJKmhDHKSJEkNZZCTJElqKIOcJElSQxnkJEmSGsogJ0mS1FAGOUmSpIYy\nyEmSJDWUQU6SJKmhDHKSJEkNZZCTJElqKIOcJElSQxnkJEmSGsogJ0mS1FAGOUmSpIYyyEmSJDWU\nQU6S [...]
+      "application/pdf": "JVBERi0xLjQKJazcIKu6CjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSID4+\nCmVuZG9iago4IDAgb2JqCjw8IC9YT2JqZWN0IDcgMCBSIC9QYXR0ZXJuIDUgMCBSCi9Qcm9jU2V0\nIFsgL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9FeHRHU3RhdGUgNCAwIFIK\nL1NoYWRpbmcgNiAwIFIgL0ZvbnQgMyAwIFIgPj4KZW5kb2JqCjEwIDAgb2JqCjw8IC9Hcm91cCA8\nPCAvQ1MgL0RldmljZVJHQiAvUyAvVHJhbnNwYXJlbmN5IC9UeXBlIC9Hcm91cCA+PiAvUGFyZW50\nIDIgMCBSCi9NZWRpYUJveCBbIDAgMCA2MjguMTU5Mzc1IDI4NC4wMDc4MTI1IF0gL0Fubm90cyBb [...]
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAnQAAAEcCAYAAABOJillAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xm4HFWd//H3NwkhCQEERZBF2cVRcJ0Iygzu27CKiCIg\nBkdFEBUXGFHEDXcFJOqo7KAjICq4oCKuSIgbiiigsoiAwA8wCiFAku/vj1NtLpfcvburq/v9ep5+\n6nbf6q5voKv7c8+pc05kJpIkSWquaXUXIEmSpKkx0EmSJDWcgU6SJKnhDHSSJEkNZ6CTJElqOAOd\nJElSwxnoJEmSGs5AJ0mS1HAGOkmSpIYz0EmSJDWcgU6SJKnhDHSSJEkNZ6CTJElqOAOdJElSwxno\nJEmSGs5AJ0mS1HAGOkmSpIYz0EmSJDWcgU6SJKnhDHSSJEkNZ6CTJElqOAOdJElSwxnoJEmSGs5A\nJ0mS [...]
       "text/plain": [
-       "<matplotlib.figure.Figure at 0x7f003ad8eb50>"
+       "<matplotlib.figure.Figure at 0x7fe343a72ed0>"
       ]
      },
      "metadata": {},
@@ -94,30 +95,7 @@
     }
    ],
    "source": [
-    "figure(figsize=(10.5, 4.5), frameon=False)\n",
-    "gca().axis(\"off\")\n",
-    "xlim(0.5, 3.5)\n",
-    "ylim(0.7, 2.2)\n",
-    "arrow_params = {\"head_length\": 0.08, \"head_width\": 0.1, \"ec\": \"k\", \"fc\": \"k\"}\n",
-    "text_params = {\"fontsize\": 25, \"horizontalalignment\": \"center\", \"verticalalignment\": \"center\"}\n",
-    "arrow(0.5, 1, 0.85, 0, **arrow_params)  # EX_A\n",
-    "arrow(1.5, 1, 0.425, 0.736, **arrow_params)  # v1\n",
-    "arrow(2.04, 1.82, 0.42, -0.72, **arrow_params)  # v2\n",
-    "arrow(2.4, 1, -0.75, 0, **arrow_params)  # v3\n",
-    "arrow(2.6, 1, 0.75, 0, **arrow_params)\n",
-    "# reaction labels\n",
-    "text(0.9, 1.15, \"EX_A\", **text_params)\n",
-    "text(1.6, 1.5, r\"v$_1$\", **text_params)\n",
-    "text(2.4, 1.5, r\"v$_2$\", **text_params)\n",
-    "text(2, 0.85, r\"v$_3$\", **text_params)\n",
-    "text(2.9, 1.15, \"DM_C\", **text_params)\n",
-    "# metabolite labels\n",
-    "scatter(1.5, 1, s=250, color='#c994c7')\n",
-    "text(1.5, 0.9, \"A\", **text_params)\n",
-    "scatter(2, 1.84, s=250, color='#c994c7')\n",
-    "text(2, 1.95, \"B\", **text_params)\n",
-    "scatter(2.5, 1, s=250, color='#c994c7')\n",
-    "text(2.5, 0.9, \"C\", **text_params);"
+    "plot_helper.plot_loop()"
    ]
   },
   {
@@ -163,7 +141,7 @@
     {
      "data": {
       "text/plain": [
-       "<Solution 1000.00 at 0x7f003ad82850>"
+       "<Solution 1000.00 at 0x7fe342fb1950>"
       ]
      },
      "execution_count": 4,
@@ -192,7 +170,7 @@
     {
      "data": {
       "text/plain": [
-       "<Solution 'infeasible' at 0x7f003ad82f10>"
+       "<Solution 'infeasible' at 0x7fe342fb1790>"
       ]
      },
      "execution_count": 5,
@@ -222,7 +200,7 @@
     {
      "data": {
       "text/plain": [
-       "<Solution 0.38 at 0x7f003a496190>"
+       "<Solution 0.38 at 0x7fe33b67ba90>"
       ]
      },
      "execution_count": 6,
@@ -245,7 +223,7 @@
     {
      "data": {
       "text/plain": [
-       "<Solution 0.98 at 0x7f003ae06b50>"
+       "<Solution 0.98 at 0x7fe342fb1a90>"
       ]
      },
      "execution_count": 7,
diff --git a/documentation_builder/milp.ipynb b/documentation_builder/milp.ipynb
index 58a489d..6d5bc93 100644
--- a/documentation_builder/milp.ipynb
+++ b/documentation_builder/milp.ipynb
@@ -75,9 +75,10 @@
     "popsicle.add_metabolites({budget: popsicle_production_cost})\n",
     "\n",
     "# objective coefficient is the profit to be made from each unit\n",
-    "cone.objective_coefficient = cone_selling_price - cone_production_cost\n",
-    "popsicle.objective_coefficient = popsicle_selling_price - \\\n",
-    "                                 popsicle_production_cost\n",
+    "cone.objective_coefficient = \\\n",
+    "    cone_selling_price - cone_production_cost\n",
+    "popsicle.objective_coefficient = \\\n",
+    "    popsicle_selling_price - popsicle_production_cost\n",
     "\n",
     "m = Model(\"lerman_ice_cream_co\")\n",
     "m.add_reactions((cone, popsicle))\n",
@@ -200,8 +201,9 @@
     "total_cost = Metabolite(\"constraint\")\n",
     "total_cost._bound = 15.05\n",
     "\n",
-    "costs = {\"mixed_fruit\": 2.15, \"french_fries\": 2.75, \"side_salad\": 3.35,\n",
-    "         \"hot_wings\": 3.55, \"mozarella_sticks\": 4.20, \"sampler_plate\": 5.80}\n",
+    "costs = {\"mixed_fruit\": 2.15, \"french_fries\": 2.75,\n",
+    "         \"side_salad\": 3.35, \"hot_wings\": 3.55,\n",
+    "         \"mozarella_sticks\": 4.20, \"sampler_plate\": 5.80}\n",
     "\n",
     "m = Model(\"appetizers\")\n",
     "\n",
@@ -211,7 +213,8 @@
     "    r.variable_kind = \"integer\"\n",
     "    m.add_reaction(r)\n",
     "\n",
-    "# To add to the problem, suppose we don't want to eat all mixed fruit.\n",
+    "# To add to the problem, suppose we want to\n",
+    "# eat as little mixed fruit as possible.\n",
     "m.reactions.mixed_fruit.objective_coefficient = 1\n",
     "    \n",
     "m.optimize(objective_sense=\"minimize\").x_dict"
@@ -295,7 +298,8 @@
     "pgi_minus = Metabolite(\"PGI_minus\")\n",
     "pgi_minus._constraint_sense = \"G\"\n",
     "\n",
-    "pgi_indicator.add_metabolites({pgi_plus: -1000, pgi_minus: 1000})\n",
+    "pgi_indicator.add_metabolites({pgi_plus: -1000,\n",
+    "                               pgi_minus: 1000})\n",
     "pgi.add_metabolites({pgi_plus: 1, pgi_minus: 1})\n",
     "model.add_reaction(pgi_indicator)\n",
     "\n",
@@ -313,7 +317,8 @@
     "zwf_minus = Metabolite(\"ZWF_minus\")\n",
     "zwf_minus._constraint_sense = \"G\"\n",
     "\n",
-    "zwf_indicator.add_metabolites({zwf_plus: -1000, zwf_minus: 1000})\n",
+    "zwf_indicator.add_metabolites({zwf_plus: -1000,\n",
+    "                               zwf_minus: 1000})\n",
     "zwf.add_metabolites({zwf_plus: 1, zwf_minus: 1})\n",
     "\n",
     "# add the indicator reactions to the model\n",
diff --git a/documentation_builder/phenotype_phase_plane.ipynb b/documentation_builder/phenotype_phase_plane.ipynb
index 77d39a9..dcf05d2 100644
--- a/documentation_builder/phenotype_phase_plane.ipynb
+++ b/documentation_builder/phenotype_phase_plane.ipynb
@@ -20,6 +20,9 @@
    "outputs": [],
    "source": [
     "%matplotlib inline\n",
+    "from IPython.display import set_matplotlib_formats\n",
+    "set_matplotlib_formats('png', 'pdf')\n",
+    "\n",
     "from time import time\n",
     "\n",
     "import cobra.test\n",
@@ -44,9 +47,10 @@
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAV0AAADtCAYAAAAcNaZ2AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsvXewHHV69/vpNNOT8wk6ygEhIVgEkhBBBIksYFmWDez6\nXe/i9etQ1/dulf2vq9Z/2eWyb9W133rtd9fZC7sLLDlnJKIIEghEkFA8acKZHDveP1o9jA7nSEfS\nCRLMp4oq0WdCd0/PM99+fs/zfQTbtunSpUuXLrODONc70KVLly5fJ7pBt0uXLl1mkW7Q7dKlS5dZ\npBt0u3Tp0mUW6QbdLl26dJlFukG3S5cuXWYR+QR/79aTdenSpcvJI0z2h67S7dKlS5dZpBt0u3Tp\n0mUW6QbdLl26dJlFukG3S5cuXWaRbtDt0qVLl1mkG3S7dOnSZRbpBt0uXbp0mUW6QbdLly5dZpFu\n0O3S [...]
+      "application/pdf": "JVBERi0xLjQKJazcIKu6CjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSID4+\nCmVuZG9iago4IDAgb2JqCjw8IC9YT2JqZWN0IDcgMCBSIC9QYXR0ZXJuIDUgMCBSCi9Qcm9jU2V0\nIFsgL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9FeHRHU3RhdGUgNCAwIFIK\nL1NoYWRpbmcgNiAwIFIgL0ZvbnQgMyAwIFIgPj4KZW5kb2JqCjEwIDAgb2JqCjw8IC9Hcm91cCA8\nPCAvQ1MgL0RldmljZVJHQiAvUyAvVHJhbnNwYXJlbmN5IC9UeXBlIC9Hcm91cCA+PiAvUGFyZW50\nIDIgMCBSCi9NZWRpYUJveCBbIDAgMCA0MjQuOCAyODAuOCBdIC9Bbm5vdHMgWyBdIC9SZXNvdXJj [...]
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsvWmQHFV69/vLrMza96WrWy3QAhK7BIgdiV2AQDBjhmGW\n63ccMxNj+0bYN+y44fAHf/Jyw+H7dRzvOMa+98Zrjz2rZ2HRAohFCAkQCCRAEqAFIamX6tqrsqpy\nvx+ys1SqaW2t7lZL5C+CkJBKffJUZZ0n/+c8z/MXbNvGw8PDw8NjviFe6Avw8PDw8PCYCi9AeXh4\neHjMS7wA5eHh4eExL/EClIeHh4fHvMQLUB4eHh4e8xLpDH/vpfh5eHh4eMw2wlR/6CkoDw8PD495\niRegPDw8PDzmJV6A8vDw8PCYl3gBysPDw8NjXuIFKA8PDw+PeYkXoDw8PDw85iVegPLw8PDwmJd4\nAcrD [...]
       "text/plain": [
-       "<matplotlib.figure.Figure at 0x7fd5f40df810>"
+       "<matplotlib.figure.Figure at 0x7feab72c2750>"
       ]
      },
      "metadata": {},
@@ -54,7 +58,8 @@
     }
    ],
    "source": [
-    "data = calculate_phenotype_phase_plane(model, \"EX_glc__D_e\", \"EX_o2_e\")\n",
+    "data = calculate_phenotype_phase_plane(\n",
+    "    model, \"EX_glc__D_e\", \"EX_o2_e\")\n",
     "data.plot_matplotlib();"
    ]
   },
@@ -74,9 +79,10 @@
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAV0AAADtCAYAAAAcNaZ2AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsnWdYlHfWxn9TmBkGZuhNUewNFbuosfdewN5LLLGlbt5s\nNtlkd7MxMcbYW4zG3nuNLSo2bKBiQwVUFAWp02Da+4E8syMBRUXQ3fldl19kGOYpc577f/7n3Edk\ntVpx4MCBAwfFg7ikP4ADBw4c/C/hCLoOHDhwUIw4gq4DBw4cFCOOoOvAgQMHxYgj6Dpw4MBBMeII\nug4cOHBQjEif83NHPZkDBw4cvDiign7gULoOHDhwUIw4gq4DBw4cFCOOoOvAgQMHxYgj6Dpw4MBB\nMeIIug4cOHBQjDiCrgMHDhwUI46g68CBAwfFiCPoOnDgwEEx4gi6Dhw4cFCMOIKuAwcOHBQjjqDr\nwIED [...]
+      "application/pdf": "JVBERi0xLjQKJazcIKu6CjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSID4+\nCmVuZG9iago4IDAgb2JqCjw8IC9YT2JqZWN0IDcgMCBSIC9QYXR0ZXJuIDUgMCBSCi9Qcm9jU2V0\nIFsgL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9FeHRHU3RhdGUgNCAwIFIK\nL1NoYWRpbmcgNiAwIFIgL0ZvbnQgMyAwIFIgPj4KZW5kb2JqCjEwIDAgb2JqCjw8IC9Hcm91cCA8\nPCAvQ1MgL0RldmljZVJHQiAvUyAvVHJhbnNwYXJlbmN5IC9UeXBlIC9Hcm91cCA+PiAvUGFyZW50\nIDIgMCBSCi9NZWRpYUJveCBbIDAgMCA0MjQuOCAyODAuOCBdIC9Bbm5vdHMgWyBdIC9SZXNvdXJj [...]
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsnXV0VFn2tp/yiicQIQ4BAgnu7q6Nu7u2Ttt0zze/kZ5p\nmzbcadyDOwQJDgFCsAAhaIAQT1nKvj+KW1NkgoWEBPo+a/ViNQl1pe49+7znvHtvidVqRURERERE\npKQhLe4TEBERERERyQ8xQImIiIiIlEjEACUiIiIiUiIRA5SIiIiISIlEDFAiIiIiIiUS+Qt+Llr8\nRERERESKGkl+fykqKBERERGREokYoERERERESiRigBIRERERKZGIAUpEREREpEQiBigRERERkRKJ\nGKBEREREREokYoASERERESmRiAFKRERERKREIgYoEREREZESiRigRERERERKJGKAEhEREREpkYgB\nSkRE [...]
       "text/plain": [
-       "<matplotlib.figure.Figure at 0x7fd5c1a56e10>"
+       "<matplotlib.figure.Figure at 0x7feae80886d0>"
       ]
      },
      "metadata": {},
@@ -84,9 +90,10 @@
     },
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAV0AAADtCAYAAAAcNaZ2AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsnWd4HPW1h98p27tW1bLce+8d29iYahtCh9ADISEhkISb\n3Nw0ICQEAgklIQTSICEQQiDgjnvvvfdepJW02t5n7gd5Nmsh2bItSzbM+zz+4NXu7M7s7JnfnP85\nvyOoqoqOjo6OTvMgtvQH0NHR0fkioQddHR0dnWZED7o6Ojo6zYgedHV0dHSaET3o6ujo6DQjetDV\n0dHRaUbkM/xdryfT0dHROXuEhv6gK10dHR2dZkQPujo6OjrNiB50dXR0dJoRPejq6OjoNCN60NXR\n0dFpRvSgq6Ojo9OM6EFXR0dHpxnRg66Ojo5OM6IHXR0dHZ1mRA+6Ojo6Os2IHnR1dHR0mpEzeS/o\n6Fz0 [...]
+      "application/pdf": "JVBERi0xLjQKJazcIKu6CjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSID4+\nCmVuZG9iago4IDAgb2JqCjw8IC9YT2JqZWN0IDcgMCBSIC9QYXR0ZXJuIDUgMCBSCi9Qcm9jU2V0\nIFsgL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9FeHRHU3RhdGUgNCAwIFIK\nL1NoYWRpbmcgNiAwIFIgL0ZvbnQgMyAwIFIgPj4KZW5kb2JqCjEwIDAgb2JqCjw8IC9Hcm91cCA8\nPCAvQ1MgL0RldmljZVJHQiAvUyAvVHJhbnNwYXJlbmN5IC9UeXBlIC9Hcm91cCA+PiAvUGFyZW50\nIDIgMCBSCi9NZWRpYUJveCBbIDAgMCA0MjQuOCAyODAuOCBdIC9Bbm5vdHMgWyBdIC9SZXNvdXJj [...]
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsnXd4HNW5/z8zs31XW1Xcbbn3gm3cu8FgTA0BQgkJJJQQ\nSLklueEWSL25yU2jhsAludeQENovFIMxxt249957kbS97075/bGazVrITZZk2czneXiUWNKemdXs\nec/3nO/7voKmaRgYGBgYGLQ1xIt9AQYGBgYGBo1hBCgDAwMDgzaJEaAMDAwMDNokRoAyMDAwMGiT\nGAHKwMDAwKBNYjrL9w2Ln4GBgYFBSyM09o+GgjIwMDAwaJMYAcrAwMDAoE1iBCgDAwMDgzaJEaAM\nDAwMDNokRoAyMDAwMGiTGAHKwMDAwKBNYgQoAwMDA4M2iRGgDAwMDAzaJEaAMjAwMDBokxgBysDA\nwMCg [...]
       "text/plain": [
-       "<matplotlib.figure.Figure at 0x7fd5c1737390>"
+       "<matplotlib.figure.Figure at 0x7feab7137e50>"
       ]
      },
      "metadata": {},
@@ -114,9 +121,10 @@
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAV0AAADtCAYAAAAcNaZ2AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsvWmUHPWV5v2L3NeqzMrMWlRakIQQCEloBwHa0AJaSqy2\ncdtAQ4OBadvted/u4zPvjH1m3N0zbY9nusftHnvMoe22jRmMDWiXEAiEFrSgBUksQmhXrZlZue+Z\nEe+HqMjKvUql2mTyOUcfVJn/yIjIyBs37r3P8wiSJFFFFVVUUcXwQDXSO1BFFVVU8UVCNehWUUUV\nVQwjqkG3iiqqqGIYUQ26VVRRRRXDiGrQraKKKqoYRlSDbhVVVFHFMELTx+vVebIqqqiiiquHUO6F\naqZbRRVVVDGMqAbdKqqooophRDXoVlFFFVUMI6pBt4oqqqhiGFENulVUUUUVw4hq0K2iiiqqGEZU\ng24V [...]
+      "application/pdf": "JVBERi0xLjQKJazcIKu6CjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSID4+\nCmVuZG9iago4IDAgb2JqCjw8IC9YT2JqZWN0IDcgMCBSIC9QYXR0ZXJuIDUgMCBSCi9Qcm9jU2V0\nIFsgL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9FeHRHU3RhdGUgNCAwIFIK\nL1NoYWRpbmcgNiAwIFIgL0ZvbnQgMyAwIFIgPj4KZW5kb2JqCjEwIDAgb2JqCjw8IC9Hcm91cCA8\nPCAvQ1MgL0RldmljZVJHQiAvUyAvVHJhbnNwYXJlbmN5IC9UeXBlIC9Hcm91cCA+PiAvUGFyZW50\nIDIgMCBSCi9NZWRpYUJveCBbIDAgMCA0MjQuOCAyODAuOCBdIC9Bbm5vdHMgWyBdIC9SZXNvdXJj [...]
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsvXmUHOV57/+p3pfp6e7p2aQRCEmWhMQiIUAIoQUkhNDK\nbmy8xRAbkjh2bs61f1nOTRyc3FznJDfOdRL7OI5xbExsA2bRjhDCArQgkEASSCAhabTN0t3T+95V\n9fujplrdPb3N3pLrc44Phpl3urpnup5+3vf7fL+CLMtoaGhoaGjUG7rxvgANDQ0NDY1SaAVKQ0ND\nQ6Mu0QqUhoaGhkZdohUoDQ0NDY26RCtQGhoaGhp1iaHK1zWJn4aGhobGaCOU+o9aB6WhoaGhUZdo\nBUpDQ0NDoy7RCpSGhoaGRl2iFSgNDQ0NjbpEK1AaGhoaGnWJVqA0NDQ0NOoSrUBpaGhoaNQlWoHS\n0NDQ [...]
       "text/plain": [
-       "<matplotlib.figure.Figure at 0x7fd5c163ff50>"
+       "<matplotlib.figure.Figure at 0x7feab6ff7490>"
       ]
      },
      "metadata": {},
@@ -124,9 +132,10 @@
     }
    ],
    "source": [
-    "calculate_phenotype_phase_plane(model, \"EX_glc__D_e\", \"EX_o2_e\",\n",
-    "                                reaction1_npoints=20,\n",
-    "                                reaction2_npoints=20).plot_matplotlib();"
+    "data = calculate_phenotype_phase_plane(\n",
+    "    model, \"EX_glc__D_e\", \"EX_o2_e\",\n",
+    "    reaction1_npoints=20, reaction2_npoints=20)\n",
+    "data.plot_matplotlib();"
    ]
   },
   {
@@ -148,18 +157,23 @@
      "output_type": "stream",
      "text": [
       "took 0.41 seconds with 1 process\n",
-      "took 0.29 seconds with 4 process\n"
+      "took 0.22 seconds with 4 process\n"
      ]
     }
    ],
    "source": [
     "start_time = time()\n",
-    "calculate_phenotype_phase_plane(model, \"EX_glc__D_e\", \"EX_o2_e\", n_processes=1,\n",
-    "                                reaction1_npoints=100, reaction2_npoints=100)\n",
+    "calculate_phenotype_phase_plane(\n",
+    "    model, \"EX_glc__D_e\", \"EX_o2_e\",\n",
+    "    reaction1_npoints=100, reaction2_npoints=100,\n",
+    "    n_processes=1)\n",
     "print(\"took %.2f seconds with 1 process\" % (time() - start_time))\n",
+    "\n",
     "start_time = time()\n",
-    "calculate_phenotype_phase_plane(model, \"EX_glc__D_e\", \"EX_o2_e\", n_processes=4,\n",
-    "                                reaction1_npoints=100, reaction2_npoints=100)\n",
+    "calculate_phenotype_phase_plane(\n",
+    "    model, \"EX_glc__D_e\", \"EX_o2_e\",\n",
+    "    reaction1_npoints=100, reaction2_npoints=100,\n",
+    "    n_processes=4)\n",
     "print(\"took %.2f seconds with 4 process\" % (time() - start_time))"
    ]
   }
diff --git a/documentation_builder/plot_helper.py b/documentation_builder/plot_helper.py
new file mode 100644
index 0000000..0e56682
--- /dev/null
+++ b/documentation_builder/plot_helper.py
@@ -0,0 +1,81 @@
+from matplotlib.pyplot import figure, xlim, ylim, gca, arrow, text, scatter
+from mpl_toolkits.axes_grid.axislines import SubplotZero
+from numpy import linspace, arange, sqrt, pi, sin, cos, sign
+from IPython.display import set_matplotlib_formats
+
+set_matplotlib_formats('png', 'pdf')
+
+
+# axis style
+def make_plot_ax():
+    fig = figure(figsize=(6, 5))
+    ax = SubplotZero(fig, 111)
+    fig.add_subplot(ax)
+    for direction in ["xzero", "yzero"]:
+        ax.axis[direction].set_axisline_style("-|>")
+        ax.axis[direction].set_visible(True)
+    for direction in ["left", "right", "bottom", "top"]:
+        ax.axis[direction].set_visible(False)
+    xlim(-0.1, 2.1)
+    ylim(xlim())
+    ticks = [0.5 * i for i in range(1, 5)]
+    labels = [str(i) if i == int(i) else "" for i in ticks]
+    ax.set_xticks(ticks)
+    ax.set_yticks(ticks)
+    ax.set_xticklabels(labels)
+    ax.set_yticklabels(labels)
+    ax.axis["yzero"].set_axis_direction("left")
+    return ax
+
+
+def plot_qp1():
+    ax = make_plot_ax()
+    ax.plot((0, 2), (2, 0), 'b')
+    ax.plot([1], [1], 'bo')
+
+    # circular grid
+    for r in sqrt(2.) + 0.125 * arange(-11, 6):
+        t = linspace(0., pi/2., 100)
+        ax.plot(r * cos(t), r * sin(t), '-.', color="gray")
+
+
+def plot_qp2():
+    ax = make_plot_ax()
+    ax.plot((0, 2), (2, 0), 'b')
+    ax.plot([0.5], [1.5], 'bo')
+
+    yrange = linspace(1, 2, 11)
+    for r in (yrange ** 2 / 2. - yrange):
+        t = linspace(-sqrt(2 * r + 1) + 0.000001,
+                     sqrt(2 * r + 1) - 0.000001, 1000)
+        ax.plot(abs(t), 1 + sqrt(2 * r + 1 - t ** 2) * sign(t), '-.',
+                color="gray")
+
+
+def plot_loop():
+    figure(figsize=(10.5, 4.5), frameon=False)
+    gca().axis("off")
+    xlim(0.5, 3.5)
+    ylim(0.7, 2.2)
+    arrow_params = {"head_length": 0.08, "head_width": 0.1, "ec": "k",
+                    "fc": "k"}
+    text_params = {"fontsize": 25, "horizontalalignment": "center",
+                   "verticalalignment": "center"}
+    arrow(0.5, 1, 0.85, 0, **arrow_params)  # EX_A
+    arrow(1.5, 1, 0.425, 0.736, **arrow_params)  # v1
+    arrow(2.04, 1.82, 0.42, -0.72, **arrow_params)  # v2
+    arrow(2.4, 1, -0.75, 0, **arrow_params)  # v3
+    arrow(2.6, 1, 0.75, 0, **arrow_params)
+    # reaction labels
+    text(0.9, 1.15, "EX_A", **text_params)
+    text(1.6, 1.5, r"v$_1$", **text_params)
+    text(2.4, 1.5, r"v$_2$", **text_params)
+    text(2, 0.85, r"v$_3$", **text_params)
+    text(2.9, 1.15, "DM_C", **text_params)
+    # metabolite labels
+    scatter(1.5, 1, s=250, color='#c994c7')
+    text(1.5, 0.9, "A", **text_params)
+    scatter(2, 1.84, s=250, color='#c994c7')
+    text(2, 1.95, "B", **text_params)
+    scatter(2.5, 1, s=250, color='#c994c7')
+    text(2.5, 0.9, "C", **text_params)
diff --git a/documentation_builder/pymatbridge.ipynb b/documentation_builder/pymatbridge.ipynb
index 16e4a63..64e2e68 100644
--- a/documentation_builder/pymatbridge.ipynb
+++ b/documentation_builder/pymatbridge.ipynb
@@ -176,7 +176,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "FBA in the COBRA toolbox should give the same result as cobrapy"
+    "FBA in the COBRA toolbox should give the same result as cobrapy (but maybe just a little bit slower :))"
    ]
   },
   {
diff --git a/documentation_builder/qp.ipynb b/documentation_builder/qp.ipynb
index b12cff8..db3aad8 100644
--- a/documentation_builder/qp.ipynb
+++ b/documentation_builder/qp.ipynb
@@ -30,9 +30,10 @@
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWAAAAEmCAYAAABcYEo9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJztnXe4XFXVh98TSOg11BCaUoNUaWKhd5UWRIoCilIFRaWJ\nrPmJgIq0CAIfXekdRIqAFOlIk16kI70KEghwvj/2DtxM5vZ1yszd7/PcB3Jm7tr73pm7Zp9VfivL\n85yiyLJsI1jkdHhkevgj8Isb8/ytVQtbMJFIJNqIrFgHPN0V8PFaMM2H8PG08F+AufM8f6mwRROJ\nRKJNKNgBZ9MBM8V/vgDMkef5q4UtmEgkEm1EoQ54koWyLM/zPCtlsUQikWgDhlW9gUQikRiqJAec\nSCQSFZEccCKRSFREcsCJRCJREckBJxKJREUkB5xIJBIVkRxwIpFIVERywIlEIlERyQEnEolERUxZ\n1cKS [...]
+      "application/pdf": "JVBERi0xLjQKJazcIKu6CjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSID4+\nCmVuZG9iago4IDAgb2JqCjw8IC9YT2JqZWN0IDcgMCBSIC9QYXR0ZXJuIDUgMCBSCi9Qcm9jU2V0\nIFsgL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9FeHRHU3RhdGUgNCAwIFIK\nL1NoYWRpbmcgNiAwIFIgL0ZvbnQgMyAwIFIgPj4KZW5kb2JqCjEwIDAgb2JqCjw8IC9Hcm91cCA8\nPCAvQ1MgL0RldmljZVJHQiAvUyAvVHJhbnNwYXJlbmN5IC9UeXBlIC9Hcm91cCA+PiAvUGFyZW50\nIDIgMCBSCi9NZWRpYUJveCBbIDAgMCAzNTMuODg4MDY4MTgxOCAyOTQuMjE4MTgxODE4MiBdIC9B [...]
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWEAAAEmCAYAAACzoiEDAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsnXlUVFe+779VzKPMoOCEOIAIzrNG42zUxCTGJMZEM5ik\nc5Pu28Nbb9217nt9+6773l2378qL3aaTKCbGmBgn1Dij4gg4gYJMAoIgUwEFVUXNVefs9weNLVah\nDPsMVezPWnfdzin87U1R9Tv7/IbvT0EIgZAoFAoFEGwBdnsBywHEAlC/Rwj5VtCFGQwGwwVQiOCE\n1wP4GRj09ytGAMp7hJjHCbowg8FguACCO2EAUCgUEwB4AsgDMBlAJSFEK/jCDAaDIXNEccKPFlMo\nCCFEIdqCDAaDIXOUUm+AwWAwBjLMCTMYDIaEePbh3/Q3fiFe/IPBYDDkg9NQLDsJMxgMhoQwJ8xg\nMBgS [...]
       "text/plain": [
-       "<matplotlib.figure.Figure at 0x7f72a06d2bd0>"
+       "<matplotlib.figure.Figure at 0x7faac037ff10>"
       ]
      },
      "metadata": {},
@@ -41,34 +42,9 @@
    ],
    "source": [
     "%matplotlib inline\n",
-    "from matplotlib.pyplot import figure, xlim, ylim\n",
-    "from mpl_toolkits.axes_grid.axislines import SubplotZero\n",
-    "from numpy import linspace, arange, sqrt, pi, sin, cos, sign\n",
-    "# axis style\n",
-    "def make_plot_ax():\n",
-    "    fig = figure(figsize=(6, 5));\n",
-    "    ax = SubplotZero(fig, 111); fig.add_subplot(ax)\n",
-    "    for direction in [\"xzero\", \"yzero\"]:\n",
-    "        ax.axis[direction].set_axisline_style(\"-|>\")\n",
-    "        ax.axis[direction].set_visible(True)\n",
-    "    for direction in [\"left\", \"right\", \"bottom\", \"top\"]:\n",
-    "        ax.axis[direction].set_visible(False)\n",
-    "    xlim(-0.1, 2.1); ylim(xlim())\n",
-    "    ticks = [0.5 * i for i in range(1, 5)]\n",
-    "    labels = [str(i) if i == int(i) else \"\" for i in ticks]\n",
-    "    ax.set_xticks(ticks); ax.set_yticks(ticks)\n",
-    "    ax.set_xticklabels(labels); ax.set_yticklabels(labels)\n",
-    "    ax.axis[\"yzero\"].set_axis_direction(\"left\")\n",
-    "    return ax\n",
-    "    \n",
-    "ax = make_plot_ax()\n",
-    "ax.plot((0, 2), (2, 0), 'b')\n",
-    "ax.plot([1], [1], 'bo')\n",
+    "import plot_helper\n",
     "\n",
-    "# circular grid\n",
-    "for r in sqrt(2.) + 0.125 * arange(-11, 6):\n",
-    "    t = linspace(0., pi/2., 100)\n",
-    "    ax.plot(r * cos(t), r * sin(t), '-.', color=\"gray\")"
+    "plot_helper.plot_qp1()"
    ]
   },
   {
@@ -241,9 +217,10 @@
    "outputs": [
     {
      "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWAAAAEmCAYAAABcYEo9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJztnXn85mPVx9/XbJaZQYgsYwlpEBkV8kQ8yFIo7UIJpcWS\np4Xi3B9LSQupnhZLSKhMlsryULaKoQyyhVCWQdl3s3yfP65rdM8992/7bvfyO+/X6/divvd9nevM\nb2bO77qvc87nhCzLqIoQws7wujPgjknwv8CXr8qyJ7eobEPHcZweIlQbgCdeBHO3hsVehrmLwzMA\nK2RZ9nBlmzqO4/QIFQfgMBFYMv3yQWC5LMv+VdmGjuM4PUSlAXiBjULIsiwLtWzmOI7TA4zptAOO\n4zijFQ/AjuM4HcIDsOM4TofwAOw4jtMhPAA7juN0CA/AjuM4HcIDsOM4TofwAOw4jtMhPAA7juN0\nCA/A [...]
+      "application/pdf": "JVBERi0xLjQKJazcIKu6CjEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1BhZ2VzIDIgMCBSID4+\nCmVuZG9iago4IDAgb2JqCjw8IC9YT2JqZWN0IDcgMCBSIC9QYXR0ZXJuIDUgMCBSCi9Qcm9jU2V0\nIFsgL1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9FeHRHU3RhdGUgNCAwIFIK\nL1NoYWRpbmcgNiAwIFIgL0ZvbnQgMyAwIFIgPj4KZW5kb2JqCjEwIDAgb2JqCjw8IC9Hcm91cCA8\nPCAvQ1MgL0RldmljZVJHQiAvUyAvVHJhbnNwYXJlbmN5IC9UeXBlIC9Hcm91cCA+PiAvUGFyZW50\nIDIgMCBSCi9NZWRpYUJveCBbIDAgMCAzNTMuODg4MDY4MTgxOCAyOTQuMjE4MTgxODE4MiBdIC9B [...]
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWEAAAEmCAYAAACzoiEDAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3XlUVFe+L/DvgWIoChAEBQVkEIkjCJpBozEajUZjTEcz\naNp0d+yYpO/Kff365va6767V6/Xt9V73uuutezt222mTNnY6mihmMIoT0TiPITiggMyTUsxFDVDT\nqTrvDxpbrAJhn6mq+H3W6tWhqs7eG4Rfndq/vX+bEwQBcuI4jgOi7cAnIcAKAEkAOjcJgrBD1o4J\nIcQPcAoE4ZcB7AHG/P2RXgBBFYJgmyprx4QQ4gdkD8IAwHHcLAAaAFcA5AGoFQTBKHvHhBDi4xQJ\nwnc74zhBEAROsQ4JIcTHBak9AEIIGc0oCBNCiIo0DNeInb9Qbv6DEEJ8h9epWLoTJoQQFVEQJoQQ\nFVEQ [...]
       "text/plain": [
-       "<matplotlib.figure.Figure at 0x7f72705b3fd0>"
+       "<matplotlib.figure.Figure at 0x7faac4871d90>"
       ]
      },
      "metadata": {},
@@ -251,14 +228,7 @@
     }
    ],
    "source": [
-    "ax = make_plot_ax()\n",
-    "ax.plot((0, 2), (2, 0), 'b')\n",
-    "ax.plot([0.5], [1.5], 'bo')\n",
-    "\n",
-    "yrange = linspace(1, 2, 11)\n",
-    "for r in (yrange ** 2 / 2. - yrange):\n",
-    "    t = linspace(-sqrt(2 * r + 1) + 0.000001, sqrt(2 * r + 1) - 0.000001, 1000)\n",
-    "    ax.plot(abs(t), 1 + sqrt(2 * r + 1 - t ** 2) * sign(t), '-.', color=\"gray\")"
+    "plot_helper.plot_qp2()"
    ]
   },
   {
diff --git a/documentation_builder/simulating.ipynb b/documentation_builder/simulating.ipynb
index 00c6b54..a7b6793 100644
--- a/documentation_builder/simulating.ipynb
+++ b/documentation_builder/simulating.ipynb
@@ -41,7 +41,7 @@
     {
      "data": {
       "text/plain": [
-       "<Solution 0.87 at 0x7fe558058b50>"
+       "<Solution 0.87 at 0x7ff4fc14b210>"
       ]
      },
      "execution_count": 2,
@@ -124,7 +124,7 @@
    "source": [
     "## Changing the Objectives\n",
     "\n",
-    "The objective function is determined from the objective_coefficient attribute of the objective reaction(s). Currently in the model, there is only one objective reaction, with an objective coefficient of 1."
+    "The objective function is determined from the objective_coefficient attribute of the objective reaction(s). Generally, a \"biomass\" function which describes the composition of metabolites which make up a cell is used."
    ]
   },
   {
@@ -133,14 +133,32 @@
    "metadata": {
     "collapsed": false
    },
+   "outputs": [],
+   "source": [
+    "biomass_rxn = model.reactions.get_by_id(\"Biomass_Ecoli_core\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Currently in the model, there is only one objective reaction (the biomass reaction), with an objective coefficient of 1."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {
+    "collapsed": false
+   },
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "{<Reaction Biomass_Ecoli_core at 0x7fe526516490>: 1.0}"
+       "{<Reaction Biomass_Ecoli_core at 0x7ff4cb9a8d90>: 1.0}"
       ]
      },
-     "execution_count": 5,
+     "execution_count": 6,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -158,7 +176,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 7,
    "metadata": {
     "collapsed": false
    },
@@ -166,25 +184,27 @@
     {
      "data": {
       "text/plain": [
-       "{<Reaction ATPM at 0x7fe526516210>: 1}"
+       "{<Reaction ATPM at 0x7ff4cb9a8b10>: 1}"
       ]
      },
-     "execution_count": 6,
+     "execution_count": 7,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
     "# change the objective to ATPM\n",
-    "# the upper bound should be 1000 so we get the actual optimal value\n",
-    "model.reactions.get_by_id(\"ATPM\").upper_bound = 1000.\n",
     "model.objective = \"ATPM\"\n",
+    "\n",
+    "# The upper bound should be 1000, so that we get\n",
+    "# the actual optimal value\n",
+    "model.reactions.get_by_id(\"ATPM\").upper_bound = 1000.\n",
     "model.objective"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 8,
    "metadata": {
     "collapsed": false
    },
@@ -195,7 +215,7 @@
        "174.99999999999997"
       ]
      },
-     "execution_count": 7,
+     "execution_count": 8,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -213,7 +233,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 9,
    "metadata": {
     "collapsed": false
    },
@@ -221,17 +241,18 @@
     {
      "data": {
       "text/plain": [
-       "{<Reaction Biomass_Ecoli_core at 0x7fe526516490>: 1.0}"
+       "{<Reaction Biomass_Ecoli_core at 0x7ff4cb9a8d90>: 1.0}"
       ]
      },
-     "execution_count": 8,
+     "execution_count": 9,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
     "model.reactions.get_by_id(\"ATPM\").objective_coefficient = 0.\n",
-    "model.reactions.get_by_id(\"Biomass_Ecoli_core\").objective_coefficient = 1.\n",
+    "biomass_rxn.objective_coefficient = 1.\n",
+    "\n",
     "model.objective"
    ]
   },
@@ -246,7 +267,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 10,
    "metadata": {
     "collapsed": false
    },
@@ -392,13 +413,14 @@
        "EX_ac_e            -3.933509e-15  0.000000e+00"
       ]
      },
-     "execution_count": 9,
+     "execution_count": 10,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "fva_result = cobra.flux_analysis.flux_variability_analysis(model, model.reactions[:20])\n",
+    "fva_result = cobra.flux_analysis.flux_variability_analysis(\n",
+    "    model, model.reactions[:20])\n",
     "pandas.DataFrame.from_dict(fva_result).T"
    ]
   },
@@ -411,7 +433,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 11,
    "metadata": {
     "collapsed": false
    },
@@ -557,13 +579,14 @@
        "EX_ac_e             3.813556e+00   0.000000"
       ]
      },
-     "execution_count": 10,
+     "execution_count": 11,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "fva_result = cobra.flux_analysis.flux_variability_analysis(model, model.reactions[:20], fraction_of_optimum=0.9)\n",
+    "fva_result = cobra.flux_analysis.flux_variability_analysis(\n",
+    "    model, model.reactions[:20], fraction_of_optimum=0.9)\n",
     "pandas.DataFrame.from_dict(fva_result).T"
    ]
   },
@@ -578,14 +601,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 12,
    "metadata": {
     "collapsed": false
    },
    "outputs": [],
    "source": [
-    "FBA_solution = model.optimize()\n",
-    "pFBA_solution = cobra.flux_analysis.optimize_minimal_flux(model)"
+    "FBA_sol = model.optimize()\n",
+    "pFBA_sol = cobra.flux_analysis.optimize_minimal_flux(model)"
    ]
   },
   {
@@ -597,7 +620,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 13,
    "metadata": {
     "collapsed": false
    },
@@ -608,13 +631,13 @@
        "1.1102230246251565e-16"
       ]
      },
-     "execution_count": 12,
+     "execution_count": 13,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "abs(FBA_solution.f - pFBA_solution.f)"
+    "abs(FBA_sol.f - pFBA_sol.f)"
    ]
   }
  ],
diff --git a/documentation_builder/solvers.ipynb b/documentation_builder/solvers.ipynb
index e39688c..9b36268 100644
--- a/documentation_builder/solvers.ipynb
+++ b/documentation_builder/solvers.ipynb
@@ -74,7 +74,7 @@
     {
      "data": {
       "text/plain": [
-       "<Solution 0.87 at 0x7f9148bb2250>"
+       "<Solution 0.87 at 0x7f15f00de750>"
       ]
      },
      "execution_count": 3,
@@ -136,7 +136,7 @@
     {
      "data": {
       "text/plain": [
-       "<Solution 0.87 at 0x7f917d50ed50>"
+       "<Solution 0.87 at 0x7f15bc67a910>"
       ]
      },
      "execution_count": 5,
@@ -167,7 +167,7 @@
     {
      "data": {
       "text/plain": [
-       "<cobra.solvers.cglpk.GLP at 0x46e8aa0>"
+       "<cobra.solvers.cglpk.GLP at 0x402ea50>"
       ]
      },
      "execution_count": 6,
@@ -230,7 +230,7 @@
     {
      "data": {
       "text/plain": [
-       "<Solution 0.87 at 0x7f917d50e9d0>"
+       "<Solution 0.87 at 0x7f15d3cdb1d0>"
       ]
      },
      "execution_count": 8,
@@ -625,28 +625,29 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "CPU times: user 144 ms, sys: 667 µs, total: 145 ms\n",
-      "Wall time: 141 ms\n"
+      "CPU times: user 153 ms, sys: 4.14 ms, total: 157 ms\n",
+      "Wall time: 155 ms\n"
      ]
     }
    ],
    "source": [
     "%%time\n",
     "# work on a copy of the model so the original is not changed\n",
-    "fva_model = model.copy()\n",
+    "m = model.copy()\n",
     "\n",
     "# set the lower bound on the objective to be the optimal value\n",
-    "f = fva_model.optimize().f\n",
-    "for objective_reaction, coefficient in fva_model.objective.items():\n",
+    "f = m.optimize().f\n",
+    "for objective_reaction, coefficient in m.objective.items():\n",
     "    objective_reaction.lower_bound = coefficient * f\n",
     "\n",
     "# now maximize and minimze every reaction to find its bounds\n",
     "fva_result = {}\n",
-    "for r in fva_model.reactions:\n",
-    "    fva_model.change_objective(r)\n",
-    "    fva_result[r.id] = {}\n",
-    "    fva_result[r.id][\"maximum\"] = fva_model.optimize(objective_sense=\"maximize\").f\n",
-    "    fva_result[r.id][\"minimum\"] = fva_model.optimize(objective_sense=\"minimize\").f"
+    "for r in m.reactions:\n",
+    "    m.change_objective(r)\n",
+    "    fva_result[r.id] = {\n",
+    "        \"maximum\": m.optimize(objective_sense=\"maximize\").f,\n",
+    "        \"minimum\": m.optimize(objective_sense=\"minimize\").f\n",
+    "    }"
    ]
   },
   {
@@ -667,8 +668,8 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "CPU times: user 9.85 ms, sys: 251 µs, total: 10.1 ms\n",
-      "Wall time: 9.94 ms\n"
+      "CPU times: user 9.39 ms, sys: 192 µs, total: 9.58 ms\n",
+      "Wall time: 9.05 ms\n"
      ]
     }
    ],
@@ -684,18 +685,21 @@
     "    objective_index = model.reactions.index(objective_reaction)\n",
     "    # old objective is no longer the objective\n",
     "    solver.change_variable_objective(lp, objective_index, 0.)\n",
-    "    solver.change_variable_bounds(lp, objective_index, f * coefficient, objective_reaction.upper_bound)\n",
+    "    solver.change_variable_bounds(\n",
+    "        lp, objective_index, f * coefficient,\n",
+    "        objective_reaction.upper_bound)\n",
     "\n",
     "# now maximize and minimze every reaction to find its bounds\n",
     "fva_result = {}\n",
     "for index, r in enumerate(model.reactions):\n",
     "    solver.change_variable_objective(lp, index, 1.)\n",
-    "    fva_result[r.id] = {}\n",
+    "    result = {}\n",
     "    solver.solve_problem(lp, objective_sense=\"maximize\")\n",
-    "    fva_result[r.id][\"maximum\"] = solver.get_objective_value(lp)\n",
+    "    result[\"maximum\"] = solver.get_objective_value(lp)\n",
     "    solver.solve_problem(lp, objective_sense=\"minimize\")\n",
-    "    fva_result[r.id][\"minimum\"] = solver.get_objective_value(lp)\n",
-    "    solver.change_variable_objective(lp, index, 0.)"
+    "    result[\"minimum\"] = solver.get_objective_value(lp)\n",
+    "    solver.change_variable_objective(lp, index, 0.)\n",
+    "    fva_result[r.id] = result"
    ]
   }
  ],

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/python-cobra.git



More information about the debian-med-commit mailing list