Пример #1
0
class TestDictList(TestCase):
    def setUp(self):
        self.obj = Object("test1")
        self.list = DictList()
        self.list.append(self.obj)

    def testAppend(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        self.assertRaises(ValueError, self.list.append,
            Object("test1"))
        self.assertEqual(self.list.index(obj2), 1)
        self.assertEqual(self.list[1], obj2)
        self.assertEqual(self.list.get_by_id("test2"), obj2)
        self.assertEqual(len(self.list), 2)

    def testExtend(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list.extend(obj_list)
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)

    def testIadd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list += obj_list
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)


    def testAdd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        sum = self.list + obj_list
        self.assertEqual(self.list[0].id, "test1")
        self.assertEqual(sum[1].id, "test2")
        self.assertEqual(sum.get_by_id("test2"), obj_list[0])
        self.assertEqual(sum[8].id, "test9")
        self.assertEqual(len(self.list), 1)
        self.assertEqual(len(sum), 9)

    def testDeepcopy(self):
        from copy import deepcopy
        copied = deepcopy(self.list)
        for i, v in enumerate(self.list):
            assert self.list[i].id == copied[i].id
            assert self.list[i] is not copied[i]

    def testQuery(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        result = self.list.query("test1")  # matches only test1
        self.assertEqual(len(result), 1)
        self.assertEqual(result[0], self.obj)
        result = self.list.query("test")  # matches test1 and test2
        self.assertEqual(len(result), 2)
Пример #2
0
class TestDictList(TestCase):
    def setUp(self):
        self.obj = Object("test1")
        self.list = DictList()
        self.list.append(self.obj)

    def testAppend(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        self.assertRaises(ValueError, self.list.append, Object("test1"))
        self.assertEqual(self.list.index(obj2), 1)
        self.assertEqual(self.list[1], obj2)
        self.assertEqual(self.list.get_by_id("test2"), obj2)
        self.assertEqual(len(self.list), 2)

    def testExtend(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list.extend(obj_list)
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)

    def testIadd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list += obj_list
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)

    def testAdd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        sum = self.list + obj_list
        self.assertEqual(self.list[0].id, "test1")
        self.assertEqual(sum[1].id, "test2")
        self.assertEqual(sum.get_by_id("test2"), obj_list[0])
        self.assertEqual(sum[8].id, "test9")
        self.assertEqual(len(self.list), 1)
        self.assertEqual(len(sum), 9)

    def testDeepcopy(self):
        from copy import deepcopy
        copied = deepcopy(self.list)
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertIsNot(self.list[i], copied[i])

    def testQuery(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        result = self.list.query("test1")  # matches only test1
        self.assertEqual(len(result), 1)
        self.assertEqual(result[0], self.obj)
        result = self.list.query("test")  # matches test1 and test2
        self.assertEqual(len(result), 2)
Пример #3
0
class TestDictList(TestCase):
    def setUp(self):
        self.obj = Object("test1")
        self.list = DictList()
        self.list.append(self.obj)

    def testContains(self):
        self.assertIn(self.obj, self.list)
        self.assertIn(self.obj.id, self.list)
        self.assertNotIn(Object("not_in"), self.list)
        self.assertNotIn('not_in', self.list)

    def testIndex(self):
        self.assertEqual(self.list.index("test1"), 0)
        self.assertEqual(self.list.index(self.obj), 0)
        self.assertRaises(ValueError, self.list.index, "f")
        self.assertRaises(ValueError, self.list.index, Object("f"))
        # ensure trying to index with an object that is a different object
        # also raises an error
        self.assertRaises(ValueError, self.list.index, Object("test1"))

    def testIndependent(self):
        a = DictList([Object("o1"), Object("o2")])
        b = DictList()
        self.assertIn("o1", a)
        self.assertNotIn("o1", b)
        b.append(Object("o3"))
        self.assertNotIn("o3", a)
        self.assertIn("o3", b)

    def testAppend(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        self.assertRaises(ValueError, self.list.append, Object("test1"))
        self.assertEqual(self.list.index(obj2), 1)
        self.assertEqual(self.list[1], obj2)
        self.assertIs(self.list.get_by_id("test2"), obj2)
        self.assertEqual(len(self.list), 2)

    def testInsert(self):
        obj2 = Object("a")
        self.list.insert(0, obj2)
        self.assertEqual(self.list.index(obj2), 0)
        self.assertEqual(self.list.index("test1"), 1)
        self.assertIs(self.list.get_by_id("a"), obj2)
        self.assertEqual(len(self.list), 2)
        self.assertRaises(ValueError, self.list.append, obj2)

    def testExtend(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list.extend(obj_list)
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)
        self.assertRaises(ValueError, self.list.extend, [Object("test1")])
        # Even if the object is unique, if it is present twice in the new
        # list, it should still raise an exception
        self.assertRaises(ValueError, self.list.extend,
                          [Object("testd"), Object("testd")])

    def testIadd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list += obj_list
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)

    def testAdd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        sum = self.list + obj_list
        self.assertIsNot(sum, self.list)
        self.assertIsNot(sum, obj_list)
        self.assertEqual(self.list[0].id, "test1")
        self.assertEqual(sum[1].id, "test2")
        self.assertEqual(sum.get_by_id("test2"), obj_list[0])
        self.assertEqual(sum[8].id, "test9")
        self.assertEqual(len(self.list), 1)
        self.assertEqual(len(sum), 9)

    def testInitCopy(self):
        self.list.append(Object("test2"))
        copied = DictList(self.list)
        self.assertIsNot(self.list, copied)
        self.assertIsInstance(copied, self.list.__class__)
        self.assertEqual(len(self.list), len(copied))
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertEqual(i, copied.index(v.id))
            self.assertIs(self.list[i], copied[i])
            self.assertIs(v, copied.get_by_id(v.id))

    def testSlice(self):
        self.list.append(Object("test2"))
        self.list.append(Object("test3"))
        sliced = self.list[:-1]
        self.assertIsNot(self.list, sliced)
        self.assertIsInstance(sliced, self.list.__class__)
        self.assertEqual(len(self.list), len(sliced) + 1)
        for i, v in enumerate(sliced):
            self.assertEqual(self.list[i].id, sliced[i].id)
            self.assertEqual(i, sliced.index(v.id))
            self.assertIs(self.list[i], sliced[i])
            self.assertIs(self.list[i], sliced.get_by_id(v.id))

    def testCopy(self):
        self.list.append(Object("test2"))
        copied = copy(self.list)
        self.assertIsNot(self.list, copied)
        self.assertIsInstance(copied, self.list.__class__)
        self.assertEqual(len(self.list), len(copied))
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertEqual(i, copied.index(v.id))
            self.assertIs(self.list[i], copied[i])
            self.assertIs(v, copied.get_by_id(v.id))

    def testDeepcopy(self):
        self.list.append(Object("test2"))
        copied = deepcopy(self.list)
        self.assertIsNot(self.list, copied)
        self.assertIsInstance(copied, self.list.__class__)
        self.assertEqual(len(self.list), len(copied))
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertEqual(i, copied.index(v.id))
            self.assertIsNot(self.list[i], copied[i])
            self.assertIsNot(v, copied.get_by_id(v.id))

    def testPickle(self):
        self.list.append(Object("test2"))
        for protocol in range(HIGHEST_PROTOCOL):
            pickle_str = dumps(self.list, protocol=protocol)
            copied = loads(pickle_str)
            self.assertIsNot(self.list, copied)
            self.assertIsInstance(copied, self.list.__class__)
            self.assertEqual(len(self.list), len(copied))
            for i, v in enumerate(self.list):
                self.assertEqual(self.list[i].id, copied[i].id)
                self.assertEqual(i, copied.index(v.id))
                self.assertIsNot(self.list[i], copied[i])
                self.assertIsNot(v, copied.get_by_id(v.id))

    def testQuery(self):
        obj2 = Object("test2")
        obj2.name = "foobar1"
        self.list.append(obj2)
        result = self.list.query("test1")  # matches only test1
        self.assertEqual(len(result), 1)
        self.assertEqual(result[0], self.obj)
        result = self.list.query("foo", "name")  # matches only test2
        self.assertEqual(len(result), 1)
        self.assertEqual(result[0], obj2)
        result = self.list.query("test")  # matches test1 and test2
        self.assertEqual(len(result), 2)
        # test with a regular expression
        result = self.list.query(re.compile("test[0-9]"))
        self.assertEqual(len(result), 2)
        result = self.list.query(re.compile("test[29]"))
        self.assertEqual(len(result), 1)
        # test query of name
        result = self.list.query(re.compile("foobar."), "name")
        self.assertEqual(len(result), 1)

    def testRemoval(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(2, 10))
        del obj_list[3]
        self.assertNotIn("test5", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        self.assertEqual(len(obj_list), 7)
        del obj_list[3:5]
        self.assertNotIn("test6", obj_list)
        self.assertNotIn("test7", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        self.assertEqual(len(obj_list), 5)
        removed = obj_list.pop(1)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        self.assertEqual(removed.id, "test3")
        self.assertNotIn("test3", obj_list)
        self.assertEqual(len(obj_list), 4)
        removed = obj_list.pop()
        self.assertEqual(removed.id, "test9")
        self.assertNotIn(removed.id, obj_list)
        self.assertEqual(len(obj_list), 3)

    def testSet(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(10))
        obj_list[4] = Object("testa")
        self.assertEqual(obj_list.index("testa"), 4)
        self.assertEqual(obj_list[4].id, "testa")
        obj_list[5:7] = [Object("testb"), Object("testc")]
        self.assertEqual(obj_list.index("testb"), 5)
        self.assertEqual(obj_list[5].id, "testb")
        self.assertEqual(obj_list.index("testc"), 6)
        self.assertEqual(obj_list[6].id, "testc")
        # Even if the object is unique, if it is present twice in the new
        # list, it should still raise an exception
        self.assertRaises(ValueError, obj_list.__setitem__, slice(5, 7),
                          [Object("testd"), Object("testd")])

    def testSortandReverse(self):
        dl = DictList(Object("test%d" % (i)) for i in reversed(range(10)))
        self.assertEqual(dl[0].id, "test9")
        dl.sort()
        self.assertEqual(len(dl), 10)
        self.assertEqual(dl[0].id, "test0")
        self.assertEqual(dl.index("test0"), 0)
        dl.reverse()
        self.assertEqual(dl[0].id, "test9")
        self.assertEqual(dl.index("test0"), 9)

    def testDir(self):
        """makes sure tab complete will work"""
        attrs = dir(self.list)
        self.assertIn("test1", attrs)
        self.assertIn("_dict", attrs)  # attribute of DictList

    def testUnion(self):
        self.list.union([Object("test1"), Object("test2")])
        # should only add 1 element
        self.assertEqual(len(self.list), 2)
        self.assertEqual(self.list.index("test2"), 1)
Пример #4
0
class MEModel(Model):
    def __init__(self, *args):
        Model.__init__(self, *args)
        self.global_info = {}
        self.stoichiometric_data = DictList()
        self.complex_data = DictList()
        self.modification_data = DictList()
        self.translation_data = DictList()
        self.transcription_data = DictList()
        self.generic_data = DictList()
        self.tRNA_data = DictList()
        self.translocation_data = DictList()
        self.posttranslation_data = DictList()
        self.subreaction_data = DictList()
        self.process_data = DictList()
        # create the biomass/dilution constraint
        self._biomass = Constraint("biomass")
        self._biomass_dilution = SummaryVariable("biomass_dilution")
        self._biomass_dilution.add_metabolites({self._biomass: -1})
        self.add_reaction(self._biomass_dilution)
        self._biomass_dilution.upper_bound = mu
        self._biomass_dilution.lower_bound = mu
        # maintenance energy
        self._gam = 0.
        self._ngam = 0.
        # Unmodeled protein is handled by converting protein_biomass to
        # biomass, and requiring production of the appropriate amount of dummy
        # protein
        self._unmodeled_protein_fraction = None
        self._protein_biomass = Constraint("protein_biomass")
        self._protein_biomass_dilution = SummaryVariable(
            "protein_biomass_dilution")
        self._protein_biomass_dilution.add_metabolites({
            self._protein_biomass:
            -1,
            self._biomass:
            1,
        })
        self._mRNA_biomass = Constraint("mRNA_biomass")
        self._mRNA_biomass_dilution = SummaryVariable("mRNA_biomass_dilution")
        self._mRNA_biomass_dilution.add_metabolites({
            self._mRNA_biomass: -1,
            self._biomass: 1,
        })
        self._tRNA_biomass = Constraint("tRNA_biomass")
        self._tRNA_biomass_dilution = SummaryVariable("tRNA_biomass_dilution")
        self._tRNA_biomass_dilution.add_metabolites({
            self._tRNA_biomass: -1,
            self._biomass: 1,
        })
        self._rRNA_biomass = Constraint("rRNA_biomass")
        self._rRNA_biomass_dilution = SummaryVariable("rRNA_biomass_dilution")
        self._rRNA_biomass_dilution.add_metabolites({
            self._rRNA_biomass: -1,
            self._biomass: 1,
        })

        self._ncRNA_biomass = Constraint("ncRNA_biomass")
        self._ncRNA_biomass_dilution = SummaryVariable(
            "ncRNA_biomass_dilution")
        self._ncRNA_biomass_dilution.add_metabolites({
            self._ncRNA_biomass: -1,
            self._biomass: 1,
        })

        self._DNA_biomass = Constraint("DNA_biomass")
        self._DNA_biomass_dilution = SummaryVariable("DNA_biomass_dilution")
        self._DNA_biomass_dilution.add_metabolites({
            self._DNA_biomass: -1,
            self._biomass: 1,
        })

        self.add_reactions(
            (self._protein_biomass_dilution, self._mRNA_biomass_dilution,
             self._tRNA_biomass_dilution, self._rRNA_biomass_dilution,
             self._ncRNA_biomass_dilution, self._DNA_biomass_dilution))

    @property
    def unmodeled_protein(self):
        return self.metabolites.get_by_id("protein_dummy")

    @property
    def unmodeled_protein_fraction(self):
        return self._unmodeled_protein_fraction

    @property
    def unmodeled_protein_biomass(self):
        return self.metabolites.get_by_id('dummy_protein_biomass')

    @unmodeled_protein_fraction.setter
    def unmodeled_protein_fraction(self, value):
        # see the Biomass_formulations for an explanation
        amount = value / (1 - value)
        self._protein_biomass_dilution.add_metabolites(
            {self.unmodeled_protein_biomass: -amount}, combine=False)
        self._protein_biomass_dilution.add_metabolites(
            {self._biomass: 1 + amount}, combine=False)
        self._unmodeled_protein_fraction = value

    @property
    def gam(self):
        return self._gam

    @gam.setter
    def gam(self, value):
        if 'GAM' not in self.reactions:
            warn('Adding GAM reaction to model')
            self.add_reaction(SummaryVariable("GAM"))
            self.reactions.GAM.lower_bound = mu
        atp_hydrolysis = {
            'atp_c': -1,
            'h2o_c': -1,
            'adp_c': 1,
            'h_c': 1,
            'pi_c': 1
        }
        for met, coeff in iteritems(atp_hydrolysis):
            self.reactions.GAM.add_metabolites({met: value * coeff},
                                               combine=False)
        self._gam = value

    @property
    def ngam(self):
        return self._ngam

    @ngam.setter
    def ngam(self, value):
        if 'ATPM' not in self.reactions:
            warn('Adding ATPM reaction to model')
            atp_hydrolysis = {
                'atp_c': -1,
                'h2o_c': -1,
                'adp_c': 1,
                'h_c': 1,
                'pi_c': 1
            }
            self.add_reaction(SummaryVariable("ATPM"))
            self.reactions.ATPM.add_metabolites(atp_hydrolysis)
        self.reactions.ATPM.lower_bound = value
        self._ngam = value

    def get_metabolic_flux(self, solution=None):
        """extract the flux state for metabolic reactions"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {r.id: 0 for r in self.stoichiometric_data}
        for reaction in self.reactions:
            if isinstance(reaction, MetabolicReaction):
                m_reaction_id = reaction.stoichiometric_data.id
                if reaction.reverse:
                    flux_dict[m_reaction_id] -= solution.x_dict[reaction.id]
                else:
                    flux_dict[m_reaction_id] += solution.x_dict[reaction.id]
            elif reaction.id.startswith("EX_") or reaction.id.startswith("DM"):
                flux_dict[reaction.id] = solution.x_dict[reaction.id]
        return flux_dict

    def get_transcription_flux(self, solution=None):
        """extract the transcription flux state"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {}
        for reaction in self.reactions:
            if isinstance(reaction, TranscriptionReaction):
                for rna_id in reaction.transcription_data.RNA_products:
                    locus_id = rna_id.replace("RNA_", "", 1)
                    if locus_id not in flux_dict:
                        flux_dict[locus_id] = 0
                    flux_dict[locus_id] += solution.x_dict[reaction.id]
        return flux_dict

    def get_translation_flux(self, solution=None):
        """extract the translation flux state"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {r.id: 0 for r in self.translation_data}
        for reaction in self.reactions:
            if isinstance(reaction, TranslationReaction):
                protein_id = reaction.translation_data.id
                flux_dict[protein_id] += solution.x_dict[reaction.id]
        return flux_dict

    def construct_S(self, growth_rate):
        """build the stoichiometric matrix at a specific growth rate"""
        # intialize to 0
        S = dok_matrix((len(self.metabolites), len(self.reactions)))
        # populate with stoichiometry
        for i, r in enumerate(self.reactions):
            for met, value in iteritems(r._metabolites):
                met_index = self.metabolites.index(met)
                if hasattr(value, "subs"):
                    S[met_index, i] = float(value.subs(mu, growth_rate))
                else:
                    S[met_index, i] = float(value)
        return S

    def construct_attribute_vector(self, attr_name, growth_rate):
        """build a vector of a reaction attribute at a specific growth rate

        Mainly used for upper and lower bounds"""
        return array([
            float(value.subs(mu, growth_rate))
            if hasattr(value, "subs") else float(value)
            for value in self.reactions.list_attr(attr_name)
        ])

    def compute_solution_error(self, solution=None):
        errors = {}
        if solution is None:
            solution = self.solution
        S = self.construct_S(solution.f)
        lb = self.construct_attribute_vector("lower_bound", solution.f)
        ub = self.construct_attribute_vector("upper_bound", solution.f)
        x = array(solution.x)
        err = abs(S * x)
        errors["max_error"] = err.max()
        errors["sum_error"] = err.sum()
        ub_err = min(ub - x)
        errors["upper_bound_error"] = abs(ub_err) if ub_err < 0 else 0
        lb_err = min(x - lb)
        errors["lower_bound_error"] = abs(lb_err) if lb_err < 0 else 0
        return errors

    def update(self):
        """updates all component reactions"""
        for r in self.reactions:
            if hasattr(r, "update"):
                r.update()

    def prune(self, skip=[]):
        """remove all unused metabolites and reactions

        This should be run after the model is fully built. It will be
        difficult to add new content to the model once this has been run.

        skip: [str]
            List of complexes/proteins/mRNAs/TUs to remain unpruned from model.
        """
        complex_data_list = [
            i.id for i in self.complex_data if i.id not in skip
        ]
        for c_d in complex_data_list:
            c = self.complex_data.get_by_id(c_d)
            cplx = c.complex
            if len(cplx.reactions) == 1:
                list(cplx.reactions)[0].delete(remove_orphans=True)
                self.complex_data.remove(self.complex_data.get_by_id(c_d))

        for p in self.metabolites.query('_folded'):
            if 'partially' not in p.id and p.id not in skip:
                delete = True
                for rxn in p._reaction:
                    try:
                        if p in rxn.reactants:
                            delete = False
                    except Exception as e:
                        print(rxn)
                        raise e
                if delete:
                    while len(p._reaction) > 0:
                        list(p._reaction)[0].delete(remove_orphans=True)
                        for data in self.posttranslation_data.query(p.id):
                            self.posttranslation_data.remove(data.id)

        for p in self.metabolites.query(re.compile('^protein_')):
            if isinstance(p, ProcessedProtein) and p.id not in skip:
                delete = True
                for rxn in p._reaction:
                    try:
                        if p in rxn.reactants:
                            delete = False
                    except Exception as e:
                        print(rxn)
                        raise e
                if delete:
                    while len(p._reaction) > 0:
                        list(p._reaction)[0].delete(remove_orphans=True)
                        for data in self.posttranslation_data.query(p.id):
                            self.posttranslation_data.remove(data.id)

        for p in self.metabolites.query(re.compile('^protein_')):
            if isinstance(p, TranslatedGene) and p.id not in skip:
                delete = True
                for rxn in p._reaction:
                    try:
                        if p in rxn.reactants and not rxn.id.startswith(
                                'degradation'):
                            delete = False
                    except Exception as e:
                        print(rxn)
                        raise e
                if delete:
                    while len(p._reaction) > 0:
                        list(p._reaction)[0].delete(remove_orphans=True)
                        p_id = p.id.replace('protein_', '')
                        for data in self.translation_data.query(p_id):
                            self.translation_data.remove(data.id)

        removed_RNA = set()
        for m in list(self.metabolites.query(re.compile("^RNA_"))):
            if m.id in skip:
                delete = False
            else:
                delete = True

            for rxn in m._reaction:
                if m in rxn.reactants and not rxn.id.startswith('DM_'):
                    delete = False
            if delete:
                try:
                    self.reactions.get_by_id('DM_' + m.id).remove_from_model(
                        remove_orphans=True)
                    if m in self.metabolites:
                        m.remove_from_model(method='subtractive')
                except KeyError:
                    pass
                else:
                    removed_RNA.add(m.id)

        for t in self.reactions.query('transcription_TU'):
            if t.id in skip:
                delete = False
            else:
                delete = True

            for product in t.products:
                if isinstance(product, TranscribedGene):
                    delete = False
            t_process_id = t.id.replace('transcription_', '')
            if delete:
                t.remove_from_model(remove_orphans=True)
                self.transcription_data.remove(t_process_id)
            else:
                # gets rid of the removed RNA from the products
                self.transcription_data.get_by_id(
                    t_process_id).RNA_products.difference_update(removed_RNA)

            # update to update the TranscriptionReaction mRNA biomass
            # stoichiometry with new RNA_products
            if not delete:
                t.update()

    def remove_genes_from_model(self, gene_list):
        for gene in gene_list:
            self.metabolites.get_by_id('RNA_' + gene).remove_from_model(
                method='subtractive')
            protein = self.metabolites.get_by_id('protein_' + gene)
            for cplx in protein.complexes:
                print('Complex (%s) removed from model' % cplx.id)
                for rxn in cplx.metabolic_reactions:
                    try:
                        self.stoichiometric_data.remove(rxn.id.split('_')[0])
                    except ValueError:
                        pass
                    rxn.remove_from_model()

            protein.remove_from_model(method='destructive')

        # Remove all transcription reactions that now do not form a used
        # transcript
        for t in self.reactions.query('transcription_TU'):
            delete = True
            for product in t.products:
                if isinstance(product, TranscribedGene):
                    delete = False
            if delete:
                t.remove_from_model(remove_orphans=True)
                t_process_id = t.id.replace('transcription_', '')
                self.transcription_data.remove(t_process_id)

    def set_SASA_keffs(self, avg_keff):
        SASA_list = []
        for rxn in self.reactions:
            if hasattr(rxn, 'keff') and rxn.complex_data is not None:
                weight = rxn.complex_data.complex.mass
                SASA = weight**(3. / 4.)
                if SASA == 0:
                    warn('Keff not updated for %s' % rxn)
                else:
                    SASA_list.append(SASA)

        for data in self.process_data:
            cplx_mw = 0.
            if isinstance(data, TranslocationData):
                continue
            if hasattr(data, 'keff') and data.enzyme is not None:
                if type(data.enzyme) == str:
                    cplxs = [data.enzyme]
                else:
                    cplxs = data.enzyme
                for cplx in cplxs:
                    if cplx in self.complex_data:
                        try:
                            cplx_mw += self.metabolites.get_by_id(cplx).mass \
                                       ** (3. / 4)
                        except:
                            warn('Complex (%s) cannot access mass' % cplx)
                    elif cplx.split('_mod_')[0] in self.complex_data:
                        cplx_mw += self.metabolites.get_by_id(
                            cplx.split('_mod_')[0]).mass**(3. / 4)

                SASA_list.append(cplx_mw)

        avg_SASA = array(SASA_list).mean()

        # redo scaling average SASA to 65.
        for rxn in self.reactions:
            if hasattr(rxn, 'keff') and rxn.complex_data is not None:
                weight = rxn.complex_data.complex.mass
                SASA = weight**(3. / 4.)
                if SASA == 0:
                    SASA = avg_SASA
                rxn.keff = SASA * avg_keff / avg_SASA
        for data in self.process_data:
            SASA = 0.
            if isinstance(data, TranslocationData):
                continue
            if hasattr(data, 'keff') and data.enzyme is not None:
                if data.enzyme == str:
                    cplxs = [data.enzyme]
                else:
                    cplxs = data.enzyme
                for cplx in cplxs:
                    if cplx in self.complex_data:
                        SASA += self.metabolites.get_by_id(cplx).mass**(3. / 4)
                    elif cplx.split('_mod_')[0] in self.complex_data:
                        SASA += self.metabolites.get_by_id(
                            cplx.split('_mod_')[0]).mass**(3. / 4)

                if SASA == 0:
                    SASA = avg_SASA
                data.keff = SASA * avg_keff / avg_SASA

        self.update()
Пример #5
0
class TestDictList(TestCase):
    def setUp(self):
        self.obj = Object("test1")
        self.list = DictList()
        self.list.append(self.obj)

    def testContains(self):
        self.assertIn(self.obj, self.list)
        self.assertIn(self.obj.id, self.list)
        self.assertNotIn(Object("not_in"), self.list)
        self.assertNotIn('not_in', self.list)

    def testIndex(self):
        self.assertEqual(self.list.index("test1"), 0)
        self.assertEqual(self.list.index(self.obj), 0)
        self.assertRaises(ValueError, self.list.index, "f")
        self.assertRaises(ValueError, self.list.index, Object("f"))

    def testIndependent(self):
        a = DictList([Object("o1"), Object("o2")])
        b = DictList()
        self.assertIn("o1", a)
        self.assertNotIn("o1", b)
        b.append(Object("o3"))
        self.assertNotIn("o3", a)
        self.assertIn("o3", b)

    def testAppend(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        self.assertRaises(ValueError, self.list.append, Object("test1"))
        self.assertEqual(self.list.index(obj2), 1)
        self.assertEqual(self.list[1], obj2)
        self.assertEqual(self.list.get_by_id("test2"), obj2)
        self.assertEqual(len(self.list), 2)

    def testExtend(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list.extend(obj_list)
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)
        self.assertRaises(ValueError, self.list.extend, [Object("test1")])
        # Even if the object is unique, if it is present twice in the new
        # list, it should still raise an exception
        self.assertRaises(ValueError, self.list.extend,
                          [Object("testd"), Object("testd")])

    def testIadd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list += obj_list
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)

    def testAdd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        sum = self.list + obj_list
        self.assertIsNot(sum, self.list)
        self.assertIsNot(sum, obj_list)
        self.assertEqual(self.list[0].id, "test1")
        self.assertEqual(sum[1].id, "test2")
        self.assertEqual(sum.get_by_id("test2"), obj_list[0])
        self.assertEqual(sum[8].id, "test9")
        self.assertEqual(len(self.list), 1)
        self.assertEqual(len(sum), 9)

    def testInitCopy(self):
        self.list.append(Object("test2"))
        copied = DictList(self.list)
        self.assertIsNot(self.list, copied)
        self.assertIsInstance(copied, self.list.__class__)
        self.assertEqual(len(self.list), len(copied))
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertEqual(i, copied.index(v.id))
            self.assertIs(self.list[i], copied[i])
            self.assertIs(v, copied.get_by_id(v.id))

    def testSlice(self):
        self.list.append(Object("test2"))
        self.list.append(Object("test3"))
        sliced = self.list[:-1]
        self.assertIsNot(self.list, sliced)
        self.assertIsInstance(sliced, self.list.__class__)
        self.assertEqual(len(self.list), len(sliced) + 1)
        for i, v in enumerate(sliced):
            self.assertEqual(self.list[i].id, sliced[i].id)
            self.assertEqual(i, sliced.index(v.id))
            self.assertIs(self.list[i], sliced[i])
            self.assertIs(self.list[i], sliced.get_by_id(v.id))

    def testCopy(self):
        self.list.append(Object("test2"))
        copied = copy(self.list)
        self.assertIsNot(self.list, copied)
        self.assertIsInstance(copied, self.list.__class__)
        self.assertEqual(len(self.list), len(copied))
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertEqual(i, copied.index(v.id))
            self.assertIs(self.list[i], copied[i])
            self.assertIs(v, copied.get_by_id(v.id))

    def testDeepcopy(self):
        self.list.append(Object("test2"))
        copied = deepcopy(self.list)
        self.assertIsNot(self.list, copied)
        self.assertIsInstance(copied, self.list.__class__)
        self.assertEqual(len(self.list), len(copied))
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertEqual(i, copied.index(v.id))
            self.assertIsNot(self.list[i], copied[i])
            self.assertIsNot(v, copied.get_by_id(v.id))

    def testPickle(self):
        self.list.append(Object("test2"))
        for protocol in range(HIGHEST_PROTOCOL):
            pickle_str = dumps(self.list, protocol=protocol)
            copied = loads(pickle_str)
            self.assertIsNot(self.list, copied)
            self.assertIsInstance(copied, self.list.__class__)
            self.assertEqual(len(self.list), len(copied))
            for i, v in enumerate(self.list):
                self.assertEqual(self.list[i].id, copied[i].id)
                self.assertEqual(i, copied.index(v.id))
                self.assertIsNot(self.list[i], copied[i])
                self.assertIsNot(v, copied.get_by_id(v.id))

    def testQuery(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        result = self.list.query("test1")  # matches only test1
        self.assertEqual(len(result), 1)
        self.assertEqual(result[0], self.obj)
        result = self.list.query("test")  # matches test1 and test2
        self.assertEqual(len(result), 2)

    def testRemoval(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(2, 10))
        del obj_list[3]
        self.assertNotIn("test5", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        del obj_list[3:5]
        self.assertNotIn("test6", obj_list)
        self.assertNotIn("test7", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        removed = obj_list.pop(1)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        self.assertEqual(removed.id, "test3")
        self.assertNotIn("test3", obj_list)

    def testSet(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(10))
        obj_list[4] = Object("testa")
        self.assertEqual(obj_list.index("testa"), 4)
        self.assertEqual(obj_list[4].id, "testa")
        obj_list[5:7] = [Object("testb"), Object("testc")]
        self.assertEqual(obj_list.index("testb"), 5)
        self.assertEqual(obj_list[5].id, "testb")
        self.assertEqual(obj_list.index("testc"), 6)
        self.assertEqual(obj_list[6].id, "testc")
        # Even if the object is unique, if it is present twice in the new
        # list, it should still raise an exception
        self.assertRaises(ValueError, obj_list.__setitem__, slice(5, 7),
                          [Object("testd"), Object("testd")])
Пример #6
0
class MEmodel(Model):
    def __init__(self, *args):
        Model.__init__(self, *args)
        self.global_info = {}
        self.stoichiometric_data = DictList()
        self.complex_data = DictList()
        self.modification_data = DictList()
        self.translation_data = DictList()
        self.transcription_data = DictList()
        self.generic_data = DictList()
        self.tRNA_data = DictList()
        self.translocation_data = DictList()
        self.posttranslation_data = DictList()
        self.subreaction_data = DictList()
        self.process_data = DictList()
        # create the biomass/dilution constraint
        self._biomass = Constraint("biomass")
        self._biomass_dilution = SummaryVariable("biomass_dilution")
        self._biomass_dilution.add_metabolites({self._biomass: -1})
        self.add_reaction(self._biomass_dilution)
        self._biomass_dilution.upper_bound = mu
        self._biomass_dilution.lower_bound = mu
        # Unmodeled protein is handled by converting protein_biomass to
        # biomass, and requiring production of the appropriate amount of dummy
        # protein
        self._unmodeled_protein_fraction = None
        self._protein_biomass = Constraint("protein_biomass")
        self._protein_biomass_dilution = SummaryVariable(
            "protein_biomass_dilution")
        self._protein_biomass_dilution.add_metabolites({
            self._protein_biomass:
            -1,
            self._biomass:
            1,
        })
        self._mRNA_biomass = Constraint("mRNA_biomass")
        self._mRNA_biomass_dilution = SummaryVariable("mRNA_biomass_dilution")
        self._mRNA_biomass_dilution.add_metabolites({
            self._mRNA_biomass: -1,
            self._biomass: 1,
        })
        self._tRNA_biomass = Constraint("tRNA_biomass")
        self._tRNA_biomass_dilution = SummaryVariable("tRNA_biomass_dilution")
        self._tRNA_biomass_dilution.add_metabolites({
            self._tRNA_biomass: -1,
            self._biomass: 1,
        })
        self._rRNA_biomass = Constraint("rRNA_biomass")
        self._rRNA_biomass_dilution = SummaryVariable("rRNA_biomass_dilution")
        self._rRNA_biomass_dilution.add_metabolites({
            self._rRNA_biomass: -1,
            self._biomass: 1,
        })

        self._ncRNA_biomass = Constraint("ncRNA_biomass")
        self._ncRNA_biomass_dilution = SummaryVariable(
            "ncRNA_biomass_dilution")
        self._ncRNA_biomass_dilution.add_metabolites({
            self._ncRNA_biomass: -1,
            self._biomass: 1,
        })
        self.add_reactions(
            (self._protein_biomass_dilution, self._mRNA_biomass_dilution,
             self._tRNA_biomass_dilution, self._rRNA_biomass_dilution,
             self._ncRNA_biomass_dilution))

        self._DNA_biomass = Constraint("DNA_biomass")
        self._DNA_biomass_dilution = SummaryVariable("DNA_biomass_dilution")
        self._DNA_biomass_dilution.add_metabolites({
            self._DNA_biomass: -1e-3,
            self._biomass: 1e-3,
        })
        self._DNA_biomass_dilution.lower_bound = mu
        self._DNA_biomass_dilution.upper_bound = mu

    @property
    def unmodeled_protein(self):
        return self.metabolites.get_by_id("protein_dummy")

    @property
    def unmodeled_protein_fraction(self):
        return self._unmodeled_protein_fraction

    @unmodeled_protein_fraction.setter
    def unmodeled_protein_fraction(self, value):
        # proportion = value / (1 - value)
        # see the Biomass_formulations for an explanation
        amount = value / self.unmodeled_protein.mass
        self._protein_biomass_dilution.add_metabolites(
            {self.unmodeled_protein: -amount}, combine=False)
        self._protein_biomass_dilution.add_metabolites(
            {self._biomass: 1 + value}, combine=False)
        self._unmodeled_protein_fraction = value

    def get_metabolic_flux(self, solution=None):
        """extract the flux state for metabolic reactions"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {r.id: 0 for r in self.stoichiometric_data}
        for reaction in self.reactions:
            if isinstance(reaction, MetabolicReaction):
                m_reaction_id = reaction.stoichiometric_data.id
                if reaction.reverse:
                    flux_dict[m_reaction_id] -= solution.x_dict[reaction.id]
                else:
                    flux_dict[m_reaction_id] += solution.x_dict[reaction.id]
            elif reaction.id.startswith("EX_") or reaction.id.startswith("DM"):
                flux_dict[reaction.id] = solution.x_dict[reaction.id]
        return flux_dict

    def get_transcription_flux(self, solution=None):
        """extract the transcription flux state"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {}
        for reaction in self.reactions:
            if isinstance(reaction, TranscriptionReaction):
                for rna_id in reaction.transcription_data.RNA_products:
                    locus_id = rna_id.replace("RNA_", "", 1)
                    if locus_id not in flux_dict:
                        flux_dict[locus_id] = 0
                    flux_dict[locus_id] += solution.x_dict[reaction.id]
        return flux_dict

    def get_translation_flux(self, solution=None):
        """extract the translation flux state"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {r.id: 0 for r in self.translation_data}
        for reaction in self.reactions:
            if isinstance(reaction, TranslationReaction):
                protein_id = reaction.translation_data.id
                flux_dict[protein_id] += solution.x_dict[reaction.id]
        return flux_dict

    def construct_S(self, growth_rate):
        """build the stoichiometric matrix at a specific growth rate"""
        # intialize to 0
        S = dok_matrix((len(self.metabolites), len(self.reactions)))
        # populate with stoichiometry
        for i, r in enumerate(self.reactions):
            for met, value in r._metabolites.iteritems():
                met_index = self.metabolites.index(met)
                if hasattr(value, "subs"):
                    S[met_index, i] = float(value.subs(mu, growth_rate))
                else:
                    S[met_index, i] = float(value)
        return S

    def construct_attribute_vector(self, attr_name, growth_rate):
        """build a vector of a reaction attribute at a specific growth rate

        Mainly used for upper and lower bounds"""
        return array([
            float(value.subs(mu, growth_rate))
            if hasattr(value, "subs") else float(value)
            for value in self.reactions.list_attr(attr_name)
        ])

    def compute_solution_error(self, solution=None):
        errors = {}
        if solution is None:
            solution = self.solution
        S = self.construct_S(solution.f)
        lb = self.construct_attribute_vector("lower_bound", solution.f)
        ub = self.construct_attribute_vector("upper_bound", solution.f)
        x = array(solution.x)
        err = abs(S * x)
        errors["max_error"] = err.max()
        errors["sum_error"] = err.sum()
        ub_err = min(ub - x)
        errors["upper_bound_error"] = abs(ub_err) if ub_err < 0 else 0
        lb_err = min(x - lb)
        errors["lower_bound_error"] = abs(lb_err) if lb_err < 0 else 0
        return errors

    def update(self):
        """updates all component reactions"""
        for r in self.reactions:
            if hasattr(r, "update"):
                r.update()

    def prune(self):
        """remove all unused metabolites and reactions

        This should be run after the model is fully built. It will be
        difficult to add new content to the model once this has been run.

        """
        complex_data_list = [i.id for i in self.complex_data]
        for c_d in complex_data_list:
            c = self.complex_data.get_by_id(c_d)
            cplx = c.complex
            if len(cplx.reactions) == 1:
                list(cplx.reactions)[0].delete(remove_orphans=True)
                self.complex_data.remove(self.complex_data.get_by_id(c_d))

        for p in self.metabolites.query(re.compile('^protein_')):
            if isinstance(p, ProcessedProtein):
                delete = True
                for rxn in p._reaction:
                    try:
                        if p in rxn.reactants:
                            delete = False
                    except Exception as e:
                        print(rxn)
                        raise e
                if delete:
                    while len(p._reaction) > 0:
                        list(p._reaction)[0].delete(remove_orphans=True)
                        for data in self.posttranslation_data.query(p.id):
                            self.posttranslation_data.remove(data.id)

        for p in self.metabolites.query(re.compile('^protein_')):
            if isinstance(p, TranslatedGene):
                delete = True
                for rxn in p._reaction:
                    try:
                        if p in rxn.reactants and not rxn.id.startswith(
                                'degradation'):
                            delete = False
                    except Exception as e:
                        print(rxn)
                        raise e
                if delete:
                    while len(p._reaction) > 0:
                        list(p._reaction)[0].delete(remove_orphans=True)
                        p_id = p.id.replace('protein_', '')
                        for data in self.translation_data.query(p_id):
                            self.translation_data.remove(data.id)

        removed_RNA = set()
        for m in list(self.metabolites.query(re.compile("^RNA_"))):
            delete = True
            for rxn in m._reaction:
                if m in rxn.reactants and not rxn.id.startswith('DM_'):
                    delete = False
            if delete:
                try:
                    self.reactions.get_by_id('DM_' + m.id).remove_from_model(
                        remove_orphans=True)
                    if m in self.metabolites:
                        m.remove_from_model(method='subtractive')
                except KeyError:
                    pass
                else:
                    removed_RNA.add(m.id)

        for t in self.reactions.query('transcription_TU'):
            delete = True
            for product in t.products:
                if isinstance(product, TranscribedGene):
                    delete = False
            t_process_id = t.id.replace('transcription_', '')
            if delete:
                t.remove_from_model(remove_orphans=True)
                self.transcription_data.remove(t_process_id)
            else:
                # gets rid of the removed RNA from the products
                self.transcription_data.get_by_id(
                    t_process_id).RNA_products.difference_update(removed_RNA)

    def remove_genes_from_model(self, gene_list):
        for gene in gene_list:
            self.metabolites.get_by_id('RNA_' + gene).remove_from_model(
                method='subtractive')
            protein = self.metabolites.get_by_id('protein_' + gene)
            for cplx in protein.complexes:
                print cplx
                for rxn in cplx.metabolic_reactions:
                    try:
                        self.stoichiometric_data.remove(rxn.id.split('_')[0])
                    except ValueError:
                        pass
                    rxn.remove_from_model()

            protein.remove_from_model(method='destructive')

        # Remove all transcription reactions that now do not form a used
        # transcript
        for t in self.reactions.query('transcription_TU'):
            delete = True
            for product in t.products:
                if isinstance(product, TranscribedGene):
                    delete = False
            if delete:
                t.remove_from_model(remove_orphans=True)
                t_process_id = t.id.replace('transcription_', '')
                self.transcription_data.remove(t_process_id)

    def get_biomass_composition(self, solution=None):
        if solution is None:
            solution = self.solution
        biomass_composition = defaultdict(float)
        for met, stoich in self._protein_biomass_dilution.metabolites.items():
            if abs(stoich) < 1:
                weight = self.unmodeled_protein.mass
                biomass_composition['Unmodeled Protein'] = \
                    solution.x_dict['protein_biomass_dilution'] * \
                    abs(stoich) * weight
        biomass_composition['Protein'] = \
            solution.x_dict['protein_biomass_dilution']
        biomass_composition['tRNA'] = \
            solution.x_dict['tRNA_biomass_dilution']
        biomass_composition['mRNA'] = \
            solution.x_dict['mRNA_biomass_dilution']
        biomass_composition['ncRNA'] = \
            solution.x_dict['ncRNA_biomass_dilution']
        biomass_composition['rRNA'] = \
            solution.x_dict['rRNA_biomass_dilution']
        biomass_composition['Other'] = \
            solution.x_dict['biomass_component_dilution']

        return biomass_composition

    def RNA_to_protein_ratio(self, solution=None):
        composition = self.get_biomass_composition(solution=solution)
        RNA_to_protein = (composition['mRNA'] + composition['tRNA'] +
                          composition['rRNA'] + composition['ncRNA']) / \
                         (composition['Protein'] +
                          composition['Unmodeled Protein'])
        return RNA_to_protein

    def get_RNA_fractions_dict(self, solution=None):
        RNA_fractions = {}
        composition = self.get_biomass_composition(solution=solution)

        tRNA_to_RNA = (
            composition['tRNA']) / (composition['mRNA'] + composition['tRNA'] +
                                    composition['rRNA'] + composition['ncRNA'])
        RNA_fractions['tRNA'] = tRNA_to_RNA

        rRNA_to_RNA = (
            composition['rRNA']) / (composition['mRNA'] + composition['tRNA'] +
                                    composition['rRNA'] + composition['ncRNA'])
        RNA_fractions['rRNA'] = rRNA_to_RNA

        mRNA_to_RNA = (
            composition['mRNA']) / (composition['mRNA'] + composition['tRNA'] +
                                    composition['rRNA'] + composition['ncRNA'])
        RNA_fractions['mRNA'] = mRNA_to_RNA

        ncRNA_to_RNA = (composition['ncRNA']) / (
            composition['mRNA'] + composition['tRNA'] + composition['rRNA'] +
            composition['ncRNA'])
        RNA_fractions['ncRNA'] = ncRNA_to_RNA

        return RNA_fractions

    def make_biomass_composition_piechart(self, solution=None):
        try:
            import brewer2mpl
        except ImportError:
            color_map = None
        else:
            color_map = brewer2mpl.wesanderson.Zissou.mpl_colormap

        try:
            import pandas
        except ImportError:
            raise Exception("Pandas must be installed to get biomass piechart")

        if solution is None:
            solution = self.solution

        summary = {}
        summary['Biomass composition'] = \
            self.get_biomass_composition(solution=solution)
        frame = pandas.DataFrame.from_dict(summary) / solution.f

        print 'Total biomass sum =', frame.sum().values[0]
        return frame.plot(kind='pie',
                          subplots=True,
                          legend=None,
                          colormap=color_map)
Пример #7
0
class TestDictList(TestCase):
    def setUp(self):
        self.obj = Object("test1")
        self.list = DictList()
        self.list.append(self.obj)

    def testIndependent(self):
        a = DictList([Object("o1"), Object("o2")])
        b = DictList()
        self.assertIn("o1", a)
        self.assertNotIn("o1", b)
        b.append(Object("o3"))
        self.assertNotIn("o3", a)
        self.assertIn("o3", b)

    def testAppend(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        self.assertRaises(ValueError, self.list.append,
            Object("test1"))
        self.assertEqual(self.list.index(obj2), 1)
        self.assertEqual(self.list[1], obj2)
        self.assertEqual(self.list.get_by_id("test2"), obj2)
        self.assertEqual(len(self.list), 2)

    def testExtend(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list.extend(obj_list)
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)

    def testIadd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list += obj_list
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)


    def testAdd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        sum = self.list + obj_list
        self.assertEqual(self.list[0].id, "test1")
        self.assertEqual(sum[1].id, "test2")
        self.assertEqual(sum.get_by_id("test2"), obj_list[0])
        self.assertEqual(sum[8].id, "test9")
        self.assertEqual(len(self.list), 1)
        self.assertEqual(len(sum), 9)

    def testDeepcopy(self):
        from copy import deepcopy
        copied = deepcopy(self.list)
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertIsNot(self.list[i], copied[i])

    def testQuery(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        result = self.list.query("test1")  # matches only test1
        self.assertEqual(len(result), 1)
        self.assertEqual(result[0], self.obj) 
        result = self.list.query("test")  # matches test1 and test2
        self.assertEqual(len(result), 2)

    def testRemoval(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(2, 10))
        del obj_list[3]
        self.assertNotIn("test5", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        del obj_list[3:5]
        self.assertNotIn("test6", obj_list)
        self.assertNotIn("test7", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        removed = obj_list.pop(1)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        self.assertEqual(removed.id, "test3")
        self.assertNotIn("test3", obj_list)

    def testSet(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(10))
        obj_list[4] = Object("testa")
        self.assertEqual(obj_list.index("testa"), 4)
        self.assertEqual(obj_list[4].id, "testa")
        obj_list[5:7] = [Object("testb"), Object("testc")]
        self.assertEqual(obj_list.index("testb"), 5)
        self.assertEqual(obj_list[5].id, "testb")
        self.assertEqual(obj_list.index("testc"), 6)
        self.assertEqual(obj_list[6].id, "testc")
Пример #8
0
class MEmodel(Model):
    def __init__(self, *args):
        Model.__init__(self, *args)
        self.global_info = {}
        self.stoichiometric_data = DictList()
        self.complex_data = DictList()
        self.modification_data = DictList()
        self.translation_data = DictList()
        self.transcription_data = DictList()
        self.generic_data = DictList()
        self.tRNA_data = DictList()
        self.translocation_data = DictList()
        self.posttranslation_data = DictList()
        self.subreaction_data = DictList()
        self.process_data = DictList()
        # create the biomass/dilution constraint
        self._biomass = Constraint("biomass")
        self._biomass_dilution = SummaryVariable("biomass_dilution")
        self._biomass_dilution.add_metabolites({self._biomass: -1})
        self.add_reaction(self._biomass_dilution)
        self._biomass_dilution.upper_bound = mu
        self._biomass_dilution.lower_bound = mu
        # Unmodeled protein is handled by converting protein_biomass to
        # biomass, and requiring production of the appropriate amount of dummy
        # protein
        self._unmodeled_protein_fraction = None
        self._protein_biomass = Constraint("protein_biomass")
        self._protein_biomass_dilution = SummaryVariable("protein_biomass_dilution")
        self._protein_biomass_dilution.add_metabolites({
            self._protein_biomass: -1,
            self._biomass: 1,
        })
        self._mRNA_biomass = Constraint("mRNA_biomass")
        self._mRNA_biomass_dilution = SummaryVariable("mRNA_biomass_dilution")
        self._mRNA_biomass_dilution.add_metabolites({
            self._mRNA_biomass: -1,
            self._biomass: 1,
        })
        self._tRNA_biomass = Constraint("tRNA_biomass")
        self._tRNA_biomass_dilution = SummaryVariable("tRNA_biomass_dilution")
        self._tRNA_biomass_dilution.add_metabolites({
            self._tRNA_biomass: -1,
            self._biomass: 1,
        })
        self._rRNA_biomass = Constraint("rRNA_biomass")
        self._rRNA_biomass_dilution = SummaryVariable("rRNA_biomass_dilution")
        self._rRNA_biomass_dilution.add_metabolites({
            self._rRNA_biomass: -1,
            self._biomass: 1,
        })

        self._ncRNA_biomass = Constraint("ncRNA_biomass")
        self._ncRNA_biomass_dilution = SummaryVariable("ncRNA_biomass_dilution")
        self._ncRNA_biomass_dilution.add_metabolites({
            self._ncRNA_biomass: -1,
            self._biomass: 1,
        })
        self.add_reactions((self._protein_biomass_dilution,
                            self._mRNA_biomass_dilution,
                            self._tRNA_biomass_dilution,
                            self._rRNA_biomass_dilution,
                            self._ncRNA_biomass_dilution))

        self._DNA_biomass = Constraint("DNA_biomass")
        self._DNA_biomass_dilution = SummaryVariable("DNA_biomass_dilution")
        self._DNA_biomass_dilution.add_metabolites({
            self._DNA_biomass: -1e-3,
            self._biomass: 1e-3,
        })
        self._DNA_biomass_dilution.lower_bound = mu
        self._DNA_biomass_dilution.upper_bound = mu

    @property
    def unmodeled_protein(self):
        return self.metabolites.get_by_id("protein_dummy")

    @property
    def unmodeled_protein_fraction(self):
        return self._unmodeled_protein_fraction

    @unmodeled_protein_fraction.setter
    def unmodeled_protein_fraction(self, value):
        # proportion = value / (1 - value)
        # see the Biomass_formulations for an explanation
        amount = value / self.unmodeled_protein.mass
        self._protein_biomass_dilution.add_metabolites(
                {self.unmodeled_protein: -amount}, combine=False)
        self._protein_biomass_dilution.add_metabolites(
            {self._biomass: 1+value}, combine=False)
        self._unmodeled_protein_fraction = value

    def get_metabolic_flux(self, solution=None):
        """extract the flux state for metabolic reactions"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {r.id: 0 for r in self.stoichiometric_data}
        for reaction in self.reactions:
            if isinstance(reaction, MetabolicReaction):
                m_reaction_id = reaction.stoichiometric_data.id
                if reaction.reverse:
                    flux_dict[m_reaction_id] -= solution.x_dict[reaction.id]
                else:
                    flux_dict[m_reaction_id] += solution.x_dict[reaction.id]
            elif reaction.id.startswith("EX_") or reaction.id.startswith("DM"):
                flux_dict[reaction.id] = solution.x_dict[reaction.id]
        return flux_dict

    def get_transcription_flux(self, solution=None):
        """extract the transcription flux state"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {}
        for reaction in self.reactions:
            if isinstance(reaction, TranscriptionReaction):
                for rna_id in reaction.transcription_data.RNA_products:
                    locus_id = rna_id.replace("RNA_", "", 1)
                    if locus_id not in flux_dict:
                        flux_dict[locus_id] = 0
                    flux_dict[locus_id] += solution.x_dict[reaction.id]
        return flux_dict

    def get_translation_flux(self, solution=None):
        """extract the translation flux state"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {r.id: 0 for r in self.translation_data}
        for reaction in self.reactions:
            if isinstance(reaction, TranslationReaction):
                protein_id = reaction.translation_data.id
                flux_dict[protein_id] += solution.x_dict[reaction.id]
        return flux_dict

    def construct_S(self, growth_rate):
        """build the stoichiometric matrix at a specific growth rate"""
        # intialize to 0
        S = dok_matrix((len(self.metabolites), len(self.reactions)))
        # populate with stoichiometry
        for i, r in enumerate(self.reactions):
            for met, value in r._metabolites.iteritems():
                met_index = self.metabolites.index(met)
                if hasattr(value, "subs"):
                    S[met_index, i] = float(value.subs(mu, growth_rate))
                else:
                    S[met_index, i] = float(value)
        return S

    def construct_attribute_vector(self, attr_name, growth_rate):
        """build a vector of a reaction attribute at a specific growth rate

        Mainly used for upper and lower bounds"""
        return array([float(value.subs(mu, growth_rate))
                      if hasattr(value, "subs") else float(value)
                      for value in self.reactions.list_attr(attr_name)])

    def compute_solution_error(self, solution=None):
        errors = {}
        if solution is None:
            solution = self.solution
        S = self.construct_S(solution.f)
        lb = self.construct_attribute_vector("lower_bound", solution.f)
        ub = self.construct_attribute_vector("upper_bound", solution.f)
        x = array(solution.x)
        err = abs(S * x)
        errors["max_error"] = err.max()
        errors["sum_error"] = err.sum()
        ub_err = min(ub - x)
        errors["upper_bound_error"] = abs(ub_err) if ub_err < 0 else 0
        lb_err = min(x - lb)
        errors["lower_bound_error"] = abs(lb_err) if lb_err < 0 else 0
        return errors

    def update(self):
        """updates all component reactions"""
        for r in self.reactions:
            if hasattr(r, "update"):
                r.update()

    def prune(self):
        """remove all unused metabolites and reactions

        This should be run after the model is fully built. It will be
        difficult to add new content to the model once this has been run.

        """
        complex_data_list = [i.id for i in self.complex_data]
        for c_d in complex_data_list:
            c = self.complex_data.get_by_id(c_d)
            cplx = c.complex
            if len(cplx.reactions) == 1:
                list(cplx.reactions)[0].delete(remove_orphans=True)
                self.complex_data.remove(self.complex_data.get_by_id(c_d))

        for p in self.metabolites.query(re.compile('^protein_')):
            if isinstance(p, ProcessedProtein):
                delete = True
                for rxn in p._reaction:
                    try:
                        if p in rxn.reactants:
                            delete = False
                    except Exception as e:
                        print(rxn)
                        raise e
                if delete:
                    while len(p._reaction) > 0:
                        list(p._reaction)[0].delete(remove_orphans=True)
                        for data in self.posttranslation_data.query(p.id):
                            self.posttranslation_data.remove(data.id)

        for p in self.metabolites.query(re.compile('^protein_')):
            if isinstance(p, TranslatedGene):
                delete = True
                for rxn in p._reaction:
                    try:
                        if p in rxn.reactants and not rxn.id.startswith('degradation'):
                            delete = False
                    except Exception as e:
                        print(rxn)
                        raise e
                if delete:
                    while len(p._reaction) > 0:
                        list(p._reaction)[0].delete(remove_orphans=True)
                        p_id = p.id.replace('protein_', '')
                        for data in self.translation_data.query(p_id):
                            self.translation_data.remove(data.id)


        removed_RNA = set()
        for m in list(self.metabolites.query(re.compile("^RNA_"))):
            delete = True
            for rxn in m._reaction:
                if m in rxn.reactants and not rxn.id.startswith('DM_'):
                    delete = False
            if delete:
                try:
                    self.reactions.get_by_id('DM_' + m.id).remove_from_model(
                            remove_orphans=True)
                    if m in self.metabolites:
                        m.remove_from_model(method='subtractive')
                except KeyError:
                    pass
                else:
                    removed_RNA.add(m.id)

        for t in self.reactions.query('transcription_TU'):
            delete = True
            for product in t.products:
                if isinstance(product, TranscribedGene):
                    delete = False
            t_process_id = t.id.replace('transcription_', '')
            if delete:
                t.remove_from_model(remove_orphans=True)
                self.transcription_data.remove(t_process_id)
            else:
                # gets rid of the removed RNA from the products
                self.transcription_data.get_by_id(
                    t_process_id).RNA_products.difference_update(removed_RNA)

    def remove_genes_from_model(self, gene_list):
        for gene in gene_list:
            self.metabolites.get_by_id('RNA_'+gene).remove_from_model(method='subtractive')
            protein = self.metabolites.get_by_id('protein_'+gene)
            for cplx in protein.complexes:
                print cplx
                for rxn in cplx.metabolic_reactions:
                    try:
                        self.stoichiometric_data.remove(rxn.id.split('_')[0])
                    except ValueError:
                        pass
                    rxn.remove_from_model()

            protein.remove_from_model(method='destructive')

        # Remove all transcription reactions that now do not form a used
        # transcript
        for t in self.reactions.query('transcription_TU'):
            delete = True
            for product in t.products:
                if isinstance(product, TranscribedGene):
                    delete = False
            if delete:
                t.remove_from_model(remove_orphans=True)
                t_process_id = t.id.replace('transcription_', '')
                self.transcription_data.remove(t_process_id)

    def get_biomass_composition(self, solution=None):
        if solution is None:
            solution = self.solution
        biomass_composition = defaultdict(float)
        for met, stoich in self._protein_biomass_dilution.metabolites.items():
            if abs(stoich) < 1:
                weight = self.unmodeled_protein.mass
                biomass_composition['Unmodeled Protein'] = \
                    solution.x_dict['protein_biomass_dilution'] * \
                    abs(stoich) * weight
        biomass_composition['Protein'] = \
            solution.x_dict['protein_biomass_dilution']
        biomass_composition['tRNA'] = \
            solution.x_dict['tRNA_biomass_dilution']
        biomass_composition['mRNA'] = \
            solution.x_dict['mRNA_biomass_dilution']
        biomass_composition['ncRNA'] = \
            solution.x_dict['ncRNA_biomass_dilution']
        biomass_composition['rRNA'] = \
            solution.x_dict['rRNA_biomass_dilution']
        biomass_composition['Other'] = \
            solution.x_dict['biomass_component_dilution']

        return biomass_composition

    def RNA_to_protein_ratio(self, solution=None):
        composition = self.get_biomass_composition(solution=solution)
        RNA_to_protein = (composition['mRNA'] + composition['tRNA'] +
                          composition['rRNA'] + composition['ncRNA']) / \
                         (composition['Protein'] +
                          composition['Unmodeled Protein'])
        return RNA_to_protein

    def get_RNA_fractions_dict(self, solution=None):
        RNA_fractions = {}
        composition = self.get_biomass_composition(solution=solution)

        tRNA_to_RNA = (composition['tRNA']) / (
        composition['mRNA'] + composition['tRNA'] + composition['rRNA'] +
        composition['ncRNA'])
        RNA_fractions['tRNA'] = tRNA_to_RNA

        rRNA_to_RNA = (composition['rRNA']) / (
        composition['mRNA'] + composition['tRNA'] + composition['rRNA'] +
        composition['ncRNA'])
        RNA_fractions['rRNA'] = rRNA_to_RNA

        mRNA_to_RNA = (composition['mRNA']) / (
        composition['mRNA'] + composition['tRNA'] + composition['rRNA'] +
        composition['ncRNA'])
        RNA_fractions['mRNA'] = mRNA_to_RNA

        ncRNA_to_RNA = (composition['ncRNA']) / (
        composition['mRNA'] + composition['tRNA'] + composition['rRNA'] +
        composition['ncRNA'])
        RNA_fractions['ncRNA'] = ncRNA_to_RNA

        return RNA_fractions

    def make_biomass_composition_piechart(self, solution=None):
        try:
            import brewer2mpl
        except ImportError:
            color_map = None
        else:
            color_map = brewer2mpl.wesanderson.Zissou.mpl_colormap

        try:
            import pandas
        except ImportError:
            raise Exception("Pandas must be installed to get biomass piechart")

        if solution is None:
            solution = self.solution

        summary = {}
        summary['Biomass composition'] = \
            self.get_biomass_composition(solution=solution)
        frame = pandas.DataFrame.from_dict(summary) / solution.f


        print 'Total biomass sum =', frame.sum().values[0]
        return frame.plot(kind='pie', subplots=True, legend=None, colormap=color_map)
Пример #9
0
class MEModel(Model):
    def __init__(self, *args):
        Model.__init__(self, *args)
        self.global_info = {}
        self.process_data = DictList()
        # create the biomass/dilution constraint
        self._biomass = Constraint("biomass")
        self._biomass_dilution = SummaryVariable("biomass_dilution")
        self._biomass_dilution.add_metabolites({self._biomass: -1})
        self.add_reactions([self._biomass_dilution])
        self._biomass_dilution.upper_bound = mu
        self._biomass_dilution.lower_bound = mu
        # maintenance energy
        self._gam = 0.
        self._ngam = 0.
        # Unmodeled protein is handled by converting protein_biomass to
        # biomass, and requiring production of the appropriate amount of dummy
        # protein
        self._unmodeled_protein_fraction = None

    def add_biomass_constraints_to_model(self, biomass_types):
        for biomass_type in biomass_types:
            if '_biomass' not in biomass_type:
                raise ValueError('Biomass types should be suffixed with '
                                 '"_biomass"')
            constraint_obj = Constraint(biomass_type)
            summary_variable_obj = SummaryVariable("%s_to_biomass" %
                                                   biomass_type)
            summary_variable_obj.add_metabolites({
                constraint_obj: -1,
                self._biomass: 1
            })
            self.add_reactions([summary_variable_obj])

    @property
    def unmodeled_protein(self):
        return self.metabolites.get_by_id("protein_dummy")

    @property
    def unmodeled_protein_fraction(self):
        return self._unmodeled_protein_fraction

    @property
    def unmodeled_protein_biomass(self):
        return self.metabolites.get_by_id('unmodeled_protein_biomass')

    @unmodeled_protein_fraction.setter
    def unmodeled_protein_fraction(self, value):
        if 'protein_biomass_to_biomass' not in self.reactions:
            raise UserWarning("Must add SummaryVariable handling the protein"
                              "biomass constraint (via "
                              ":meth:`add_biomass_constraints_to_model`) "
                              "before defining the unmodeled protein fraction")

        # see the Biomass_formulations for an explanation
        amount = value / (1 - value)
        self.reactions.protein_biomass_to_biomass.add_metabolites(
            {self.unmodeled_protein_biomass: -amount}, combine=False)
        self.reactions.protein_biomass_to_biomass.add_metabolites(
            {self._biomass: 1 + amount}, combine=False)
        self._unmodeled_protein_fraction = value

    @property
    def gam(self):
        return self._gam

    @gam.setter
    def gam(self, value):
        if 'GAM' not in self.reactions:
            warn('Adding GAM reaction to model')
            self.add_reactions([SummaryVariable("GAM")])
            self.reactions.GAM.lower_bound = mu
        atp_hydrolysis = {
            'atp_c': -1,
            'h2o_c': -1,
            'adp_c': 1,
            'h_c': 1,
            'pi_c': 1
        }
        for met, coeff in iteritems(atp_hydrolysis):
            self.reactions.GAM.add_metabolites({met: value * coeff},
                                               combine=False)
        self._gam = value

    @property
    def ngam(self):
        return self._ngam

    @ngam.setter
    def ngam(self, value):
        if 'ATPM' not in self.reactions:
            warn('Adding ATPM reaction to model')
            atp_hydrolysis = {
                'atp_c': -1,
                'h2o_c': -1,
                'adp_c': 1,
                'h_c': 1,
                'pi_c': 1
            }
            self.add_reactions([SummaryVariable("ATPM")])
            self.reactions.ATPM.add_metabolites(atp_hydrolysis)
        self.reactions.ATPM.lower_bound = value
        self._ngam = value

    @property
    def stoichiometric_data(self):
        for data in self.process_data:
            if isinstance(data, processdata.StoichiometricData):
                yield data

    @property
    def complex_data(self):
        for data in self.process_data:
            if isinstance(data, processdata.ComplexData):
                yield data

    @property
    def translation_data(self):
        for data in self.process_data:
            if isinstance(data, processdata.TranslationData):
                yield data

    @property
    def transcription_data(self):
        for data in self.process_data:
            if isinstance(data, processdata.TranscriptionData):
                yield data

    @property
    def generic_data(self):
        for data in self.process_data:
            if isinstance(data, processdata.GenericData):
                yield data

    @property
    def tRNA_data(self):
        for data in self.process_data:
            if isinstance(data, processdata.tRNAData):
                yield data

    @property
    def translocation_data(self):
        for data in self.process_data:
            if isinstance(data, processdata.TranslocationData):
                yield data

    @property
    def posttranslation_data(self):
        for data in self.process_data:
            if isinstance(data, processdata.PostTranslationData):
                yield data

    @property
    def subreaction_data(self):
        for data in self.process_data:
            if isinstance(data, processdata.SubreactionData):
                yield data

    def get_metabolic_flux(self, solution=None):
        """extract the flux state for metabolic reactions"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {r.id: 0 for r in self.stoichiometric_data}
        for reaction in self.reactions:
            if isinstance(reaction, MetabolicReaction):
                m_reaction_id = reaction.stoichiometric_data.id
                if reaction.reverse:
                    flux_dict[m_reaction_id] -= solution.x_dict[reaction.id]
                else:
                    flux_dict[m_reaction_id] += solution.x_dict[reaction.id]
            elif reaction.id.startswith("EX_") or reaction.id.startswith("DM"):
                flux_dict[reaction.id] = solution.x_dict[reaction.id]
        return flux_dict

    def get_transcription_flux(self, solution=None):
        """extract the transcription flux state"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {}
        for reaction in self.reactions:
            if isinstance(reaction, TranscriptionReaction):
                for rna_id in reaction.transcription_data.RNA_products:
                    locus_id = rna_id.replace("RNA_", "", 1)
                    if locus_id not in flux_dict:
                        flux_dict[locus_id] = 0
                    flux_dict[locus_id] += solution.x_dict[reaction.id]
        return flux_dict

    def get_translation_flux(self, solution=None):
        """extract the translation flux state"""
        if solution is None:
            solution = self.solution
        if solution.status != "optimal":
            raise ValueError("solution status '%s' is not 'optimal'" %
                             solution.status)
        flux_dict = {r.id: 0 for r in self.translation_data}
        for reaction in self.reactions:
            if isinstance(reaction, TranslationReaction):
                protein_id = reaction.translation_data.id
                flux_dict[protein_id] += solution.x_dict[reaction.id]
        return flux_dict

    def construct_s_matrix(self, growth_rate):
        """build the stoichiometric matrix at a specific growth rate"""
        # intialize to 0
        s = dok_matrix((len(self.metabolites), len(self.reactions)))
        # populate with stoichiometry
        for i, r in enumerate(self.reactions):
            for met, value in iteritems(r._metabolites):
                met_index = self.metabolites.index(met)
                if hasattr(value, "subs"):
                    s[met_index, i] = float(value.subs(mu, growth_rate))
                else:
                    s[met_index, i] = float(value)
        return s

    def construct_attribute_vector(self, attr_name, growth_rate):
        """build a vector of a reaction attribute at a specific growth rate

        Mainly used for upper and lower bounds"""
        return array([
            float(value.subs(mu, growth_rate))
            if hasattr(value, "subs") else float(value)
            for value in self.reactions.list_attr(attr_name)
        ])

    def compute_solution_error(self, solution=None):
        errors = {}
        if solution is None:
            solution = self.solution
        s = self.construct_s_matrix(solution.f)
        lb = self.construct_attribute_vector("lower_bound", solution.f)
        ub = self.construct_attribute_vector("upper_bound", solution.f)
        x = array(solution.x)
        err = abs(s * x)
        errors["max_error"] = err.max()
        errors["sum_error"] = err.sum()
        ub_err = min(ub - x)
        errors["upper_bound_error"] = abs(ub_err) if ub_err < 0 else 0
        lb_err = min(x - lb)
        errors["lower_bound_error"] = abs(lb_err) if lb_err < 0 else 0
        return errors

    def update(self):
        """updates all component reactions"""
        for r in self.reactions:
            if hasattr(r, "update"):
                r.update()

    def prune(self, skip=None):
        """remove all unused metabolites and reactions

        This should be run after the model is fully built. It will be
        difficult to add new content to the model once this has been run.

        skip: list
            List of complexes/proteins/mRNAs/TUs to remain unpruned from model.
        """
        if not skip:
            skip = []

        complex_data_list = [
            i.id for i in self.complex_data if i.id not in skip
        ]
        for c_d in complex_data_list:
            c = self.process_data.get_by_id(c_d)
            cplx = c.complex
            if len(cplx.reactions) == 1:
                list(cplx.reactions)[0].delete(remove_orphans=True)
                self.process_data.remove(self.process_data.get_by_id(c_d))

        for p in self.metabolites.query('_folded'):
            if 'partially' not in p.id and p.id not in skip:
                delete = True
                for rxn in p.reactions:
                    if rxn.metabolites[p] < 0:
                        delete = False
                        break

                if delete:
                    while len(p.reactions) > 0:
                        list(p.reactions)[0].delete(remove_orphans=True)
                        for data in self.process_data.query(p.id):
                            self.process_data.remove(data.id)

        for p in self.metabolites.query(re.compile('^protein_')):
            if isinstance(p, ProcessedProtein) and p.id not in skip:
                delete = True
                for rxn in p.reactions:
                    if rxn.metabolites[p] < 0:
                        delete = False
                        break
                if delete:
                    for rxn in list(p.reactions):
                        self.process_data.remove(rxn.posttranslation_data.id)
                        rxn.delete(remove_orphans=True)

        for p in self.metabolites.query(re.compile('^protein_')):
            if isinstance(p, TranslatedGene) and p.id not in skip:
                delete = True
                for rxn in p.reactions:

                    if rxn.metabolites[p] < 0 and not rxn.id.startswith(
                            'degradation'):
                        delete = False
                        break

                if delete:
                    for rxn in list(p.reactions):
                        p_id = p.id.replace('protein_', '')
                        data = self.process_data.get_by_id(p_id)
                        self.process_data.remove(data.id)
                        rxn.delete(remove_orphans=True)

        removed_rna = set()
        for m in list(self.metabolites.query(re.compile("^RNA_"))):

            delete = False if m.id in skip else True

            for rxn in m.reactions:
                if rxn.metabolites[m] < 0 and not rxn.id.startswith('DM_'):
                    delete = False
            if delete:
                try:
                    self.reactions.get_by_id('DM_' + m.id).remove_from_model(
                        remove_orphans=True)
                    if m in self.metabolites:
                        # Defaults to subtractive when removing reaction
                        m.remove_from_model()
                except KeyError:
                    pass
                else:
                    removed_rna.add(m.id)

        for t in self.reactions.query('transcription_TU'):
            if t.id in skip:
                delete = False
            else:
                delete = True

            for product in t.products:
                if isinstance(product, TranscribedGene):
                    delete = False

            t_process_id = t.id.replace('transcription_', '')
            if delete:
                t.remove_from_model(remove_orphans=True)
                self.process_data.remove(t_process_id)
            else:
                # gets rid of the removed RNA from the products
                self.process_data.get_by_id(
                    t_process_id).RNA_products.difference_update(removed_rna)

            # update to update the TranscriptionReaction mRNA biomass
            # stoichiometry with new RNA_products
            if not delete:
                t.update()

    def remove_genes_from_model(self, gene_list):
        for gene in gene_list:
            # defaults to subtractive when removing model
            self.metabolites.get_by_id('RNA_' + gene).remove_from_model()
            protein = self.metabolites.get_by_id('protein_' + gene)
            for cplx in protein.complexes:
                print('Complex (%s) removed from model' % cplx.id)
                for rxn in cplx.metabolic_reactions:
                    try:
                        self.process_data.remove(rxn.id.split('_')[0])
                    except ValueError:
                        pass
                    rxn.remove_from_model()

            # If cannot import SymbolicParameter, assume using cobrapy
            # versions <= 0.5.11
            try:
                from optlang.interface import SymbolicParameter
            except ImportError:
                protein.remove_from_model(method='destructive')
            else:
                protein.remove_from_model(destructive=True)

        # Remove all transcription reactions that now do not form a used
        # transcript
        for t in self.reactions.query('transcription_TU'):
            delete = True
            for product in t.products:
                if isinstance(product, TranscribedGene):
                    delete = False
            if delete:
                t.remove_from_model(remove_orphans=True)
                t_process_id = t.id.replace('transcription_', '')
                self.process_data.remove(t_process_id)

    def set_sasa_keffs(self, avg_keff):
        sasa_list = []
        for rxn in self.reactions:
            if hasattr(rxn, 'keff') and rxn.complex_data is not None:
                weight = rxn.complex_data.complex.mass
                sasa = weight**(3. / 4.)
                if sasa == 0:
                    warn('Keff not updated for %s' % rxn)
                else:
                    sasa_list.append(sasa)

        for data in self.process_data:
            cplx_mw = 0.
            if isinstance(data, processdata.TranslocationData):
                continue
            if hasattr(data, 'keff') and data.enzyme is not None:
                if type(data.enzyme) == str:
                    cplxs = [data.enzyme]
                else:
                    cplxs = data.enzyme
                for cplx in cplxs:
                    if cplx in self.process_data:
                        try:
                            cplx_mw += self.metabolites.get_by_id(cplx).mass \
                                ** (3. / 4)
                        except:
                            warn('Complex (%s) cannot access mass' % cplx)
                    elif cplx.split('_mod_')[0] in self.process_data:
                        cplx_mw += self.metabolites.get_by_id(
                            cplx.split('_mod_')[0]).mass**(3. / 4)

                sasa_list.append(cplx_mw)

        avg_sasa = array(sasa_list).mean()

        # redo scaling average SASA to 65.
        for rxn in self.reactions:
            if hasattr(rxn, 'keff') and rxn.complex_data is not None:
                weight = rxn.complex_data.complex.mass
                sasa = weight**(3. / 4.)
                if sasa == 0:
                    sasa = avg_sasa
                rxn.keff = sasa * avg_keff / avg_sasa
        for data in self.process_data:
            sasa = 0.
            if isinstance(data, processdata.TranslocationData):
                continue
            if hasattr(data, 'keff') and data.enzyme is not None:
                if data.enzyme == str:
                    cplxs = [data.enzyme]
                else:
                    cplxs = data.enzyme
                for cplx in cplxs:
                    if cplx in self.process_data:
                        sasa += \
                            self.metabolites.get_by_id(cplx).mass ** (3. / 4)
                    elif cplx.split('_mod_')[0] in self.process_data:
                        sasa += self.metabolites.get_by_id(
                            cplx.split('_mod_')[0]).mass**(3. / 4)

                if sasa == 0:
                    sasa = avg_sasa
                data.keff = sasa * avg_keff / avg_sasa

        self.update()
Пример #10
0
class TestDictList(TestCase):
    def setUp(self):
        self.obj = Object("test1")
        self.list = DictList()
        self.list.append(self.obj)

    def testContains(self):
        self.assertIn(self.obj, self.list)
        self.assertIn(self.obj.id, self.list)
        self.assertNotIn(Object("not_in"), self.list)
        self.assertNotIn('not_in', self.list)

    def testIndex(self):
        self.assertEqual(self.list.index("test1"), 0)
        self.assertEqual(self.list.index(self.obj), 0)
        self.assertRaises(ValueError, self.list.index, "f")
        self.assertRaises(ValueError, self.list.index, Object("f"))

    def testIndependent(self):
        a = DictList([Object("o1"), Object("o2")])
        b = DictList()
        self.assertIn("o1", a)
        self.assertNotIn("o1", b)
        b.append(Object("o3"))
        self.assertNotIn("o3", a)
        self.assertIn("o3", b)

    def testAppend(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        self.assertRaises(ValueError, self.list.append, Object("test1"))
        self.assertEqual(self.list.index(obj2), 1)
        self.assertEqual(self.list[1], obj2)
        self.assertEqual(self.list.get_by_id("test2"), obj2)
        self.assertEqual(len(self.list), 2)

    def testExtend(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list.extend(obj_list)
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)
        self.assertRaises(ValueError, self.list.extend, [Object("test1")])
        # Even if the object is unique, if it is present twice in the new
        # list, it should still raise an exception
        self.assertRaises(ValueError, self.list.extend,
                          [Object("testd"), Object("testd")])

    def testIadd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list += obj_list
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)

    def testAdd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        sum = self.list + obj_list
        self.assertIsNot(sum, self.list)
        self.assertIsNot(sum, obj_list)
        self.assertEqual(self.list[0].id, "test1")
        self.assertEqual(sum[1].id, "test2")
        self.assertEqual(sum.get_by_id("test2"), obj_list[0])
        self.assertEqual(sum[8].id, "test9")
        self.assertEqual(len(self.list), 1)
        self.assertEqual(len(sum), 9)

    def testInitCopy(self):
        self.list.append(Object("test2"))
        copied = DictList(self.list)
        self.assertIsNot(self.list, copied)
        self.assertIsInstance(copied, self.list.__class__)
        self.assertEqual(len(self.list), len(copied))
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertEqual(i, copied.index(v.id))
            self.assertIs(self.list[i], copied[i])
            self.assertIs(v, copied.get_by_id(v.id))

    def testSlice(self):
        self.list.append(Object("test2"))
        self.list.append(Object("test3"))
        sliced = self.list[:-1]
        self.assertIsNot(self.list, sliced)
        self.assertIsInstance(sliced, self.list.__class__)
        self.assertEqual(len(self.list), len(sliced) + 1)
        for i, v in enumerate(sliced):
            self.assertEqual(self.list[i].id, sliced[i].id)
            self.assertEqual(i, sliced.index(v.id))
            self.assertIs(self.list[i], sliced[i])
            self.assertIs(self.list[i], sliced.get_by_id(v.id))

    def testCopy(self):
        self.list.append(Object("test2"))
        copied = copy(self.list)
        self.assertIsNot(self.list, copied)
        self.assertIsInstance(copied, self.list.__class__)
        self.assertEqual(len(self.list), len(copied))
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertEqual(i, copied.index(v.id))
            self.assertIs(self.list[i], copied[i])
            self.assertIs(v, copied.get_by_id(v.id))

    def testDeepcopy(self):
        self.list.append(Object("test2"))
        copied = deepcopy(self.list)
        self.assertIsNot(self.list, copied)
        self.assertIsInstance(copied, self.list.__class__)
        self.assertEqual(len(self.list), len(copied))
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertEqual(i, copied.index(v.id))
            self.assertIsNot(self.list[i], copied[i])
            self.assertIsNot(v, copied.get_by_id(v.id))

    def testPickle(self):
        self.list.append(Object("test2"))
        for protocol in range(HIGHEST_PROTOCOL):
            pickle_str = dumps(self.list, protocol=protocol)
            copied = loads(pickle_str)
            self.assertIsNot(self.list, copied)
            self.assertIsInstance(copied, self.list.__class__)
            self.assertEqual(len(self.list), len(copied))
            for i, v in enumerate(self.list):
                self.assertEqual(self.list[i].id, copied[i].id)
                self.assertEqual(i, copied.index(v.id))
                self.assertIsNot(self.list[i], copied[i])
                self.assertIsNot(v, copied.get_by_id(v.id))

    def testQuery(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        result = self.list.query("test1")  # matches only test1
        self.assertEqual(len(result), 1)
        self.assertEqual(result[0], self.obj)
        result = self.list.query("test")  # matches test1 and test2
        self.assertEqual(len(result), 2)

    def testRemoval(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(2, 10))
        del obj_list[3]
        self.assertNotIn("test5", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        del obj_list[3:5]
        self.assertNotIn("test6", obj_list)
        self.assertNotIn("test7", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        removed = obj_list.pop(1)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        self.assertEqual(removed.id, "test3")
        self.assertNotIn("test3", obj_list)

    def testSet(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(10))
        obj_list[4] = Object("testa")
        self.assertEqual(obj_list.index("testa"), 4)
        self.assertEqual(obj_list[4].id, "testa")
        obj_list[5:7] = [Object("testb"), Object("testc")]
        self.assertEqual(obj_list.index("testb"), 5)
        self.assertEqual(obj_list[5].id, "testb")
        self.assertEqual(obj_list.index("testc"), 6)
        self.assertEqual(obj_list[6].id, "testc")
        # Even if the object is unique, if it is present twice in the new
        # list, it should still raise an exception
        self.assertRaises(ValueError, obj_list.__setitem__, slice(5, 7),
                          [Object("testd"), Object("testd")])
Пример #11
0
class TestDictList(TestCase):
    def setUp(self):
        self.obj = Object("test1")
        self.list = DictList()
        self.list.append(self.obj)

    def testIndependent(self):
        a = DictList([Object("o1"), Object("o2")])
        b = DictList()
        self.assertIn("o1", a)
        self.assertNotIn("o1", b)
        b.append(Object("o3"))
        self.assertNotIn("o3", a)
        self.assertIn("o3", b)

    def testAppend(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        self.assertRaises(ValueError, self.list.append, Object("test1"))
        self.assertEqual(self.list.index(obj2), 1)
        self.assertEqual(self.list[1], obj2)
        self.assertEqual(self.list.get_by_id("test2"), obj2)
        self.assertEqual(len(self.list), 2)

    def testExtend(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list.extend(obj_list)
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)

    def testIadd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        self.list += obj_list
        self.assertEqual(self.list[1].id, "test2")
        self.assertEqual(self.list.get_by_id("test2"), obj_list[0])
        self.assertEqual(self.list[8].id, "test9")
        self.assertEqual(len(self.list), 9)

    def testAdd(self):
        obj_list = [Object("test%d" % (i)) for i in range(2, 10)]
        sum = self.list + obj_list
        self.assertEqual(self.list[0].id, "test1")
        self.assertEqual(sum[1].id, "test2")
        self.assertEqual(sum.get_by_id("test2"), obj_list[0])
        self.assertEqual(sum[8].id, "test9")
        self.assertEqual(len(self.list), 1)
        self.assertEqual(len(sum), 9)

    def testDeepcopy(self):
        from copy import deepcopy
        copied = deepcopy(self.list)
        for i, v in enumerate(self.list):
            self.assertEqual(self.list[i].id, copied[i].id)
            self.assertIsNot(self.list[i], copied[i])

    def testQuery(self):
        obj2 = Object("test2")
        self.list.append(obj2)
        result = self.list.query("test1")  # matches only test1
        self.assertEqual(len(result), 1)
        self.assertEqual(result[0], self.obj)
        result = self.list.query("test")  # matches test1 and test2
        self.assertEqual(len(result), 2)

    def testRemoval(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(2, 10))
        del obj_list[3]
        self.assertNotIn("test5", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        del obj_list[3:5]
        self.assertNotIn("test6", obj_list)
        self.assertNotIn("test7", obj_list)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        removed = obj_list.pop(1)
        self.assertEqual(obj_list.index(obj_list[-1]), len(obj_list) - 1)
        self.assertEqual(removed.id, "test3")
        self.assertNotIn("test3", obj_list)

    def testSet(self):
        obj_list = DictList(Object("test%d" % (i)) for i in range(10))
        obj_list[4] = Object("testa")
        self.assertEqual(obj_list.index("testa"), 4)
        self.assertEqual(obj_list[4].id, "testa")
        obj_list[5:7] = [Object("testb"), Object("testc")]
        self.assertEqual(obj_list.index("testb"), 5)
        self.assertEqual(obj_list[5].id, "testb")
        self.assertEqual(obj_list.index("testc"), 6)
        self.assertEqual(obj_list[6].id, "testc")