Source code for cobrame.io.json

from __future__ import print_function, division, absolute_import

import os
import copy
import json
from collections import OrderedDict

from six import iteritems, string_types
from jsonschema import validate, ValidationError
from sympy import Basic

import cobra
from cobrame.util import me_model_interface
from cobrame.io.dict import (me_model_to_dict, me_model_from_dict,
                             get_numeric_from_string)

try:
    # If cannot import SymbolicParameter, assume using cobrapy
    # versions <= 0.5.11
    from optlang.interface import SymbolicParameter
except ImportError:
    from cobra.io.json import metabolite_from_dict, save_json_model
else:
    from cobra.io.json import save_json_model
    from cobra.io.dict import metabolite_from_dict


cur_dir = os.path.dirname(os.path.abspath(__file__))


[docs]def get_schema(): """ Load JSON schema for ME-model JSON saving/loading Returns ------- dict JSONSCHEMA """ with open(os.path.join(cur_dir, 'JSONSCHEMA'), 'r') as f: return json.load(f)
[docs]def save_json_me_model(model, file_name): """ Save a full JSON version of the ME-model. Saving/loading a model in this format can then be loaded to return a ME-model identical to the one saved, which retains all ME-model functionality. Parameters ---------- model : :class:`cobrame.core.model.MEModel` A full ME-model file_name : str or file-like object Filename of the JSON output or an open json file """ should_close = False if isinstance(file_name, string_types): file_name = open(file_name, 'w') should_close = True model_dict = me_model_to_dict(model) # Confirm that dictionary representation of model adheres to JSONSCHEMA try: validate(model_dict, get_schema()) except ValidationError: raise Exception('Must pass valid ME-model json file') json.dump(model_dict, file_name) if should_close: file_name.close()
[docs]def load_json_me_model(file_name): """ Load a full JSON version of the ME-model. Loading a model in this format will return a ME-model identical to the one saved, which retains all ME-model functionality. Parameters ---------- file_name : str or file-like object Filename of the JSON output or an open json file Returns ------- :class:`cobrame.core.model.MEModel` A full ME-model """ if isinstance(file_name, string_types): with open(file_name, 'r') as f: model_dict = json.load(f) else: model_dict = json.load(file_name) try: validate(model_dict, get_schema()) except ValidationError: raise Exception('Must pass valid ME-model json file') return me_model_from_dict(model_dict)
# ----------------------------------------------------------------------------- # Functions below here facilitate json dumping/loading of reduced ME-models # without all process_data/reaction info intact.
[docs]def save_reduced_json_me_model(me0, file_name): """ Save a stripped-down JSON version of the ME-model. This will exclude all of ME-Model information except the reaction stoichiometry information and the reaction bounds. Saving/loading a model in this format will thus occur much quicker, but limit the ability to edit the model and use most of its features. Parameters ---------- me0 : :class:`cobrame.core.model.MEModel` A full ME-model file_name : str or file-like object Filename of the JSON output """ me = copy.deepcopy(me0) for rxn in me.reactions: for met in rxn.metabolites: s = rxn._metabolites[met] if isinstance(s, Basic): rxn._metabolites[met] = str(s) if isinstance(rxn.lower_bound, Basic): rxn.lower_bound = str(rxn.lower_bound) if isinstance(rxn.upper_bound, Basic): rxn.upper_bound = str(rxn.upper_bound) for met in me.metabolites: if isinstance(met._bound, Basic): met._bound = str(met._bound) save_json_model(me, file_name)
[docs]def load_reduced_json_me_model(file_name): """ Load a stripped-down JSON version of the ME-model. This will exclude all of ME-Model information except the reaction stoichiometry information and the reaction bounds. Saving/loading a model in this format will thus occur much quicker, but limit the ability to edit the model and use most of its features. Parameters ---------- file_name : str or file-like object Filename of the JSON ME-model Returns ------- :class:`cobra.core.model.Model` COBRA Model representation of the ME-model. This will not include all of the functionality of a :class:`~cobrame.core.model.MEModel` but will solve identically compared to the full model. """ if isinstance(file_name, string_types): with open(file_name, 'r') as f: obj = json.load(f) else: obj = json.load(file_name) model = cobra.Model() # If cannot import SymbolicParameter, assume using cobrapy # versions <= 0.5.11. If versions >= 0.8.0 are used, a ME-model interface # must be assigned as the solver interface try: from optlang.interface import SymbolicParameter except ImportError: pass else: model.solver = me_model_interface default_reactions = [i.id for i in model.reactions] for k, v in iteritems(obj): if k in {'id', 'name'}: setattr(model, k, v) def _reaction_from_dict(reaction, model): new_reaction = cobra.Reaction() for k, v in iteritems(reaction): if k in {'objective_coefficient', 'reversibility', 'reaction'}: continue elif k == 'metabolites': new_reaction.add_metabolites(OrderedDict( (model.metabolites.get_by_id(str(met)), get_numeric_from_string(coeff)) for met, coeff in iteritems(v))) elif k in {'upper_bound', 'lower_bound'}: v = get_numeric_from_string(v) setattr(new_reaction, k, v) else: setattr(new_reaction, k, v) return new_reaction model.add_metabolites( [metabolite_from_dict(metabolite) for metabolite in obj['metabolites']] ) new_reactions = [ _reaction_from_dict(reaction, model) for reaction in obj['reactions']] model.remove_reactions(default_reactions) model.add_reactions(new_reactions) return model