cobra.io.sbml
=============

.. py:module:: cobra.io.sbml

.. autoapi-nested-parse::

   SBML import and export using python-libsbml.

   - The SBML importer supports all versions of SBML and the fbc package.
   - The SBML exporter writes SBML L3 models.
   - Annotation information is stored on the cobrapy objects
   - Information from the group package is read

   Parsing of fbc models was implemented as efficient as possible, whereas
   (discouraged) fallback solutions are not optimized for efficiency.

   Notes are only supported in a minimal way relevant for constraint-based
   models. I.e., structured information from notes in the form
      <p>key: value</p>
   is read into the Object.notes dictionary when reading SBML files.
   On writing the Object.notes dictionary is serialized to the SBML
   notes information.

   Annotations are read in the Object.annotation fields.

   Some SBML related issues are still open, please refer to the respective issue:
   - update annotation format and support qualifiers (depends on decision
       for new annotation format; https://github.com/opencobra/cobrapy/issues/684)
   - write compartment annotations and notes (depends on updated first-class
       compartments; see https://github.com/opencobra/cobrapy/issues/760)
   - support compression on file handles (depends on solution for
       https://github.com/opencobra/cobrapy/issues/812)



Attributes
----------

.. autoapisummary::

   cobra.io.sbml.LOGGER
   cobra.io.sbml.config
   cobra.io.sbml.LOWER_BOUND_ID
   cobra.io.sbml.UPPER_BOUND_ID
   cobra.io.sbml.ZERO_BOUND_ID
   cobra.io.sbml.BOUND_MINUS_INF
   cobra.io.sbml.BOUND_PLUS_INF
   cobra.io.sbml.SBO_FBA_FRAMEWORK
   cobra.io.sbml.SBO_DEFAULT_FLUX_BOUND
   cobra.io.sbml.SBO_FLUX_BOUND
   cobra.io.sbml.SBO_EXCHANGE_REACTION
   cobra.io.sbml.LONG_SHORT_DIRECTION
   cobra.io.sbml.SHORT_LONG_DIRECTION
   cobra.io.sbml.UNITS_FLUX
   cobra.io.sbml.SBML_DOT
   cobra.io.sbml.pattern_notes
   cobra.io.sbml.pattern_to_sbml
   cobra.io.sbml.pattern_from_sbml
   cobra.io.sbml.F_GENE
   cobra.io.sbml.F_GENE_REV
   cobra.io.sbml.F_SPECIE
   cobra.io.sbml.F_SPECIE_REV
   cobra.io.sbml.F_REACTION
   cobra.io.sbml.F_REACTION_REV
   cobra.io.sbml.F_GROUP
   cobra.io.sbml.F_GROUP_REV
   cobra.io.sbml.F_REPLACE
   cobra.io.sbml.URL_IDENTIFIERS_PATTERN
   cobra.io.sbml.URL_IDENTIFIERS_PREFIX
   cobra.io.sbml.QUALIFIER_TYPES


Exceptions
----------

.. autoapisummary::

   cobra.io.sbml.CobraSBMLError


Classes
-------

.. autoapisummary::

   cobra.io.sbml.Unit


Functions
---------

.. autoapisummary::

   cobra.io.sbml._escape_non_alphanum
   cobra.io.sbml._number_to_chr
   cobra.io.sbml._clip
   cobra.io.sbml._f_gene
   cobra.io.sbml._f_gene_rev
   cobra.io.sbml._f_specie
   cobra.io.sbml._f_specie_rev
   cobra.io.sbml._f_reaction
   cobra.io.sbml._f_reaction_rev
   cobra.io.sbml._f_group
   cobra.io.sbml._f_group_rev
   cobra.io.sbml.read_sbml_model
   cobra.io.sbml._get_doc_from_filename
   cobra.io.sbml._sbml_to_model
   cobra.io.sbml.write_sbml_model
   cobra.io.sbml._model_to_sbml
   cobra.io.sbml._create_bound
   cobra.io.sbml._create_parameter
   cobra.io.sbml._check_required
   cobra.io.sbml._check
   cobra.io.sbml._parse_notes_dict
   cobra.io.sbml._sbase_notes_dict
   cobra.io.sbml._parse_annotations
   cobra.io.sbml._parse_annotation_info
   cobra.io.sbml._sbase_annotations
   cobra.io.sbml.validate_sbml_model
   cobra.io.sbml._error_string


Module Contents
---------------

.. py:exception:: CobraSBMLError

   Bases: :py:obj:`Exception`


   SBML error class.


.. py:data:: LOGGER

.. py:data:: config

.. py:data:: LOWER_BOUND_ID
   :value: 'cobra_default_lb'


.. py:data:: UPPER_BOUND_ID
   :value: 'cobra_default_ub'


.. py:data:: ZERO_BOUND_ID
   :value: 'cobra_0_bound'


.. py:data:: BOUND_MINUS_INF
   :value: 'minus_inf'


.. py:data:: BOUND_PLUS_INF
   :value: 'plus_inf'


.. py:data:: SBO_FBA_FRAMEWORK
   :value: 'SBO:0000624'


.. py:data:: SBO_DEFAULT_FLUX_BOUND
   :value: 'SBO:0000626'


.. py:data:: SBO_FLUX_BOUND
   :value: 'SBO:0000625'


.. py:data:: SBO_EXCHANGE_REACTION
   :value: 'SBO:0000627'


.. py:data:: LONG_SHORT_DIRECTION

.. py:data:: SHORT_LONG_DIRECTION

.. py:class:: Unit

   Bases: :py:obj:`tuple`


   .. py:attribute:: kind


   .. py:attribute:: scale


   .. py:attribute:: multiplier


   .. py:attribute:: exponent


.. py:data:: UNITS_FLUX

.. py:data:: SBML_DOT
   :value: '__SBML_DOT__'


.. py:data:: pattern_notes
   :type:  Pattern

.. py:data:: pattern_to_sbml
   :type:  Pattern

.. py:data:: pattern_from_sbml
   :type:  Pattern

.. py:function:: _escape_non_alphanum(nonASCII: Match) -> str

   Convert non alphanumeric to string representation of ascii number.

   Converts a non alphanumeric character to a string representation of
   its ascii number using ord.

   :param nonASCII: Match object, identified by pattern_from_sbml
   :type nonASCII: Match

   :returns: The ascii code, surronded by __.
   :rtype: str


.. py:function:: _number_to_chr(numberStr: Match) -> str

   Convert an ascii number to a character.

   :param numberStr: Match object, identified by pattern_from_sbml
   :type numberStr: Match

   :returns: The first match between the underscores, converted to character.
   :rtype: str


.. py:function:: _clip(sid: str, prefix: str) -> str

   Clip a prefix from the beginning of a string if it exists.

   :param sid: String to clip.
   :type sid: str
   :param prefix: Prefix to remove.
   :type prefix: str

   :returns: The string with prefix clipped if it existed. Otherwise the original string.
   :rtype: str


.. py:function:: _f_gene(sid: str, prefix: str = 'G_') -> str

   Clip gene prefix from id.

   :param sid: String to process
   :type sid: str
   :param prefix: Prefix for gene (default "G_").
   :type prefix: str, optional

   :returns: Returns modified str with prefix removed, SBML_DOT (see above) replaced
             with ".", __(NUMBER)__ replaced with the character value of NUMBER.
   :rtype: str

   .. seealso:: :py:obj:`pattern_from_sbml`, :py:obj:`_number_to_chr`, :py:obj:`SBML_DOT`


.. py:function:: _f_gene_rev(sid: str, prefix: str = 'G_') -> str

   Add gene prefix to id.

   :param sid: String to process
   :type sid: str
   :param prefix: Prefix for gene (default "G_").
   :type prefix: str, optional

   :returns: Returns prefix prepended to modified str, with "." replaced with
             SBML_DOT, non alphanumeric repalced with a string representation of the
             unicode number.
   :rtype: str

   .. seealso:: :py:obj:`pattern_to_sbml`, :py:obj:`_escape_non_alphanum`, :py:obj:`SBML_DOT`


.. py:function:: _f_specie(sid: str, prefix: str = 'M_') -> str

   Clip specie/metabolite prefix from id.

   :param sid: String to process
   :type sid: str
   :param prefix: Prefix for species/metabolite (default "M_").
   :type prefix: str, optional

   :returns: Returns modified str with prefix removed, SBML_DOT (see above) replaced
             with ".", __(NUMBER)__ replaced with the character value of NUMBER.
   :rtype: str

   .. seealso:: :py:obj:`pattern_from_sbml`, :py:obj:`_number_to_chr`, :py:obj:`SBML_DOT`


.. py:function:: _f_specie_rev(sid: str, prefix: str = 'M_') -> str

   Add specie/metabolite prefix to id.

   :param sid: String to process
   :type sid: str
   :param prefix: Prefix for metabolite (default "M_").
   :type prefix: str, optional

   :returns: Returns prefix prepended to modified str, with "." replaced with
             SBML_DOT, non alphanumeric repalced with a string representation of the
             unicode number.
   :rtype: str

   .. seealso:: :py:obj:`pattern_to_sbml`, :py:obj:`_escape_non_alphanum`, :py:obj:`SBML_DOT`


.. py:function:: _f_reaction(sid: str, prefix: str = 'R_') -> str

   Clip reaction prefix from id.

   :param sid: String to process
   :type sid: str
   :param prefix: Prefix for reaction (default "R_").
   :type prefix: str, optional

   :returns: Returns modified str with prefix removed, SBML_DOT (see above) replaced
             with ".", __(NUMBER)__ replaced with the character value of NUMBER.
   :rtype: str

   .. seealso:: :py:obj:`pattern_from_sbml`, :py:obj:`_number_to_chr`, :py:obj:`SBML_DOT`


.. py:function:: _f_reaction_rev(sid: str, prefix: str = 'R_') -> str

   Add reaction prefix to id.

   :param sid: String to process
   :type sid: str
   :param prefix: Prefix for reaction (default "R_").
   :type prefix: str, optional

   :returns: Returns prefix prepended to modified str, with "." replaced with
             SBML_DOT, non alphanumeric repalced with a string representation of the
             unicode number.
   :rtype: str

   .. seealso:: :py:obj:`pattern_to_sbml`, :py:obj:`_escape_non_alphanum`, :py:obj:`SBML_DOT`


.. py:function:: _f_group(sid: str, prefix: str = 'G_') -> str

   Clip group prefix from id.

   :param sid: String to process
   :type sid: str
   :param prefix: Prefix for group (default "G_").
   :type prefix: str, optional

   :returns: Returns modified str with prefix removed, SBML_DOT (see above) replaced
             with ".", __(NUMBER)__ replaced with the character value of NUMBER.
   :rtype: str

   .. seealso:: :py:obj:`pattern_from_sbml`, :py:obj:`_number_to_chr`, :py:obj:`SBML_DOT`


.. py:function:: _f_group_rev(sid: str, prefix: str = 'G_') -> str

   Add group prefix to id.

   :param sid: String to process
   :type sid: str
   :param prefix: Prefix for group (default "G_").
   :type prefix: str, optional

   :returns: Returns prefix prepended to modified str, with "." replaced with
             SBML_DOT, non alphanumeric repalced with a string representation of the
             unicode number.
   :rtype: str

   .. seealso:: :py:obj:`pattern_to_sbml`, :py:obj:`_escape_non_alphanum`, :py:obj:`SBML_DOT`


.. py:data:: F_GENE
   :value: 'F_GENE'


.. py:data:: F_GENE_REV
   :value: 'F_GENE_REV'


.. py:data:: F_SPECIE
   :value: 'F_SPECIE'


.. py:data:: F_SPECIE_REV
   :value: 'F_SPECIE_REV'


.. py:data:: F_REACTION
   :value: 'F_REACTION'


.. py:data:: F_REACTION_REV
   :value: 'F_REACTION_REV'


.. py:data:: F_GROUP
   :value: 'F_GROUP'


.. py:data:: F_GROUP_REV
   :value: 'F_GROUP_REV'


.. py:data:: F_REPLACE
   :type:  dict

.. py:function:: read_sbml_model(filename: Union[str, IO, pathlib.Path], number: Type = float, f_replace: dict = F_REPLACE, **kwargs) -> cobra.core.Model

   Read SBML model from given filename.

   If the given filename ends with the suffix ''.gz'' (for example,
   ''myfile.xml.gz'),' the file is assumed to be compressed in gzip
   format and will be automatically decompressed upon reading. Similarly,
   if the given filename ends with ''.zip'' or ''.bz2',' the file is
   assumed to be compressed in zip or bzip2 format (respectively).  Files
   whose names lack these suffixes will be read uncompressed.  Note that
   if the file is in zip format but the archive contains more than one
   file, only the first file in the archive will be read and the rest
   ignored.

   To read a gzip/zip file, libSBML needs to be configured and linked
   with the zlib library at compile time.  It also needs to be linked
   with the bzip2 library to read files in bzip2 format.  (Both of these
   are the default configurations for libSBML.)

   This function supports SBML with FBC-v1 and FBC-v2. FBC-v1 models
   are converted to FBC-v2 models before reading.

   The parser tries to fall back to information in notes dictionaries
   if information is not available in the FBC packages, e.g.,
   CHARGE, FORMULA on species, or GENE_ASSOCIATION, SUBSYSTEM on reactions.

   :param filename: SBML which is read into cobra model
   :type filename: path to SBML file, or SBML string, or SBML file handle
   :param number: In which data type should the stoichiometry be parsed.
   :type number: data type of stoichiometry: {float, int}
   :param f_replace: Dictionary of replacement functions for gene, specie, and reaction.
                     By default the following id changes are performed on import:
                     clip G_ from genes, clip M_ from species, clip R_ from reactions
                     If no replacements should be performed, set f_replace={}, None
   :type f_replace: dict of replacement functions for id replacement
   :param \*\*kwargs: Further keyword arguments are passed on to the called function (_sbml_to_model)

   :rtype: cobra.core.Model

   :raises IOError if file not read:
   :raises All other errors are wrapped around in a message pointing to SBML validator.:

   .. rubric:: Notes

   Provided file handles cannot be opened in binary mode, i.e., use
       with open(path, "r" as f):
           read_sbml_model(f)
   File handles to compressed files are not supported yet.


.. py:function:: _get_doc_from_filename(filename: Union[str, IO, pathlib.Path]) -> libsbml.SBMLDocument

   Get SBMLDocument from given filename.

   :param filename:
   :type filename: path to SBML, or SBML string, or filehandle

   :rtype: libsbml.SBMLDocument

   :raises IOError if file not readable or does not contain SBML.:
   :raises CobraSBMLError if input type is not valid.:


.. py:function:: _sbml_to_model(doc: libsbml.SBMLDocument, number: Type = float, f_replace: dict = F_REPLACE, set_missing_bounds: bool = False, **kwargs) -> cobra.core.Model

   Create cobra model from SBMLDocument.

   :param doc:
   :type doc: libsbml.SBMLDocument
   :param number: In which data type should the stoichiometry be parsed.
   :type number: data type of stoichiometry: {float, int}
   :param f_replace: dict of replacement functions for id replacement
   :type f_replace: dict
   :param set_missing_bounds: flag to set missing bounds. Looks like it will be ignored.
   :type set_missing_bounds: bool
   :param \*\*kwargs: Further keyword arguments are passed on.

   :rtype: cobra.core.Model

   :raises CobraSBMLError if no SBML model detected in file.:
   :raises Exception if fbc coversion from v1 to v2 needed and not successful.:
   :raises CobraSBMLError if upper or lower bound are missing from a reaction.:
   :raises CobraSBMLError if objective reaction declared and not found. Objective reaction not: declared will lead to an ERROR being logged.


.. py:function:: write_sbml_model(cobra_model: cobra.core.Model, filename: Union[str, IO, pathlib.Path], f_replace: dict = F_REPLACE, **kwargs) -> None

   Write cobra model to filename.

   The created model is SBML level 3 version 1 (L1V3) with
   fbc package v2 (fbc-v2).

   If the given filename ends with the suffix ".gz" (for example,
   "myfile.xml.gz"), libSBML assumes the caller wants the file to be
   written compressed in gzip format. Similarly, if the given filename
   ends with ".zip" or ".bz2", libSBML assumes the caller wants the
   file to be compressed in zip or bzip2 format (respectively). Files
   whose names lack these suffixes will be written uncompressed. Special
   considerations for the zip format: If the given filename ends with
   ".zip", the file placed in the zip archive will have the suffix
   ".xml" or ".sbml".  For example, the file in the zip archive will
   be named "test.xml" if the given filename is "test.xml.zip" or
   "test.zip". Similarly, the filename in the archive will be
   "test.sbml" if the given filename is "test.sbml.zip".

   :param cobra_model: Model instance which is written to SBML
   :type cobra_model: cobra.core.Model
   :param filename: path to which the model is written
   :type filename: string or filehandle
   :param f_replace: dictionary of replacement functions for id replacement
   :type f_replace: dict
   :param \*\*kwargs: Further keyword arguments are passed on.


.. py:function:: _model_to_sbml(cobra_model: cobra.core.Model, f_replace: Optional[dict] = None, units: bool = True) -> libsbml.SBMLDocument

   Convert Cobra model to SBMLDocument.

   :param cobra_model: Cobra model instance
   :type cobra_model: cobra.core.Model
   :param f_replace: Replacement to apply on identifiers.
   :type f_replace: dict of replacement functions
   :param units: Should the FLUX_UNITS be written in the SBMLDocument.
   :type units: boolean

   :rtype: libsbml.SBMLDocument


.. py:function:: _create_bound(model: libsbml.Model, reaction: cobra.core.Reaction, bound_type: str, f_replace: dict, units: Optional[bool] = None, flux_udef: Optional[libsbml.UnitDefinition] = None) -> str

   Create bound in model for given reaction.

   Adds the parameters for the bounds to the SBML model.

   :param model: SBML model instance
   :type model: libsbml.Model
   :param reaction: Cobra reaction instance from which the bounds are read.
   :type reaction: cobra.core.Reaction
   :param bound_type: Type of bound
   :type bound_type: {LOWER_BOUND, UPPER_BOUND}
   :param f_replace: of id replacement functions
   :type f_replace: dict
   :param units: Whether or not to use flux units in the SBML document.
   :type units: bool, optional, defualt None
   :param flux_udef: Unit definition if units are used.
   :type flux_udef: libsbml.UnitDefinition, optional

   :returns: **pid** -- Id of bound parameter.
   :rtype: str


.. py:function:: _create_parameter(model: libsbml.Model, pid: str, value: float, sbo: Optional[str] = None, constant: Optional[bool] = True, units: Optional[bool] = None, flux_udef: Optional[libsbml.UnitDefinition] = None) -> None

   Create parameter in SBML model.

   :param model: SBML model instance
   :type model: libsbml.Model
   :param pid: Parameter id to create in the SBML model.
   :type pid: str
   :param value: Value to set parameter
   :type value: float
   :param sbo: SBO term for parameter. In COBRA, it seems to be SBO_FLUX_BOUND ( "SBO:0000625")
               or SBO_DEFAULT_FLUX_BOUND ("SBO:0000626")
   :type sbo: str, optional
   :param constant: Flag if parameter is constant.
   :type constant: bool, optional
   :param units: Whether or not to use flux units in the SBML document.
   :type units: bool, optional, defualt None
   :param flux_udef: Unit definition if units are used.
   :type flux_udef: libsbml.UnitDefinition, optional


.. py:function:: _check_required(sbase: libsbml.Base, value: str, attribute: str) -> str

   Get required attribute from SBase.

   :param sbase:
   :type sbase: libsbml.SBase
   :param value:
   :type value: existing value
   :param attribute:
   :type attribute: name of attribute

   :rtype: attribute value (or value if already set)

   :raises CobraSBMLError if attribute not found or not parsed.:


.. py:function:: _check(value: Union[None, int], message: str) -> None

   Check the libsbml return value and logs error messages.

   :param value:
   :type value: None or int
   :param message:
   :type message: str
   :param If 'value' is None: 'message' and then exits with status code 1. If 'value' is an integer,
                              it assumes it is a libSBML return status code. If the code value is
                              LIBSBML_OPERATION_SUCCESS, returns without further action; if it is not,
                              prints an error message constructed using 'message' along with text from
                              libSBML explaining the meaning of the code, and exits with status code 1.
   :param logs an error message constructed using: 'message' and then exits with status code 1. If 'value' is an integer,
                                                   it assumes it is a libSBML return status code. If the code value is
                                                   LIBSBML_OPERATION_SUCCESS, returns without further action; if it is not,
                                                   prints an error message constructed using 'message' along with text from
                                                   libSBML explaining the meaning of the code, and exits with status code 1.


.. py:function:: _parse_notes_dict(sbase) -> dict

   Create dictionary of COBRA notes.

   :param sbase:
   :type sbase: libsbml.SBase

   :rtype: dict of notes


.. py:function:: _sbase_notes_dict(sbase: libsbml.SBase, notes: dict) -> None

   Set SBase notes based on dictionary.

   :param sbase: SBML object to set notes on
   :type sbase: libsbml.SBase
   :param notes: Notes information from cobra object.
   :type notes: dict


.. py:data:: URL_IDENTIFIERS_PATTERN

.. py:data:: URL_IDENTIFIERS_PREFIX
   :value: 'https://identifiers.org'


.. py:data:: QUALIFIER_TYPES

.. py:function:: _parse_annotations(sbase: libsbml.SBase) -> dict

   Parse cobra annotations from a given SBase object.

   Annotations are dictionaries with the providers as keys.

   :param sbase: SBase from which the SBML annotations are read
   :type sbase: libsbml.SBase

   :rtype: dict (annotation dictionary)


.. py:function:: _parse_annotation_info(uri: str) -> Union[None, Tuple[str, str]]

   Parse provider and term from given identifiers annotation uri.

   :param uri: uri (identifiers.org url)
   :type uri: str

   :rtype: (provider, identifier) if resolvable, None otherwise


.. py:function:: _sbase_annotations(sbase: libsbml.SBase, annotation: dict) -> None

   Set SBase annotations based on cobra annotations.

   :param sbase: SBML object to annotate
   :type sbase: libsbml.SBase
   :param annotation: cobra object with annotation information
   :type annotation: dict, cobra annotation structure

   :raises CobraSBMLError for unsupported qualifier:


.. py:function:: validate_sbml_model(filename: Union[str, IO, pathlib.Path], check_model: bool = True, internal_consistency: bool = True, check_units_consistency: bool = False, check_modeling_practice: bool = False, **kwargs) -> Tuple[Optional[cobra.core.Model], dict]

   Validate SBML model and returns the model along with a list of errors.

   :param filename: The filename (or SBML string) of the SBML model to be validated.
   :type filename: str or filehandle
   :param check_model: Whether to also check some basic model properties such as reaction
                       boundaries and compartment formulas.
   :type check_model: boolean {True, False}, default True
   :param internal_consistency: Check internal consistency (default True).
   :type internal_consistency: bool, optional
   :param check_units_consistency: Check consistency of units (default True).
   :type check_units_consistency: bool, optional
   :param check_modeling_practice: Check modeling practise (defualt True).
   :type check_modeling_practice: bool, optional
   :param \*\*kwargs: Further keyword arguments are passed on to the called function (_sbml_to_model).

   :returns: * *(model, errors)*
             * **model** (:class:`~cobra.core.Model.Model` object) -- The cobra model if the file could be read successfully or None
               otherwise.
             * **errors** (*dict*) -- Warnings and errors grouped by their respective types.

   .. rubric:: Notes

   Errors and warnings are grouped based on their type. SBML_* types are
   from the libsbml validator. COBRA_* types are from the cobrapy SBML
   parser.


.. py:function:: _error_string(error: libsbml.SBMLError, k: Optional[int] = None)

   Return string representation of SBMLError.

   :param error:
   :type error: libsbml.SBMLError
   :param k: index of error (default None).
   :type k: int, optional

   :rtype: string representation of error


