@@ -128,8 +128,93 @@ def update_annotations_from_others(model: libModel) -> libModel:
128
128
add_cv_term_metabolites (entry , db_id , other_metab )
129
129
return model
130
130
131
- # @TODO
132
- # maybe add the function from SPECIMEN for BioCyc/MetaCyc annotation completion
131
+
132
+ def complete_BioMetaCyc (model :cobra .Model ) -> cobra .Model :
133
+ """Check for existing MetaCyc and BioCyc annotations for metabolites and
134
+ reactions and generate them from the other if one of the two is missing.
135
+
136
+ Args:
137
+ model (cobra.Model): A genome-scale model to be checked
138
+ for complete BioCyc/MetaCyc annotations.
139
+
140
+ Returns:
141
+ cobra.Model: The updated model.
142
+ """
143
+
144
+
145
+ # reactions
146
+ # ---------
147
+ for reac in model .reactions :
148
+ # case 1: MetaCyc but not BioCyc
149
+ if 'metacyc.reaction' in reac .annotation and not 'biocyc' in reac .annotation :
150
+ # add database (META) information to get BioCyc ID
151
+ if isinstance (reac .annotation ['metacyc.reaction' ], list ):
152
+ reac .annotation ['biocyc' ] = ['META:' + _ for _ in reac .annotation ['metacyc.reaction' ]]
153
+ else :
154
+ reac .annotation ['biocyc' ] = 'META:' + reac .annotation ['metacyc.reaction' ]
155
+ # case 2: BioCyc, but no MetaCyc
156
+ elif 'biocyc' in reac .annotation and not 'metacyc.reaction' in reac .annotation :
157
+ # if there are multiple metacyc.reaction annotation
158
+ if isinstance (reac .annotation ['biocyc' ], list ):
159
+ add_anno = []
160
+ for biocyc_anno in reac .annotation ['biocyc' ]:
161
+ if ':' in biocyc_anno :
162
+ # exclude organism identifier from ID to get MetaCyc ID
163
+ add_anno .append (biocyc_anno .split (':' )[1 ])
164
+ else :
165
+ # high possibility that information is faulty - do not use it
166
+ print (F'\n \n Warning: Unexpected BioCyc annotation { biocyc_anno } for reaction { reac .id } ' )
167
+ reac .annotation ['metacyc.reaction' ] = add_anno
168
+ # if there is only one
169
+ else :
170
+ if ':' in reac .annotation ['biocyc' ]:
171
+ # exclude organism identifier from ID to get MetaCyc ID
172
+ reac .annotation ['metacyc.reaction' ] = reac .annotation ['biocyc' ].split (':' )[1 ]
173
+ else :
174
+ # high possibility that information is faulty - do not use it
175
+ print (F'\n \n Warning: Unexpected BioCyc annotation { reac .annotation ["biocyc" ]} for reaction { reac .id } ' )
176
+ # case 3: both or no = skip
177
+ else :
178
+ continue
179
+
180
+ # metabolites
181
+ # -----------
182
+ for meta in model .metabolites :
183
+ # case 1: MetaCyc but not BioCyc
184
+ if 'metacyc.compound' in meta .annotation and not 'biocyc' in meta .annotation :
185
+ # add database (META) information to get BioCyc ID
186
+ if isinstance (meta .annotation ['metacyc.compound' ],list ):
187
+ meta .annotation ['biocyc' ] = ['META:' + _ for _ in meta .annotation ['metacyc.compound' ]]
188
+ else :
189
+ meta .annotation ['biocyc' ] = 'META:' + meta .annotation ['metacyc.compound' ]
190
+ # case 2: BioCyc, but no MetaCyc
191
+ elif 'biocyc' in meta .annotation and not 'metacyc.compound' in meta .annotation :
192
+ # if there are multiple metacyc.compound annotations
193
+ if isinstance (meta .annotation ['biocyc' ], list ):
194
+ add_anno = []
195
+ for biocyc_anno in meta .annotation ['biocyc' ]:
196
+ if ':' in biocyc_anno :
197
+ # exclude organism identifier from ID to get MetaCyc ID
198
+ add_anno .append (biocyc_anno .split (':' )[1 ])
199
+ else :
200
+ # high possibility that information is faulty - do not use it
201
+ print (F'\n \n Warning: Unexpected BioCyc annotation { biocyc_anno } for metabolite { meta .id } ' )
202
+ meta .annotation ['metacyc.compound' ] = add_anno
203
+ # if there is only one
204
+ else :
205
+ if ':' in meta .annotation ['biocyc' ]:
206
+ # exclude organism identifier from ID to get MetaCyc ID
207
+ meta .annotation ['metacyc.compound' ] = meta .annotation ['biocyc' ].split (':' )[1 ]
208
+ else :
209
+ # high possibility that information is faulty - do not use it
210
+ print (F'\n \n Warning: Unexpected BioCyc annotation { meta .annotation ["biocyc" ]} for metabolite { meta .id } ' )
211
+ # case 3: both or no = skip
212
+ else :
213
+ continue
214
+
215
+ return model
216
+
217
+
133
218
134
219
# duplicates
135
220
# ----------
@@ -439,3 +524,4 @@ def resolve_duplicates(model:cobra.Model, check_reac:bool=True,
439
524
440
525
return model
441
526
527
+
0 commit comments