def get_libsbml_document(cobra_model, sbml_level=2, sbml_version=1, print_time=False, use_fbc_package=True): """ Return a libsbml document object for writing to a file. This function is used by write_cobra_model_to_sbml_file(). """ note_start_tag, note_end_tag = '<p>', '</p>' if sbml_level > 2 or (sbml_level == 2 and sbml_version == 4): note_start_tag, note_end_tag = '<html:p>', '</html:p>' sbml_doc = SBMLDocument(sbml_level, sbml_version) sbml_model = sbml_doc.createModel(cobra_model.id.split('.')[0]) #Note need to set units reaction_units = 'mmol_per_gDW_per_hr' model_units = sbml_model.createUnitDefinition() model_units.setId(reaction_units) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_MOLE) sbml_unit.setScale(-3) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_GRAM) sbml_unit.setExponent(-1) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_SECOND) sbml_unit.setMultiplier(1.0 / 60 / 60) sbml_unit.setExponent(-1) #Add in the common compartment abbreviations. If there are additional compartments #they also need to be added. if not cobra_model.compartments: cobra_model.compartments = { 'c': 'cytosol', 'p': 'periplasm', 'e': 'extracellular' } for the_key in cobra_model.compartments.keys(): sbml_comp = sbml_model.createCompartment() sbml_comp.setId(the_key) sbml_comp.setName(cobra_model.compartments[the_key]) sbml_comp.setSize(1) #Just to get rid of warnings if print_time: warn("print_time is deprecated") #Use this dict to allow for fast look up of species id #for references created in the reaction section. metabolite_dict = {} for cobra_metabolite in cobra_model.metabolites: metabolite_dict[cobra_metabolite.id] = add_sbml_species( sbml_model, cobra_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag) for the_reaction in cobra_model.reactions: #This is probably the culprit. Including cobra.Reaction #objects explicitly in cobra.Model will speed this up. sbml_reaction = sbml_model.createReaction() #Need to remove - for proper SBML. Replace with __ the_reaction_id = 'R_' + the_reaction.id.replace('-', '__') sbml_reaction.setId(the_reaction_id) # The reason we are not using the Reaction.reversibility property # is because the SBML definition of reversibility does not quite # match with the cobra definition. In cobra, reversibility implies # that both positive and negative flux values are feasible. However, # SBML requires negative-flux-only reactions to still be classified # as reversible. To quote from the SBML Level 3 Version 1 Spec: # > However, labeling a reaction as irreversible is interpreted as # > an assertion that the rate expression will not have negative # > values during a simulation. # (Page 60 lines 44-45) sbml_reaction.setReversible(the_reaction.lower_bound < 0) if the_reaction.name: sbml_reaction.setName(the_reaction.name) else: sbml_reaction.setName(the_reaction.id) #Add in the reactant/product references for the_metabolite, the_coefficient in the_reaction._metabolites.items( ): sbml_stoichiometry = the_coefficient metabolite_id = str(metabolite_dict[the_metabolite.id]) #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Deal with the case where the reaction is a boundary reaction if len(the_reaction._metabolites) == 1: the_metabolite, the_coefficient = list( the_reaction._metabolites.items())[0] metabolite_id = add_sbml_species(sbml_model, the_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag, boundary_metabolite=True) sbml_stoichiometry = -the_coefficient #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Add in the kineticLaw sbml_law = KineticLaw(sbml_level, sbml_version) if hasattr(sbml_law, 'setId'): sbml_law.setId('FLUX_VALUE') sbml_law.setFormula('FLUX_VALUE') reaction_parameter_dict = { 'LOWER_BOUND': [the_reaction.lower_bound, reaction_units], 'UPPER_BOUND': [the_reaction.upper_bound, reaction_units], 'FLUX_VALUE': [0, reaction_units], 'OBJECTIVE_COEFFICIENT': [the_reaction.objective_coefficient, 'dimensionless'] } for k, v in reaction_parameter_dict.items(): sbml_parameter = Parameter(sbml_level, sbml_version) sbml_parameter.setId(k) if hasattr(v, '__iter__'): sbml_parameter.setValue(v[0]) sbml_parameter.setUnits(v[1]) else: sbml_parameter.setValue(v) sbml_law.addParameter(sbml_parameter) sbml_reaction.setKineticLaw(sbml_law) #Checks if GPR and Subsystem annotations are present in the notes section and if they are the same as those in #the reaction's gene_reaction_rule/ subsystem attribute #If they are not identical, they are set to be identical note_dict = the_reaction.notes.copy() if the_reaction.gene_reaction_rule: if 'GENE ASSOCIATION' in note_dict: del note_dict['GENE ASSOCIATION'] note_dict['GENE_ASSOCIATION'] = [ str(the_reaction.gene_reaction_rule) ] if the_reaction.subsystem: note_dict['SUBSYSTEM'] = [str(the_reaction.subsystem)] #In a cobrapy model the notes section is stored as a dictionary. The following section turns the key-value-pairs #of the dictionary into a string and replaces recurring symbols so that the string has the required syntax for #an SBML doc. note_str = str(list(iteritems(note_dict))) note_start_tag, note_end_tag, note_delimiter = '<p>', '</p>', ':' note_str = note_str.replace('(\'', note_start_tag) note_str = note_str.replace('\']),', note_end_tag) note_str = note_str.replace('\',', note_delimiter) note_str = note_str.replace('\']', '') note_str = note_str.replace('[\'', '') note_str = note_str.replace( '[', '<html xmlns="http://www.w3.org/1999/xhtml">') note_str = note_str.replace(')]', note_end_tag + '</html>') sbml_reaction.setNotes(note_str) if use_fbc_package: try: from libsbml import ConversionProperties, LIBSBML_OPERATION_SUCCESS conversion_properties = ConversionProperties() conversion_properties.addOption("convert cobra", True, "Convert Cobra model") result = sbml_doc.convert(conversion_properties) if result != LIBSBML_OPERATION_SUCCESS: raise Exception("Conversion of COBRA to SBML+fbc failed") except Exception as e: error_string = 'Error saving as SBML+fbc. %s' try: #Check whether the FbcExtension is there from libsbml import FbcExtension error_string = error_string % e except ImportError: error_string = error_string%'FbcExtension not available in libsbml. ' +\ 'If use_fbc_package == True then libsbml must be compiled with ' +\ 'the fbc extension. ' from libsbml import getLibSBMLDottedVersion _sbml_version = getLibSBMLDottedVersion() _major, _minor, _patch = map(int, _sbml_version.split('.')) if _major < 5 or (_major == 5 and _minor < 8): error_string += "You've got libsbml %s installed. You need 5.8.0 or later with the fbc package" raise (Exception(error_string)) return sbml_doc
def write_cobra_model_to_sbml_file(cobra_model, sbml_filename, sbml_level=2, sbml_version=1, print_time=False, use_fbc_package=True): """Write a cobra.Model object to an SBML XML file. cobra_model: :class:`~cobra.core.Model.Model` object sbml_filename: The file to write the SBML XML to. sbml_level: 2 is the only level supported at the moment. sbml_version: 1 is the only version supported at the moment. use_fbc_package: Boolean. Convert the model to the FBC package format to improve portability. http://sbml.org/Documents/Specifications/SBML_Level_3/Packages/Flux_Balance_Constraints_(flux) TODO: Update the NOTES to match the SBML standard and provide support for Level 2 Version 4 """ note_start_tag, note_end_tag = '<p>', '</p>' if sbml_level > 2 or (sbml_level == 2 and sbml_version == 4): note_start_tag, note_end_tag = '<html:p>', '</html:p>' sbml_doc = SBMLDocument(sbml_level, sbml_version) sbml_model = sbml_doc.createModel(cobra_model.id.split('.')[0]) #Note need to set units reaction_units = 'mmol_per_gDW_per_hr' model_units = sbml_model.createUnitDefinition() model_units.setId(reaction_units) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_MOLE) sbml_unit.setScale(-3) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_GRAM) sbml_unit.setExponent(-1) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_SECOND) sbml_unit.setMultiplier(1.0 / 60 / 60) sbml_unit.setExponent(-1) #Add in the common compartment abbreviations. If there are additional compartments #they also need to be added. if not cobra_model.compartments: cobra_model.compartments = { 'c': 'cytosol', 'p': 'periplasm', 'e': 'extracellular' } for the_key in cobra_model.compartments.keys(): sbml_comp = sbml_model.createCompartment() sbml_comp.setId(the_key) sbml_comp.setName(cobra_model.compartments[the_key]) sbml_comp.setSize(1) #Just to get rid of warnings if print_time: warn("print_time is deprecated") #Use this dict to allow for fast look up of species id #for references created in the reaction section. metabolite_dict = {} for cobra_metabolite in cobra_model.metabolites: metabolite_dict[cobra_metabolite.id] = add_sbml_species( sbml_model, cobra_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag) for the_reaction in cobra_model.reactions: #This is probably the culprit. Including cobra.Reaction #objects explicitly in cobra.Model will speed this up. sbml_reaction = sbml_model.createReaction() #Need to remove - for proper SBML. Replace with __ the_reaction_id = 'R_' + the_reaction.id.replace('-', '__') sbml_reaction.setId(the_reaction_id) # The reason we are not using the Reaction.reversibility property # is because the SBML definition of reversibility does not quite # match with the cobra definition. In cobra, reversibility implies # that both positive and negative flux values are feasible. However, # SBML requires negative-flux-only reactions to still be classified # as reversible. To quote from the SBML Level 3 Version 1 Spec: # > However, labeling a reaction as irreversible is interpreted as # > an assertion that the rate expression will not have negative # > values during a simulation. # (Page 60 lines 44-45) sbml_reaction.setReversible(the_reaction.lower_bound < 0) if the_reaction.name: sbml_reaction.setName(the_reaction.name) else: sbml_reaction.setName(the_reaction.id) #Add in the reactant/product references for the_metabolite, the_coefficient in the_reaction._metabolites.items( ): sbml_stoichiometry = the_coefficient metabolite_id = str(metabolite_dict[the_metabolite.id]) #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Deal with the case where the reaction is a boundary reaction if len(the_reaction._metabolites) == 1: the_metabolite, the_coefficient = list( the_reaction._metabolites.items())[0] metabolite_id = add_sbml_species(sbml_model, the_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag, boundary_metabolite=True) sbml_stoichiometry = -the_coefficient #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Add in the kineticLaw sbml_law = KineticLaw(sbml_level, sbml_version) if hasattr(sbml_law, 'setId'): sbml_law.setId('FLUX_VALUE') sbml_law.setFormula('FLUX_VALUE') reaction_parameter_dict = { 'LOWER_BOUND': [the_reaction.lower_bound, reaction_units], 'UPPER_BOUND': [the_reaction.upper_bound, reaction_units], 'FLUX_VALUE': [0, reaction_units], 'OBJECTIVE_COEFFICIENT': [the_reaction.objective_coefficient, 'dimensionless'] } for k, v in reaction_parameter_dict.items(): sbml_parameter = Parameter(sbml_level, sbml_version) sbml_parameter.setId(k) if hasattr(v, '__iter__'): sbml_parameter.setValue(v[0]) sbml_parameter.setUnits(v[1]) else: sbml_parameter.setValue(v) sbml_law.addParameter(sbml_parameter) sbml_reaction.setKineticLaw(sbml_law) sbml_reaction.setNotes( '<html xmlns="http://www.w3.org/1999/xhtml">%sGENE_ASSOCIATION: %s%s%sSUBSYSTEM: %s%s</html>' % (note_start_tag, the_reaction.gene_reaction_rule, note_end_tag, note_start_tag, the_reaction.subsystem, note_end_tag)) if use_fbc_package: try: from libsbml import ConversionProperties, LIBSBML_OPERATION_SUCCESS conversion_properties = ConversionProperties() conversion_properties.addOption("convert cobra", True, "Convert Cobra model") result = sbml_doc.convert(conversion_properties) if result != LIBSBML_OPERATION_SUCCESS: raise Exception("Conversion of COBRA to SBML+fbc failed") except Exception as e: error_string = 'Error saving as SBML+fbc. %s' try: #Check whether the FbcExtension is there from libsbml import FbcExtension error_string = error_string % e except ImportError: error_string = error_string%'FbcExtension not available in libsbml. ' +\ 'If use_fbc_package == True then libsbml must be compiled with ' +\ 'the fbc extension. ' from libsbml import getLibSBMLDottedVersion _sbml_version = getLibSBMLDottedVersion() _major, _minor, _patch = map(int, _sbml_version.split('.')) if _major < 5 or (_major == 5 and _minor < 8): error_string += "You've got libsbml %s installed. You need 5.8.0 or later with the fbc package" raise (Exception(error_string)) writeSBML(sbml_doc, sbml_filename)
def get_libsbml_document(cobra_model, sbml_level=2, sbml_version=1, print_time=False, use_fbc_package=True): """ Return a libsbml document object for writing to a file. This function is used by write_cobra_model_to_sbml_file(). """ note_start_tag, note_end_tag = '<p>', '</p>' if sbml_level > 2 or (sbml_level == 2 and sbml_version == 4): note_start_tag, note_end_tag = '<html:p>', '</html:p>' sbml_doc = SBMLDocument(sbml_level, sbml_version) sbml_model = sbml_doc.createModel(cobra_model.id.split('.')[0]) #Note need to set units reaction_units = 'mmol_per_gDW_per_hr' model_units = sbml_model.createUnitDefinition() model_units.setId(reaction_units) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_MOLE) sbml_unit.setScale(-3) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_GRAM) sbml_unit.setExponent(-1) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_SECOND) sbml_unit.setMultiplier(1.0/60/60) sbml_unit.setExponent(-1) #Add in the common compartment abbreviations. If there are additional compartments #they also need to be added. if not cobra_model.compartments: cobra_model.compartments = {'c': 'cytosol', 'p': 'periplasm', 'e': 'extracellular'} for the_key in cobra_model.compartments.keys(): sbml_comp = sbml_model.createCompartment() sbml_comp.setId(the_key) sbml_comp.setName(cobra_model.compartments[the_key]) sbml_comp.setSize(1) #Just to get rid of warnings if print_time: warn("print_time is deprecated") #Use this dict to allow for fast look up of species id #for references created in the reaction section. metabolite_dict = {} for cobra_metabolite in cobra_model.metabolites: metabolite_dict[cobra_metabolite.id] = add_sbml_species(sbml_model, cobra_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag) for the_reaction in cobra_model.reactions: #This is probably the culprit. Including cobra.Reaction #objects explicitly in cobra.Model will speed this up. sbml_reaction = sbml_model.createReaction() #Need to remove - for proper SBML. Replace with __ the_reaction_id = 'R_' + the_reaction.id.replace('-','__' ) sbml_reaction.setId(the_reaction_id) # The reason we are not using the Reaction.reversibility property # is because the SBML definition of reversibility does not quite # match with the cobra definition. In cobra, reversibility implies # that both positive and negative flux values are feasible. However, # SBML requires negative-flux-only reactions to still be classified # as reversible. To quote from the SBML Level 3 Version 1 Spec: # > However, labeling a reaction as irreversible is interpreted as # > an assertion that the rate expression will not have negative # > values during a simulation. # (Page 60 lines 44-45) sbml_reaction.setReversible(the_reaction.lower_bound < 0) if the_reaction.name: sbml_reaction.setName(the_reaction.name) else: sbml_reaction.setName(the_reaction.id) #Add in the reactant/product references for the_metabolite, the_coefficient in the_reaction._metabolites.items(): sbml_stoichiometry = the_coefficient metabolite_id = str(metabolite_dict[the_metabolite.id]) #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Deal with the case where the reaction is a boundary reaction if len(the_reaction._metabolites) == 1: the_metabolite, the_coefficient = list(the_reaction._metabolites.items())[0] metabolite_id = add_sbml_species(sbml_model, the_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag, boundary_metabolite=True) sbml_stoichiometry = -the_coefficient #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Add in the kineticLaw sbml_law = KineticLaw(sbml_level, sbml_version) if hasattr(sbml_law, 'setId'): sbml_law.setId('FLUX_VALUE') sbml_law.setFormula('FLUX_VALUE') reaction_parameter_dict = {'LOWER_BOUND': [the_reaction.lower_bound, reaction_units], 'UPPER_BOUND': [the_reaction.upper_bound, reaction_units], 'FLUX_VALUE': [0, reaction_units], 'OBJECTIVE_COEFFICIENT': [the_reaction.objective_coefficient, 'dimensionless']} for k, v in reaction_parameter_dict.items(): sbml_parameter = Parameter(sbml_level, sbml_version) sbml_parameter.setId(k) if hasattr(v, '__iter__'): sbml_parameter.setValue(v[0]) sbml_parameter.setUnits(v[1]) else: sbml_parameter.setValue(v) sbml_law.addParameter(sbml_parameter) sbml_reaction.setKineticLaw(sbml_law) #Checks if GPR and Subsystem annotations are present in the notes section and if they are the same as those in #the reaction's gene_reaction_rule/ subsystem attribute #If they are not identical, they are set to be identical note_dict = the_reaction.notes.copy() if the_reaction.gene_reaction_rule: note_dict['GENE_ASSOCIATION'] = [str(the_reaction.gene_reaction_rule)] if the_reaction.subsystem: note_dict['SUBSYSTEM'] = [str(the_reaction.subsystem)] #In a cobrapy model the notes section is stored as a dictionary. The following section turns the key-value-pairs #of the dictionary into a string and replaces recurring symbols so that the string has the required syntax for #an SBML doc. note_str = str(list(iteritems(note_dict))) note_start_tag, note_end_tag, note_delimiter = '<p>', '</p>', ':' note_str = note_str.replace('(\'',note_start_tag) note_str = note_str.replace('\']),',note_end_tag) note_str = note_str.replace('\',',note_delimiter) note_str = note_str.replace('\']','') note_str = note_str.replace('[\'','') note_str = note_str.replace('[','<html xmlns="http://www.w3.org/1999/xhtml">') note_str = note_str.replace(')]',note_end_tag+'</html>') sbml_reaction.setNotes(note_str) if use_fbc_package: try: from libsbml import ConversionProperties, LIBSBML_OPERATION_SUCCESS conversion_properties = ConversionProperties() conversion_properties.addOption("convert cobra", True, "Convert Cobra model") result = sbml_doc.convert(conversion_properties) if result != LIBSBML_OPERATION_SUCCESS: raise Exception("Conversion of COBRA to SBML+fbc failed") except Exception as e: error_string = 'Error saving as SBML+fbc. %s' try: #Check whether the FbcExtension is there from libsbml import FbcExtension error_string = error_string%e except ImportError: error_string = error_string%'FbcExtension not available in libsbml. ' +\ 'If use_fbc_package == True then libsbml must be compiled with ' +\ 'the fbc extension. ' from libsbml import getLibSBMLDottedVersion _sbml_version = getLibSBMLDottedVersion() _major, _minor, _patch = map(int, _sbml_version.split('.')) if _major < 5 or (_major == 5 and _minor < 8): error_string += "You've got libsbml %s installed. You need 5.8.0 or later with the fbc package" raise(Exception(error_string)) return sbml_doc
def write_cobra_model_to_sbml_file(cobra_model, sbml_filename, sbml_level=2, sbml_version=1, print_time=False, use_fbc_package=True): """Write a cobra.Model object to an SBML XML file. cobra_model: :class:`~cobra.core.Model.Model` object sbml_filename: The file to write the SBML XML to. sbml_level: 2 is the only level supported at the moment. sbml_version: 1 is the only version supported at the moment. use_fbc_package: Boolean. Convert the model to the FBC package format to improve portability. http://sbml.org/Documents/Specifications/SBML_Level_3/Packages/Flux_Balance_Constraints_(flux) TODO: Update the NOTES to match the SBML standard and provide support for Level 2 Version 4 """ note_start_tag, note_end_tag = '<p>', '</p>' if sbml_level > 2 or (sbml_level == 2 and sbml_version == 4): note_start_tag, note_end_tag = '<html:p>', '</html:p>' sbml_doc = SBMLDocument(sbml_level, sbml_version) sbml_model = sbml_doc.createModel(cobra_model.description.split('.')[0]) #Note need to set units reaction_units = 'mmol_per_gDW_per_hr' model_units = sbml_model.createUnitDefinition() model_units.setId(reaction_units) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_MOLE) sbml_unit.setScale(-3) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_GRAM) sbml_unit.setExponent(-1) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_SECOND) sbml_unit.setMultiplier(1.0/60/60) sbml_unit.setExponent(-1) #Add in the common compartment abbreviations. If there are additional compartments #they also need to be added. if not cobra_model.compartments: cobra_model.compartments = {'c': 'cytosol', 'p': 'periplasm', 'e': 'extracellular'} for the_key in cobra_model.compartments.keys(): sbml_comp = sbml_model.createCompartment() sbml_comp.setId(the_key) sbml_comp.setName(cobra_model.compartments[the_key]) sbml_comp.setSize(1) #Just to get rid of warnings if print_time: warn("print_time is deprecated") #Use this dict to allow for fast look up of species id #for references created in the reaction section. metabolite_dict = {} for cobra_metabolite in cobra_model.metabolites: metabolite_dict[cobra_metabolite.id] = add_sbml_species(sbml_model, cobra_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag) for the_reaction in cobra_model.reactions: #This is probably the culprit. Including cobra.Reaction #objects explicitly in cobra.Model will speed this up. sbml_reaction = sbml_model.createReaction() #Need to remove - for proper SBML. Replace with __ the_reaction_id = 'R_' + the_reaction.id.replace('-','__' ) sbml_reaction.setId(the_reaction_id) sbml_reaction.setReversible(the_reaction.reversibility) if the_reaction.name: sbml_reaction.setName(the_reaction.name) else: sbml_reaction.setName(the_reaction.id) #Add in the reactant/product references for the_metabolite, the_coefficient in the_reaction._metabolites.items(): sbml_stoichiometry = the_coefficient metabolite_id = str(metabolite_dict[the_metabolite.id]) #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Deal with the case where the reaction is a boundary reaction if len(the_reaction._metabolites) == 1: the_metabolite, the_coefficient = list(the_reaction._metabolites.items())[0] the_metabolite = the_metabolite.copy() metabolite_id = add_sbml_species(sbml_model, the_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag, boundary_metabolite=True) sbml_stoichiometry = -the_coefficient #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Add in the kineticLaw sbml_law = KineticLaw(sbml_level, sbml_version) if hasattr(sbml_law, 'setId'): sbml_law.setId('FLUX_VALUE') sbml_law.setFormula('FLUX_VALUE') reaction_parameter_dict = {'LOWER_BOUND': [the_reaction.lower_bound, reaction_units], 'UPPER_BOUND': [the_reaction.upper_bound, reaction_units], 'FLUX_VALUE': [0, reaction_units], 'OBJECTIVE_COEFFICIENT': [the_reaction.objective_coefficient, 'dimensionless']} for k, v in reaction_parameter_dict.items(): sbml_parameter = Parameter(sbml_level, sbml_version) sbml_parameter.setId(k) if hasattr(v, '__iter__'): sbml_parameter.setValue(v[0]) sbml_parameter.setUnits(v[1]) else: sbml_parameter.setValue(v) sbml_law.addParameter(sbml_parameter) sbml_reaction.setKineticLaw(sbml_law) sbml_reaction.setNotes('<html xmlns="http://www.w3.org/1999/xhtml">%sGENE_ASSOCIATION: %s%s%sSUBSYSTEM: %s%s</html>'%(note_start_tag, the_reaction.gene_reaction_rule, note_end_tag, note_start_tag, the_reaction.subsystem, note_end_tag)) if use_fbc_package: try: from libsbml import ConversionProperties, LIBSBML_OPERATION_SUCCESS conversion_properties = ConversionProperties() conversion_properties.addOption("convert cobra", True, "Convert Cobra model") result = sbml_doc.convert(conversion_properties) if result != LIBSBML_OPERATION_SUCCESS: raise Exception("Conversion of COBRA to SBML+fbc failed") except Exception as e: error_string = 'Error saving as SBML+fbc. %s' try: #Check whether the FbcExtension is there from libsbml import FbcExtension error_string = error_string%e except ImportError: error_string = error_string%'FbcExtension not available in libsbml. ' +\ 'If use_fbc_package == True then libsbml must be compiled with ' +\ 'the fbc extension. ' from libsbml import getLibSBMLDottedVersion _sbml_version = getLibSBMLDottedVersion() _major, _minor, _patch = map(int, _sbml_version.split('.')) if _major < 5 or (_major == 5 and _minor < 8): error_string += "You've got libsbml %s installed. You need 5.8.0 or later with the fbc package" raise(Exception(error_string)) writeSBML(sbml_doc, sbml_filename)
def write_cobra_model_to_sbml_file(cobra_model, sbml_filename, sbml_level=2, sbml_version=1, print_time=False): """Write a cobra.Model object to an SBML XML file. cobra_model: A cobra.Model object sbml_filename: The file to write the SBML XML to. sbml_level: 2 is the only level supported at the moment. sbml_version: 1 is the only version supported at the moment. print_time: Boolean. Print the time requirements for different sections TODO: Update the NOTES to match the SBML standard and provide support for Level 2 Version 4 """ note_start_tag, note_end_tag = '<p>', '</p>' if sbml_level > 2 or (sbml_level == 2 and sbml_version == 4): note_start_tag, note_end_tag = '<html:p>', '</html:p>' sbml_doc = SBMLDocument(sbml_level, sbml_version) sbml_model = sbml_doc.createModel(cobra_model.description.split('.')[0]) #Note need to set units reaction_units = 'mmol_per_gDW_per_hr' model_units = sbml_model.createUnitDefinition() model_units.setId(reaction_units) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_MOLE) sbml_unit.setScale(-3) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_GRAM) sbml_unit.setExponent(-1) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_SECOND) sbml_unit.setMultiplier(1.0 / 60 / 60) sbml_unit.setExponent(-1) #Add in the common compartment abbreviations. If there are additional compartments #they also need to be added. if not cobra_model.compartments: cobra_model.compartments = { 'c': 'cytosol', 'p': 'periplasm', 'e': 'extracellular' } for the_key in cobra_model.compartments.keys(): sbml_comp = sbml_model.createCompartment() sbml_comp.setId(the_key) sbml_comp.setName(cobra_model.compartments[the_key]) sbml_comp.setSize(1) #Just to get rid of warnings if print_time: start_time = time() #Use this dict to allow for fast look up of species id #for references created in the reaction section. metabolite_dict = {} for cobra_metabolite in cobra_model.metabolites: metabolite_dict[cobra_metabolite.id] = add_sbml_species( sbml_model, cobra_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag) if print_time: print 'Adding %s took %1.2f seconds' % ('metabolites', time() - start_time) if print_time: start_time = time() for the_reaction in cobra_model.reactions: #This is probably the culprit. Including cobra.Reaction #objects explicitly in cobra.Model will speed this up. sbml_reaction = sbml_model.createReaction() #Need to remove - for proper SBML. Replace with __ the_reaction_id = 'R_' + the_reaction.id.replace('-', '__') sbml_reaction.setId(the_reaction_id) sbml_reaction.setReversible(the_reaction.reversibility) if the_reaction.name: sbml_reaction.setName(the_reaction.name) else: sbml_reaction.setName(the_reaction.id) #Add in the reactant/product references for the_metabolite, the_coefficient in the_reaction._metabolites.items( ): sbml_stoichiometry = the_coefficient metabolite_id = str(metabolite_dict[the_metabolite.id]) #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Deal with the case where the reaction is a boundary reaction if len(the_reaction._metabolites) == 1: the_metabolite, the_coefficient = the_reaction._metabolites.items( )[0] the_metabolite = the_metabolite.copy() metabolite_id = add_sbml_species(sbml_model, the_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag, boundary_metabolite=True) sbml_stoichiometry = -the_coefficient #Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + '_' + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) #Add in the kineticLaw sbml_law = KineticLaw(sbml_level, sbml_version) if hasattr(sbml_law, 'setId'): sbml_law.setId('FLUX_VALUE') sbml_law.setFormula('FLUX_VALUE') reaction_parameter_dict = { 'LOWER_BOUND': [the_reaction.lower_bound, reaction_units], 'UPPER_BOUND': [the_reaction.upper_bound, reaction_units], 'FLUX_VALUE': [0, reaction_units], 'OBJECTIVE_COEFFICIENT': [the_reaction.objective_coefficient, 'dimensionless'] } for k, v in reaction_parameter_dict.items(): sbml_parameter = Parameter(sbml_level, sbml_version) sbml_parameter.setId(k) if hasattr(v, '__iter__'): sbml_parameter.setValue(v[0]) sbml_parameter.setUnits(v[1]) else: sbml_parameter.setValue(v) sbml_law.addParameter(sbml_parameter) sbml_reaction.setKineticLaw(sbml_law) sbml_reaction.setNotes( '<html xmlns="http://www.w3.org/1999/xhtml">%sGENE_ASSOCIATION: %s%s%sSUBSYSTEM: %s%s</html>' % (note_start_tag, the_reaction.gene_reaction_rule, note_end_tag, note_start_tag, the_reaction.subsystem, note_end_tag)) if print_time: print 'Adding %s took %1.2f seconds' % ('reactions', time() - start_time) writeSBML(sbml_doc, sbml_filename)
def write_cobra_model_to_sbml_file(cobra_model, sbml_filename, sbml_level=2, sbml_version=1, print_time=False): """Write a cobra.Model object to an SBML XML file. cobra_model: A cobra.Model object sbml_filename: The file to write the SBML XML to. sbml_level: 2 is the only level supported at the moment. sbml_version: 1 is the only version supported at the moment. print_time: Boolean. Print the time requirements for different sections TODO: Update the NOTES to match the SBML standard and provide support for Level 2 Version 4 """ # Add in the common compartment abbreviations. If there are additional compartments # they also need to be added. note_start_tag, note_end_tag = "<p>", "</p>" if sbml_level > 2 or (sbml_level == 2 and sbml_version == 4): note_start_tag, note_end_tag = "<html:p>", "</html:p>" if not hasattr(cobra_model, "compartments"): cobra_model.compartments = {"c": "cytosol", "p": "periplasm", "e": "extracellular"} sbml_doc = SBMLDocument(sbml_level, sbml_version) sbml_model = sbml_doc.createModel(cobra_model.description.split(".")[0]) # Note need to set units reaction_units = "mmol_per_gDW_per_hr" model_units = sbml_model.createUnitDefinition() model_units.setId(reaction_units) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_MOLE) sbml_unit.setScale(-3) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_GRAM) sbml_unit.setExponent(-1) sbml_unit = model_units.createUnit() sbml_unit.setKind(UNIT_KIND_SECOND) sbml_unit.setMultiplier(1.0 / 60 / 60) sbml_unit.setExponent(-1) for the_key in cobra_model.compartments.keys(): sbml_comp = sbml_model.createCompartment() sbml_comp.setId(the_key) sbml_comp.setName(cobra_model.compartments[the_key]) sbml_comp.setSize(1) # Just to get rid of warnings if print_time: start_time = time() # Use this dict to allow for fast look up of species id # for references created in the reaction section. metabolite_dict = {} for cobra_metabolite in cobra_model.metabolites: metabolite_dict[cobra_metabolite.id] = add_sbml_species( sbml_model, cobra_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag ) if print_time: print "Adding %s took %1.2f seconds" % ("metabolites", time() - start_time) if print_time: start_time = time() for the_reaction in cobra_model.reactions: # This is probably the culprit. Including cobra.Reaction # objects explicitly in cobra.Model will speed this up. sbml_reaction = sbml_model.createReaction() # Need to remove - for proper SBML. Replace with __ the_reaction_id = "R_" + the_reaction.id.replace("-", "__") sbml_reaction.setId(the_reaction_id) sbml_reaction.setReversible(the_reaction.reversibility) if the_reaction.name: sbml_reaction.setName(the_reaction.name) else: sbml_reaction.setName(the_reaction.id) # Add in the reactant/product references for the_metabolite, the_coefficient in the_reaction._metabolites.items(): sbml_stoichiometry = the_coefficient metabolite_id = str(metabolite_dict[the_metabolite.id]) # Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + "_" + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) # Deal with the case where the reaction is a boundary reaction if len(the_reaction._metabolites) == 1: the_metabolite, the_coefficient = the_reaction._metabolites.items()[0] the_metabolite = the_metabolite.copy() metabolite_id = add_sbml_species( sbml_model, the_metabolite, note_start_tag=note_start_tag, note_end_tag=note_end_tag, boundary_metabolite=True, ) sbml_stoichiometry = -the_coefficient # Each SpeciesReference must have a unique id if sbml_stoichiometry < 0: species_reference = sbml_reaction.createReactant() else: species_reference = sbml_reaction.createProduct() species_reference.setId(metabolite_id + "_" + the_reaction_id) species_reference.setSpecies(metabolite_id) species_reference.setStoichiometry(abs(sbml_stoichiometry)) # Add in the kineticLaw sbml_law = KineticLaw(sbml_level, sbml_version) if hasattr(sbml_law, "setId"): sbml_law.setId("FLUX_VALUE") sbml_law.setFormula("FLUX_VALUE") reaction_parameter_dict = { "LOWER_BOUND": [the_reaction.lower_bound, reaction_units], "UPPER_BOUND": [the_reaction.upper_bound, reaction_units], "FLUX_VALUE": [0, reaction_units], "OBJECTIVE_COEFFICIENT": [the_reaction.objective_coefficient, "dimensionless"], } for k, v in reaction_parameter_dict.items(): sbml_parameter = Parameter(sbml_level, sbml_version) sbml_parameter.setId(k) if hasattr(v, "__iter__"): sbml_parameter.setValue(v[0]) sbml_parameter.setUnits(v[1]) else: sbml_parameter.setValue(v) sbml_law.addParameter(sbml_parameter) sbml_reaction.setKineticLaw(sbml_law) sbml_reaction.setNotes( '<html xmlns="http://www.w3.org/1999/xhtml">%sGENE_ASSOCIATION: %s%s%sSUBSYSTEM: %s%s</html>' % ( note_start_tag, the_reaction.gene_reaction_rule, note_end_tag, note_start_tag, the_reaction.subsystem, note_end_tag, ) ) if print_time: print "Adding %s took %1.2f seconds" % ("reactions", time() - start_time) writeSBML(sbml_doc, sbml_filename)