-
Notifications
You must be signed in to change notification settings - Fork 28
/
modelpro.py
174 lines (137 loc) · 5.56 KB
/
modelpro.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import re
import os.path as op
import cobra.io.dict
from cobra.io import load_matlab_model
from cobra.io import read_sbml_model
from cobra.io import load_json_model
from cobra.core import Model
from cobra.core import Gene
from cobra.core import DictList
from ssbio.core.genepro import GenePro
class ModelPro(Model):
def __new__(cls, *args, **kwargs):
"""Casting Gene objects into GenePro objects
This replaces any new instance of Genes with GenePros. Even when you load a model later
using COBRApy methods. Use with caution!
See http://stackoverflow.com/questions/3464061/cast-base-class-to-derived-class-python-or-more-pythonic-way-of-extending-class
Returns:
GenePro: a Gene object with a .protein attribute
"""
if cls == Gene:
return object.__new__(GenePro)
return object.__new__(cls)
Gene.__new__ = staticmethod(__new__)
def __json_encode__(self):
"""convert the model to a dict"""
obj = dict(
reactions=[cobra.io.dict.reaction_to_dict(reaction) for reaction in self.reactions],
metabolites=[
cobra.io.dict.metabolite_to_dict(metabolite) for metabolite in self.metabolites
],
genes = self.genes,
id=self.id,
)
cobra.io.dict._update_optional(self, obj, cobra.io.dict._OPTIONAL_MODEL_ATTRIBUTES, cobra.io.dict._ORDERED_OPTIONAL_MODEL_KEYS)
# add in the JSON version
obj["version"] = 1
return obj
def __json_decode__(self, **attrs):
"""build a model from a dict"""
Model.__init__(self)
if 'reactions' not in attrs:
raise Exception('JSON object has no reactions attribute. Cannot load.')
self.add_metabolites(
[cobra.io.dict.metabolite_from_dict(metabolite) for metabolite in attrs['metabolites']]
)
self.genes = DictList(attrs['genes'])
self.add_reactions(
[cobra.io.dict.reaction_from_dict(reaction, self) for reaction in attrs['reactions']]
)
for k, v in attrs.items():
if k in {'id', 'name', 'notes', 'compartments', 'annotation'}:
setattr(self, k, v)
def model_loader(gem_file_path, gem_file_type):
"""Consolidated function to load a GEM using COBRApy. Specify the file type being loaded.
Args:
gem_file_path (str): Path to model file
gem_file_type (str): GEM model type - ``sbml`` (or ``xml``), ``mat``, or ``json`` format
Returns:
COBRApy Model object.
"""
if gem_file_type.lower() == 'xml' or gem_file_type.lower() == 'sbml':
model = read_sbml_model(gem_file_path)
elif gem_file_type.lower() == 'mat':
model = load_matlab_model(gem_file_path)
elif gem_file_type.lower() == 'json':
model = load_json_model(gem_file_path)
else:
raise ValueError('File type must be "sbml", "xml", "mat", or "json".')
return model
def is_spontaneous(gene, custom_id=None):
"""Input a COBRApy Gene object and check if the ID matches a spontaneous ID regex.
Args:
gene (Gene): COBRApy Gene
custom_id (str): Optional custom spontaneous ID if it does not match the regular expression ``[Ss](_|)0001``
Returns:
bool: If gene ID matches spontaneous ID
"""
spont = re.compile("[Ss](_|)0001")
if spont.match(gene.id):
return True
elif gene.id == custom_id:
return True
else:
return False
def filter_out_spontaneous_genes(genes, custom_spont_id=None):
"""Return the DictList of genes that are not spontaneous in a model.
Args:
genes (DictList): Genes DictList
custom_spont_id (str): Optional custom spontaneous ID if it does not match the regular expression ``[Ss](_|)0001``
Returns:
DictList: genes excluding ones that are spontaneous
"""
new_genes = DictList()
for gene in genes:
if not is_spontaneous(gene, custom_id=custom_spont_id):
new_genes.append(gene)
return new_genes
def true_num_genes(model, custom_spont_id=None):
"""Return the number of genes in a model ignoring spontaneously labeled genes.
Args:
model (Model):
custom_spont_id (str): Optional custom spontaneous ID if it does not match the regular expression ``[Ss](_|)0001``
Returns:
int: Number of genes excluding spontaneous genes
"""
true_num = 0
for gene in model.genes:
if not is_spontaneous(gene, custom_id=custom_spont_id):
true_num += 1
return true_num
def true_num_reactions(model, custom_spont_id=None):
"""Return the number of reactions associated with a gene.
Args:
model (Model):
custom_spont_id (str): Optional custom spontaneous ID if it does not match the regular expression ``[Ss](_|)0001``
Returns:
int: Number of reactions associated with a gene
"""
true_num = 0
for rxn in model.reactions:
if len(rxn.genes) == 0:
continue
if len(rxn.genes) == 1 and is_spontaneous(list(rxn.genes)[0], custom_id=custom_spont_id):
continue
else:
true_num += 1
return true_num
def adj_num_reactions(model, missing_genes, custom_spont_id=None):
adj_num = 0
for rxn in model.reactions:
if len(rxn.genes) == 0:
continue
if len(rxn.genes) == 1 and (is_spontaneous(list(rxn.genes)[0], custom_id=custom_spont_id) or list(rxn.genes)[0] in missing_genes):
continue
else:
adj_num += 1
return adj_num