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 test_independent(self): a = DictList([Object("o1"), Object("o2")]) b = DictList() assert "o1" in a assert "o1" not in b b.append(Object("o3")) assert "o3" not in a assert "o3" in b
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")
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 test_init_copy(self, dict_list): obj, test_list = dict_list test_list.append(Object("test2")) copied = DictList(test_list) assert test_list is not copied assert isinstance(copied, test_list.__class__) assert len(test_list) == len(copied) for i, v in enumerate(test_list): assert test_list[i].id == copied[i].id assert i == copied.index(v.id) assert test_list[i] is copied[i] assert v is copied.get_by_id(v.id)
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): from os import name as __name if __name == 'java': warn('\t\n**cobra.test.unit_tests.testAdd does not yet work with %s'%__name) return 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 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")])
def test_sort_and_reverse(self): dl = DictList(Object("test%d" % (i)) for i in reversed(range(10))) assert dl[0].id == "test9" dl.sort() assert len(dl) == 10 assert dl[0].id == "test0" assert dl.index("test0") == 0 dl.reverse() assert dl[0].id == "test9" assert dl.index("test0") == 9
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)
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 __iadd__(self, other): if not isinstance(other, StrainDesign): raise AssertionError("Only instances of StrainDesign can be added together") targets = {} for target in self.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) for target in other.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) targets = [next(iter(t)) if len(t) == 1 else EnsembleTarget(id, t) for id, t in six.iteritems(targets)] self.targets = DictList(targets) return self
def test_set(self): obj_list = DictList(Object("test%d" % (i)) for i in range(10)) obj_list[4] = Object("testa") assert obj_list.index("testa") == 4 assert obj_list[4].id == "testa" obj_list[5:7] = [Object("testb"), Object("testc")] assert obj_list.index("testb") == 5 assert obj_list[5].id == "testb" assert obj_list.index("testc") == 6 assert 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 with pytest.raises(ValueError): obj_list.__setitem__(slice(5, 7), [Object("testd"), Object("testd")])
def _build_targets(self): targets = DictList() for reaction in self.reactions: reaction = self._replace_adapted_metabolites(reaction) if reaction.id in metanetx.mnx2all: target = ReactionKnockinTarget(reaction.id, reaction, accession_id=reaction.id, accession_db='metanetx') else: target = ReactionKnockinTarget(reaction.id, reaction) targets.append(target) for reaction in self.exchanges: reaction = self._replace_adapted_metabolites(reaction) targets.append(ReactionKnockinTarget(reaction.id, reaction)) product = self._replace_adapted_metabolites(self.product) product.lower_bound = 0 targets.append(ReactionKnockinTarget(product.id, product)) return targets
def test_removal(self): obj_list = DictList(Object("test%d" % (i)) for i in range(2, 10)) del obj_list[3] assert "test5" not in obj_list assert obj_list.index(obj_list[-1]) == len(obj_list) - 1 assert len(obj_list) == 7 del obj_list[3:5] assert "test6" not in obj_list assert "test7" not in obj_list assert obj_list.index(obj_list[-1]) == len(obj_list) - 1 assert len(obj_list) == 5 removed = obj_list.pop(1) assert obj_list.index(obj_list[-1]) == len(obj_list) - 1 assert removed.id == "test3" assert "test3" not in obj_list assert len(obj_list) == 4 removed = obj_list.pop() assert removed.id == "test9" assert removed.id not in obj_list assert len(obj_list) == 3
def create_metanetx_universal_model(validate=False, verbose=False): """ Create an universal model from MetaNetX universal reactions and metabolites. The MetaNetX metabolite list is very large and includes metabolites that are not used in any reaction. The returned model only includes metabolites that are actually used in a reaction. Parameters ---------- validate : bool, optional When True, perform validity checks on universal COBRA model verbose : bool, optional When True, show warning messages Returns ------- cobra.Model COBRA model object with universal reactions and metabolites """ # Create an empty model. universal = Model('metanetx_universal', name='MetaNetX universal model') # Download the metabolites file. metabolite_list = _download_metanetx_file('chem_prop.tsv') # Map field names to column numbers (MetaNetX may add fields in future). field_names = { 'MNX_ID': 0, 'Description': 1, 'Formula': 2, 'Charge': 3, 'Mass': 4, 'InChI': 5, 'SMILES': 6, 'Source': 7, 'InChIKey': 8 } # Accumulate all available Metabolite objects separately. Later when creating # reactions, metabolites are put in a compartment. all_metabolites = DictList() # Create Metabolite objects for all of the metabolites from the downloaded file. # Add all of the universal metabolites from the list. LOGGER.info('Started creating Metabolite objects from %d lines in file', len(metabolite_list)) for index in range(len(metabolite_list)): if len(metabolite_list[index] ) == 0 or metabolite_list[index][0] == '#': continue # Skip empty lines and comment lines fields = metabolite_list[index].split('\t') if len(fields) < len(field_names): if verbose: warn('Skipped metabolite on line {0} with missing fields: {1}'. format(index, metabolite_list[index])) continue # Create cobra.core.Metabolite from MetaNetX metabolite. metabolite = Metabolite(id=fields[field_names['MNX_ID']], name=fields[field_names['Description']], formula=fields[field_names['Formula']]) charge = fields[field_names['Charge']] metabolite.charge = int( charge) if len(charge) > 0 and charge != 'NA' else None mass = fields[field_names['Mass']] if len(mass) > 0: metabolite.notes['mass'] = float(mass) metabolite.notes['InChI'] = fields[field_names['InChI']] \ if len(fields[field_names['InChI']]) > 0 else 'NA' metabolite.notes['SMILES'] = fields[field_names['SMILES']] \ if len(fields[field_names['SMILES']]) > 0 else 'NA' metabolite.notes['source'] = fields[field_names['Source']] \ if len(fields[field_names['Source']]) > 0 else 'NA' metabolite.notes['InChIKey'] = fields[field_names['InChIKey']] \ if len(fields[field_names['InChIKey']]) > 0 else 'NA' all_metabolites.append(metabolite) LOGGER.info('Finished creating %d Metabolite objects', len(all_metabolites)) # Download the compartments file. compartment_list = _download_metanetx_file('comp_prop.tsv') # Map field names to column numbers (MetaNetX may add fields in future). field_names = {'MNX_ID': 0, 'Description': 1, 'Source': 2} # Add the compartments to the universal model. LOGGER.info('Started adding compartments from %d lines in file', len(compartment_list)) for index in range(len(compartment_list)): if len(compartment_list[index] ) == 0 or compartment_list[index][0] == '#': continue # Skip empty lines and comment lines fields = compartment_list[index].split('\t') if len(fields) < len(field_names): if verbose: warn( 'Skipped compartment on line {0} with missing fields: {1}'. format(index, compartment_list[index])) continue universal.compartments[fields[field_names['MNX_ID']]] = fields[ field_names['Description']] LOGGER.info('Finished adding {0} compartments to universal model'.format( len(universal.compartments))) # Download the reactions file. reaction_list = _download_metanetx_file('reac_prop.tsv') # Map field names to column numbers (hopefully MetaNetX doesn't change this). field_names = { 'MNX_ID': 0, 'Equation': 1, 'Description': 2, 'Balance': 3, 'EC': 4, 'Source': 5 } # Accumulate Reaction and Metabolite objects separately because it is faster # than adding them one at a time to a model. reactions = DictList() metabolites = DictList() # Create Reaction objects for all of the reactions from the downloaded file. LOGGER.info('Started creating Reaction objects from %d lines in file', len(reaction_list)) for index in range(len(reaction_list)): if len(reaction_list[index]) == 0 or reaction_list[index][0] == '#': continue # Skip empty lines and comment lines fields = reaction_list[index].split('\t') if len(fields) != len(field_names): if verbose: warn('Skipped reaction on line {0} with missing fields: {1}'. format(index, reaction_list[index])) continue # Create cobra.core.Reaction from MetaNetX reaction. metabolite_info = _parse_metanetx_equation( fields[field_names['Equation']]) if metabolite_info is None: if verbose: warn( 'Could not parse equation for reaction {0} on line {1}: {2}' .format(fields[field_names['MNX_ID']], index, fields[field_names['Equation']])) continue rxn_mets = dict() for metabolite_id in metabolite_info: try: rxn_mets[metabolites.get_by_id( metabolite_id )] = metabolite_info[metabolite_id]['coefficient'] except KeyError: metabolite = all_metabolites.get_by_id( metabolite_info[metabolite_id]['mnx_id']).copy() metabolite.id = metabolite_id metabolite.compartment = metabolite_info[metabolite_id][ 'compartment'] metabolites.append(metabolite) rxn_mets[metabolite] = metabolite_info[metabolite_id][ 'coefficient'] reaction = Reaction(id=fields[field_names['MNX_ID']], name=fields[field_names['MNX_ID']], lower_bound=-1000.0, upper_bound=1000.0) reaction.add_metabolites(rxn_mets) if len(fields[field_names['EC']]) > 0: reaction.notes['EC_number'] = fields[field_names['EC']] if len(fields[field_names['Source']]) > 1: parts = fields[field_names['Source']].split(':') if len(parts) == 2: reaction.notes['aliases'] = {parts[0]: parts[1]} else: if verbose: warn('Could not parse source for {0}: {1}'.format( fields[field_names['MNX_ID']], fields[field_names['Source']])) reactions.append(reaction) LOGGER.info('Finished creating %d Reaction objects', len(reactions)) # Add the reactions to the universal model. universal.add_reactions(reactions) LOGGER.info('Finished adding Reaction objects to universal model') # If requested, validate the COBRA model. if validate: warn('Coming soon') return universal
def __init__(self, targets): self.targets = DictList(targets)
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)
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")])
def setUp(self): self.obj = Object("test1") self.list = DictList() self.list.append(self.obj)
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
class StrainDesign(object): """ A StrainDesign is a collection of targets in a COBRA model. The targets, identified by a StrainDesignMethod, map elements in the model that need to be modified to achieve the objective of the design method. """ def __init__(self, targets): self.targets = DictList(targets) def __str__(self): return ", ".join(str(t) for t in self.targets) def __repr__(self): return "<StrainDesign [" + ";".join(repr(t) for t in self.targets) + "]>" def __iter__(self): return iter(self.targets) def __len__(self): return len(self.targets) def __contains__(self, item): if isinstance(item, Target): if item in self.targets: return item == self.targets.get_by_id(item.id) else: return False elif isinstance(item, six.string_types): return item in self.targets else: return False def __eq__(self, other): if isinstance(other, StrainDesign): if len(self) != len(other): return False else: return all(t in other for t in self.targets) and all( t in self for t in other.targets) else: return False def apply(self, model): for target in self.targets: target.apply(model) def __add__(self, other): if not isinstance(other, StrainDesign): raise AssertionError( "Only instances of StrainDesign can be added together") targets = {} for target in self.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) for target in other.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) targets = [ next(iter(t)) if len(t) == 1 else EnsembleTarget(id, t) for id, t in six.iteritems(targets) ] return StrainDesign(targets) def __iadd__(self, other): if not isinstance(other, StrainDesign): raise AssertionError( "Only instances of StrainDesign can be added together") targets = {} for target in self.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) for target in other.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) targets = [ next(iter(t)) if len(t) == 1 else EnsembleTarget(id, t) for id, t in six.iteritems(targets) ] self.targets = DictList(targets) return self def _repr_html_(self): return " ".join(t._repr_html_() for t in self.targets) def to_gnomic(self): return Genotype([target.to_gnomic() for target in self.targets])
def dict_list(): obj = Object("test1") test_list = DictList() test_list.append(obj) return obj, test_list
class StrainDesign(object): """ A StrainDesign is a collection of targets in a COBRA model. The targets, identified by a StrainDesignMethod, map elements in the model that need to be modified to achieve the objective of the design method. """ def __init__(self, targets): self.targets = DictList(targets) def __str__(self): return ", ".join(str(t) for t in self.targets) def __repr__(self): return "<StrainDesign [" + ";".join(repr(t) for t in self.targets) + "]>" def __iter__(self): return iter(self.targets) def __len__(self): return len(self.targets) def __contains__(self, item): if isinstance(item, Target): if item in self.targets: return item == self.targets.get_by_id(item.id) else: return False elif isinstance(item, six.string_types): return item in self.targets else: return False def __eq__(self, other): if isinstance(other, StrainDesign): if len(self) != len(other): return False else: return all(t in other for t in self.targets) and all(t in self for t in other.targets) else: return False def apply(self, model): for target in self.targets: target.apply(model) def __add__(self, other): if not isinstance(other, StrainDesign): raise AssertionError("Only instances of StrainDesign can be added together") targets = {} for target in self.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) for target in other.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) targets = [next(iter(t)) if len(t) == 1 else EnsembleTarget(id, t) for id, t in six.iteritems(targets)] return StrainDesign(targets) def __iadd__(self, other): if not isinstance(other, StrainDesign): raise AssertionError("Only instances of StrainDesign can be added together") targets = {} for target in self.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) for target in other.targets: if target.id not in targets: targets[target.id] = set() targets[target.id].add(target) targets = [next(iter(t)) if len(t) == 1 else EnsembleTarget(id, t) for id, t in six.iteritems(targets)] self.targets = DictList(targets) return self def _repr_html_(self): return " ".join(t._repr_html_() for t in self.targets) def to_gnomic(self): return Genotype([target.to_gnomic() for target in self.targets])
def __init__(self, enzymes = None, scaled = False, *args, **kwargs): ExpressionReaction.__init__(self, scaled, *args, **kwargs) self.enzymes = DictList() if enzymes: self.add_enzymes(enzymes)
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)
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()
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)
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")