signature:
def flux_variability_analysis ( model , reaction_list = None , loopless = False , fraction_of_optimum = 1.0 , pfba_factor = None , processes = None ) :
    """Determine the minimum and maximum possible flux value for each reaction .
 Parameters
 model : cobra . Model
 The model for which to run the analysis . It will * not * be modified .
 reaction _ list : list of cobra . Reaction or str , optional
 The reactions for which to obtain min / max fluxes . If None will use
 all reactions in the model ( default ) .
 loopless : boolean , optional
 Whether to return only loopless solutions . This is significantly
 slower . Please also refer to the notes .
 fraction _ of _ optimum : float , optional
 Must be < = 1.0 . Requires that the objective value is at least the
 fraction times maximum objective value . A value of 0.85 for instance
 means that the objective has to be at least at 85 % percent of its
 maximum .
 pfba _ factor : float , optional
 Add an additional constraint to the model that requires the total sum
 of absolute fluxes must not be larger than this value times the
 smallest possible sum of absolute fluxes , i . e . , by setting the value
 to 1.1 the total sum of absolute fluxes must not be more than
 10 % larger than the pFBA solution . Since the pFBA solution is the
 one that optimally minimizes the total flux sum , the ` ` pfba _ factor ` `
 should , if set , be larger than one . Setting this value may lead to
 more realistic predictions of the effective flux bounds .
 processes : int , optional
 The number of parallel processes to run . If not explicitly passed ,
 will be set from the global configuration singleton .
 Returns
 pandas . DataFrame
 A data frame with reaction identifiers as the index and two columns :
 - maximum : indicating the highest possible flux
 - minimum : indicating the lowest possible flux
 Notes
 This implements the fast version as described in [ 1 ] _ . Please note that
 the flux distribution containing all minimal / maximal fluxes does not have
 to be a feasible solution for the model . Fluxes are minimized / maximized
 individually and a single minimal flux might require all others to be
 suboptimal .
 Using the loopless option will lead to a significant increase in
 computation time ( about a factor of 100 for large models ) . However , the
 algorithm used here ( see [ 2 ] _ ) is still more than 1000x faster than the
 " naive " version using ` ` add _ loopless ( model ) ` ` . Also note that if you have
 included constraints that force a loop ( for instance by setting all fluxes
 in a loop to be non - zero ) this loop will be included in the solution .
 References
 . . [ 1 ] Computationally efficient flux variability analysis .
 Gudmundsson S , Thiele I .
 BMC Bioinformatics . 2010 Sep 29;11:489.
 doi : 10.1186/1471-2105-11-489 , PMID : 20920235
 . . [ 2 ] CycleFreeFlux : efficient removal of thermodynamically infeasible
 loops from flux distributions .
 Desouki AA , Jarre F , Gelius - Dietrich G , Lercher MJ .
 Bioinformatics . 2015 Jul 1;31(13 ) : 2159-65.
 doi : 10.1093 / bioinformatics / btv096."""

implementation:
if reaction_list is None :
    reaction_ids = [ r . id for r in model . reactions ]
else :
    reaction_ids = [ r . id for r in model . reactions . get_by_any ( reaction_list ) ]
if processes is None :
    processes = CONFIGURATION . processes
num_reactions = len ( reaction_ids )
processes = min ( processes , num_reactions )
fva_result = DataFrame ( { "minimum" : zeros ( num_reactions , dtype = float ) , "maximum" : zeros ( num_reactions , dtype = float ) } , index = reaction_ids )
prob = model . problem
with model : # Safety check before setting up FVA .
    model . slim_optimize ( error_value = None , message = "There is no optimal solution for the " "chosen objective!" )
    # Add the previous objective as a variable to the model then set it to
    # zero . This also uses the fraction to create the lower / upper bound for
    # the old objective .
    # TODO : Use utility function here ( fix _ objective _ as _ constraint ) ?
    if model . solver . objective . direction == "max" :
        fva_old_objective = prob . Variable ( "fva_old_objective" , lb = fraction_of_optimum * model . solver . objective . value )
    else :
        fva_old_objective = prob . Variable ( "fva_old_objective" , ub = fraction_of_optimum * model . solver . objective . value )
    fva_old_obj_constraint = prob . Constraint ( model . solver . objective . expression - fva_old_objective , lb = 0 , ub = 0 , name = "fva_old_objective_constraint" )
    model . add_cons_vars ( [ fva_old_objective , fva_old_obj_constraint ] )
    if pfba_factor is not None :
        if pfba_factor < 1. :
            warn ( "The 'pfba_factor' should be larger or equal to 1." , UserWarning )
        with model :
            add_pfba ( model , fraction_of_optimum = 0 )
            ub = model . slim_optimize ( error_value = None )
            flux_sum = prob . Variable ( "flux_sum" , ub = pfba_factor * ub )
            flux_sum_constraint = prob . Constraint ( model . solver . objective . expression - flux_sum , lb = 0 , ub = 0 , name = "flux_sum_constraint" )
        model . add_cons_vars ( [ flux_sum , flux_sum_constraint ] )
    model . objective = Zero
    # This will trigger the reset as well
    for what in ( "minimum" , "maximum" ) :
        if processes > 1 : # We create and destroy a new pool here in order to set the
        # objective direction for all reactions . This creates a
        # slight overhead but seems the most clean .
            chunk_size = len ( reaction_ids ) // processes
            pool = multiprocessing . Pool ( processes , initializer = _init_worker , initargs = ( model , loopless , what [ : 3 ] ) )
            for rxn_id , value in pool . imap_unordered ( _fva_step , reaction_ids , chunksize = chunk_size ) :
                fva_result . at [ rxn_id , what ] = value
            pool . close ( )
            pool . join ( )
        else :
            _init_worker ( model , loopless , what [ : 3 ] )
            for rxn_id , value in map ( _fva_step , reaction_ids ) :
                fva_result . at [ rxn_id , what ] = value
return fva_result [ [ "minimum" , "maximum" ] ]


signature:
def find_blocked_reactions ( model , reaction_list = None , zero_cutoff = None , open_exchanges = False , processes = None ) :
    """Find reactions that cannot carry any flux .
 The question whether or not a reaction is blocked is highly dependent
 on the current exchange reaction settings for a COBRA model . Hence an
 argument is provided to open all exchange reactions .
 Notes
 Sink and demand reactions are left untouched . Please modify them manually .
 Parameters
 model : cobra . Model
 The model to analyze .
 reaction _ list : list , optional
 List of reactions to consider , the default includes all model
 reactions .
 zero _ cutoff : float , optional
 Flux value which is considered to effectively be zero
 ( default model . tolerance ) .
 open _ exchanges : bool , optional
 Whether or not to open all exchange reactions to very high flux ranges .
 processes : int , optional
 The number of parallel processes to run . Can speed up the computations
 if the number of reactions is large . If not explicitly
 passed , it will be set from the global configuration singleton .
 Returns
 list
 List with the identifiers of blocked reactions ."""

implementation:
zero_cutoff = normalize_cutoff ( model , zero_cutoff )
with model :
    if open_exchanges :
        for reaction in model . exchanges :
            reaction . bounds = ( min ( reaction . lower_bound , - 1000 ) , max ( reaction . upper_bound , 1000 ) )
    if reaction_list is None :
        reaction_list = model . reactions
    # Limit the search space to reactions which have zero flux . If the
    # reactions already carry flux in this solution ,
    # then they cannot be blocked .
    model . slim_optimize ( )
    solution = get_solution ( model , reactions = reaction_list )
    reaction_list = solution . fluxes [ solution . fluxes . abs ( ) < zero_cutoff ] . index . tolist ( )
    # Run FVA to find reactions where both the minimal and maximal flux
    # are zero ( below the cut off ) .
    flux_span = flux_variability_analysis ( model , fraction_of_optimum = 0. , reaction_list = reaction_list , processes = processes )
    return flux_span [ flux_span . abs ( ) . max ( axis = 1 ) < zero_cutoff ] . index . tolist ( )


signature:
def find_essential_genes ( model , threshold = None , processes = None ) :
    """Return a set of essential genes .
 A gene is considered essential if restricting the flux of all reactions
 that depend on it to zero causes the objective , e . g . , the growth rate ,
 to also be zero , below the threshold , or infeasible .
 Parameters
 model : cobra . Model
 The model to find the essential genes for .
 threshold : float , optional
 Minimal objective flux to be considered viable . By default this is
 1 % of the maximal objective .
 processes : int , optional
 The number of parallel processes to run . If not passed ,
 will be set to the number of CPUs found .
 processes : int , optional
 The number of parallel processes to run . Can speed up the computations
 if the number of knockouts to perform is large . If not explicitly
 passed , it will be set from the global configuration singleton .
 Returns
 set
 Set of essential genes"""

implementation:
if threshold is None :
    threshold = model . slim_optimize ( error_value = None ) * 1E-02
deletions = single_gene_deletion ( model , method = 'fba' , processes = processes )
essential = deletions . loc [ deletions [ 'growth' ] . isna ( ) | ( deletions [ 'growth' ] < threshold ) , : ] . index
return { model . genes . get_by_id ( g ) for ids in essential for g in ids }


signature:
def find_essential_reactions ( model , threshold = None , processes = None ) :
    """Return a set of essential reactions .
 A reaction is considered essential if restricting its flux to zero
 causes the objective , e . g . , the growth rate , to also be zero , below the
 threshold , or infeasible .
 Parameters
 model : cobra . Model
 The model to find the essential reactions for .
 threshold : float , optional
 Minimal objective flux to be considered viable . By default this is
 1 % of the maximal objective .
 processes : int , optional
 The number of parallel processes to run . Can speed up the computations
 if the number of knockouts to perform is large . If not explicitly
 passed , it will be set from the global configuration singleton .
 Returns
 set
 Set of essential reactions"""

implementation:
if threshold is None :
    threshold = model . slim_optimize ( error_value = None ) * 1E-02
deletions = single_reaction_deletion ( model , method = 'fba' , processes = processes )
essential = deletions . loc [ deletions [ 'growth' ] . isna ( ) | ( deletions [ 'growth' ] < threshold ) , : ] . index
return { model . reactions . get_by_id ( r ) for ids in essential for r in ids }


signature:
def add_SBO ( model ) :
    """adds SBO terms for demands and exchanges
 This works for models which follow the standard convention for
 constructing and naming these reactions .
 The reaction should only contain the single metabolite being exchanged ,
 and the id should be EX _ metid or DM _ metid"""

implementation:
for r in model . reactions : # don ' t annotate already annotated reactions
    if r . annotation . get ( "sbo" ) :
        continue
    # only doing exchanges
    if len ( r . metabolites ) != 1 :
        continue
    met_id = list ( r . _metabolites ) [ 0 ] . id
    if r . id . startswith ( "EX_" ) and r . id == "EX_" + met_id :
        r . annotation [ "sbo" ] = "SBO:0000627"
    elif r . id . startswith ( "DM_" ) and r . id == "DM_" + met_id :
        r . annotation [ "sbo" ] = "SBO:0000628"


signature:
def weight ( self ) :
    """Calculate the mol mass of the compound
 Returns
 float
 the mol mass"""

implementation:
try :
    return sum ( [ count * elements_and_molecular_weights [ element ] for element , count in self . elements . items ( ) ] )
except KeyError as e :
    warn ( "The element %s does not appear in the periodic table" % e )


signature:
def insert_break ( lines , break_pos = 9 ) :
    """Insert a < ! - - more - - > tag for larger release notes .
 Parameters
 lines : list of str
 The content of the release note .
 break _ pos : int
 Line number before which a break should approximately be inserted .
 Returns
 list of str
 The text with the inserted tag or no modification if it was
 sufficiently short ."""

implementation:
def line_filter ( line ) :
    if len ( line ) == 0 :
        return True
    return any ( line . startswith ( c ) for c in "-*+" )
if len ( lines ) <= break_pos :
    return lines
newlines = [ i for i , line in enumerate ( lines [ break_pos : ] , start = break_pos ) if line_filter ( line . strip ( ) ) ]
if len ( newlines ) > 0 :
    break_pos = newlines [ 0 ]
lines . insert ( break_pos , "<!--more-->\n" )
return lines


signature:
def build_hugo_md ( filename , tag , bump ) :
    """Build the markdown release notes for Hugo .
 Inserts the required TOML header with specific values and adds a break
 for long release notes .
 Parameters
 filename : str , path
 The release notes file .
 tag : str
 The tag , following semantic versioning , of the current release .
 bump : { " major " , " minor " , " patch " , " alpha " , " beta " }
 The type of release ."""

implementation:
header = [ '+++\n' , 'date = "{}"\n' . format ( date . today ( ) . isoformat ( ) ) , 'title = "{}"\n' . format ( tag ) , 'author = "The COBRApy Team"\n' , 'release = "{}"\n' . format ( bump ) , '+++\n' , '\n' ]
with open ( filename , "r" ) as file_h :
    content = insert_break ( file_h . readlines ( ) )
header . extend ( content )
with open ( filename , "w" ) as file_h :
    file_h . writelines ( header )


signature:
def find_bump ( target , tag ) :
    """Identify the kind of release by comparing to existing ones ."""

implementation:
tmp = tag . split ( "." )
existing = [ intify ( basename ( f ) ) for f in glob ( join ( target , "[0-9]*.md" ) ) ]
latest = max ( existing )
if int ( tmp [ 0 ] ) > latest [ 0 ] :
    return "major"
elif int ( tmp [ 1 ] ) > latest [ 1 ] :
    return "minor"
else :
    return "patch"


signature:
def main ( argv ) :
    """Identify the release type and create a new target file with TOML header .
 Requires three arguments ."""

implementation:
source , target , tag = argv
if "a" in tag :
    bump = "alpha"
if "b" in tag :
    bump = "beta"
else :
    bump = find_bump ( target , tag )
filename = "{}.md" . format ( tag )
destination = copy ( join ( source , filename ) , target )
build_hugo_md ( destination , tag , bump )


signature:
def _multi_deletion ( model , entity , element_lists , method = "fba" , solution = None , processes = None , ** kwargs ) :
    """Provide a common interface for single or multiple knockouts .
 Parameters
 model : cobra . Model
 The metabolic model to perform deletions in .
 entity : ' gene ' or ' reaction '
 The entity to knockout ( ` ` cobra . Gene ` ` or ` ` cobra . Reaction ` ` ) .
 element _ lists : list
 List of iterables ` ` cobra . Reaction ` ` s or ` ` cobra . Gene ` ` s ( or their IDs )
 to be deleted .
 method : { " fba " , " moma " , " linear moma " , " room " , " linear room " } , optional
 Method used to predict the growth rate .
 solution : cobra . Solution , optional
 A previous solution to use as a reference for ( linear ) MOMA or ROOM .
 processes : int , optional
 The number of parallel processes to run . Can speed up the computations
 if the number of knockouts to perform is large . If not passed ,
 will be set to the number of CPUs found .
 kwargs :
 Passed on to underlying simulation functions .
 Returns
 pandas . DataFrame
 A representation of all combinations of entity deletions . The
 columns are ' growth ' and ' status ' , where
 index : frozenset ( [ str ] )
 The gene or reaction identifiers that were knocked out .
 growth : float
 The growth rate of the adjusted model .
 status : str
 The solution ' s status ."""

implementation:
solver = sutil . interface_to_str ( model . problem . __name__ )
if method == "moma" and solver not in sutil . qp_solvers :
    raise RuntimeError ( "Cannot use MOMA since '{}' is not QP-capable." "Please choose a different solver or use FBA only." . format ( solver ) )
if processes is None :
    processes = CONFIGURATION . processes
with model :
    if "moma" in method :
        add_moma ( model , solution = solution , linear = "linear" in method )
    elif "room" in method :
        add_room ( model , solution = solution , linear = "linear" in method , ** kwargs )
    args = set ( [ frozenset ( comb ) for comb in product ( * element_lists ) ] )
    processes = min ( processes , len ( args ) )
    def extract_knockout_results ( result_iter ) :
        result = pd . DataFrame ( [ ( frozenset ( ids ) , growth , status ) for ( ids , growth , status ) in result_iter ] , columns = [ 'ids' , 'growth' , 'status' ] )
        result . set_index ( 'ids' , inplace = True )
        return result
    if processes > 1 :
        worker = dict ( gene = _gene_deletion_worker , reaction = _reaction_deletion_worker ) [ entity ]
        chunk_size = len ( args ) // processes
        pool = multiprocessing . Pool ( processes , initializer = _init_worker , initargs = ( model , ) )
        results = extract_knockout_results ( pool . imap_unordered ( worker , args , chunksize = chunk_size ) )
        pool . close ( )
        pool . join ( )
    else :
        worker = dict ( gene = _gene_deletion , reaction = _reaction_deletion ) [ entity ]
        results = extract_knockout_results ( map ( partial ( worker , model ) , args ) )
    return results


signature:
def single_reaction_deletion ( model , reaction_list = None , method = "fba" , solution = None , processes = None , ** kwargs ) :
    """Knock out each reaction from a given list .
 Parameters
 model : cobra . Model
 The metabolic model to perform deletions in .
 reaction _ list : iterable , optional
 ` ` cobra . Reaction ` ` s to be deleted . If not passed ,
 all the reactions from the model are used .
 method : { " fba " , " moma " , " linear moma " , " room " , " linear room " } , optional
 Method used to predict the growth rate .
 solution : cobra . Solution , optional
 A previous solution to use as a reference for ( linear ) MOMA or ROOM .
 processes : int , optional
 The number of parallel processes to run . Can speed up the computations
 if the number of knockouts to perform is large . If not passed ,
 will be set to the number of CPUs found .
 kwargs :
 Keyword arguments are passed on to underlying simulation functions
 such as ` ` add _ room ` ` .
 Returns
 pandas . DataFrame
 A representation of all single reaction deletions . The columns are
 ' growth ' and ' status ' , where
 index : frozenset ( [ str ] )
 The reaction identifier that was knocked out .
 growth : float
 The growth rate of the adjusted model .
 status : str
 The solution ' s status ."""

implementation: return _multi_deletion ( model , 'reaction' , element_lists = _element_lists ( model . reactions , reaction_list ) , method = method , solution = solution , processes = processes , ** kwargs )


signature:
def single_gene_deletion ( model , gene_list = None , method = "fba" , solution = None , processes = None , ** kwargs ) :
    """Knock out each gene from a given list .
 Parameters
 model : cobra . Model
 The metabolic model to perform deletions in .
 gene _ list : iterable
 ` ` cobra . Gene ` ` s to be deleted . If not passed ,
 all the genes from the model are used .
 method : { " fba " , " moma " , " linear moma " , " room " , " linear room " } , optional
 Method used to predict the growth rate .
 solution : cobra . Solution , optional
 A previous solution to use as a reference for ( linear ) MOMA or ROOM .
 processes : int , optional
 The number of parallel processes to run . Can speed up the computations
 if the number of knockouts to perform is large . If not passed ,
 will be set to the number of CPUs found .
 kwargs :
 Keyword arguments are passed on to underlying simulation functions
 such as ` ` add _ room ` ` .
 Returns
 pandas . DataFrame
 A representation of all single gene deletions . The columns are
 ' growth ' and ' status ' , where
 index : frozenset ( [ str ] )
 The gene identifier that was knocked out .
 growth : float
 The growth rate of the adjusted model .
 status : str
 The solution ' s status ."""

implementation: return _multi_deletion ( model , 'gene' , element_lists = _element_lists ( model . genes , gene_list ) , method = method , solution = solution , processes = processes , ** kwargs )


signature:
def double_reaction_deletion ( model , reaction_list1 = None , reaction_list2 = None , method = "fba" , solution = None , processes = None , ** kwargs ) :
    """Knock out each reaction pair from the combinations of two given lists .
 We say ' pair ' here but the order order does not matter .
 Parameters
 model : cobra . Model
 The metabolic model to perform deletions in .
 reaction _ list1 : iterable , optional
 First iterable of ` ` cobra . Reaction ` ` s to be deleted . If not passed ,
 all the reactions from the model are used .
 reaction _ list2 : iterable , optional
 Second iterable of ` ` cobra . Reaction ` ` s to be deleted . If not passed ,
 all the reactions from the model are used .
 method : { " fba " , " moma " , " linear moma " , " room " , " linear room " } , optional
 Method used to predict the growth rate .
 solution : cobra . Solution , optional
 A previous solution to use as a reference for ( linear ) MOMA or ROOM .
 processes : int , optional
 The number of parallel processes to run . Can speed up the computations
 if the number of knockouts to perform is large . If not passed ,
 will be set to the number of CPUs found .
 kwargs :
 Keyword arguments are passed on to underlying simulation functions
 such as ` ` add _ room ` ` .
 Returns
 pandas . DataFrame
 A representation of all combinations of reaction deletions . The
 columns are ' growth ' and ' status ' , where
 index : frozenset ( [ str ] )
 The reaction identifiers that were knocked out .
 growth : float
 The growth rate of the adjusted model .
 status : str
 The solution ' s status ."""

implementation:
reaction_list1 , reaction_list2 = _element_lists ( model . reactions , reaction_list1 , reaction_list2 )
return _multi_deletion ( model , 'reaction' , element_lists = [ reaction_list1 , reaction_list2 ] , method = method , solution = solution , processes = processes , ** kwargs )


signature:
def double_gene_deletion ( model , gene_list1 = None , gene_list2 = None , method = "fba" , solution = None , processes = None , ** kwargs ) :
    """Knock out each gene pair from the combination of two given lists .
 We say ' pair ' here but the order order does not matter .
 Parameters
 model : cobra . Model
 The metabolic model to perform deletions in .
 gene _ list1 : iterable , optional
 First iterable of ` ` cobra . Gene ` ` s to be deleted . If not passed ,
 all the genes from the model are used .
 gene _ list2 : iterable , optional
 Second iterable of ` ` cobra . Gene ` ` s to be deleted . If not passed ,
 all the genes from the model are used .
 method : { " fba " , " moma " , " linear moma " , " room " , " linear room " } , optional
 Method used to predict the growth rate .
 solution : cobra . Solution , optional
 A previous solution to use as a reference for ( linear ) MOMA or ROOM .
 processes : int , optional
 The number of parallel processes to run . Can speed up the computations
 if the number of knockouts to perform is large . If not passed ,
 will be set to the number of CPUs found .
 kwargs :
 Keyword arguments are passed on to underlying simulation functions
 such as ` ` add _ room ` ` .
 Returns
 pandas . DataFrame
 A representation of all combinations of gene deletions . The
 columns are ' growth ' and ' status ' , where
 index : frozenset ( [ str ] )
 The gene identifiers that were knocked out .
 growth : float
 The growth rate of the adjusted model .
 status : str
 The solution ' s status ."""

implementation:
gene_list1 , gene_list2 = _element_lists ( model . genes , gene_list1 , gene_list2 )
return _multi_deletion ( model , 'gene' , element_lists = [ gene_list1 , gene_list2 ] , method = method , solution = solution , processes = processes , ** kwargs )


signature:
def reverse_id ( self ) :
    """Generate the id of reverse _ variable from the reaction ' s id ."""

implementation: return '_' . join ( ( self . id , 'reverse' , hashlib . md5 ( self . id . encode ( 'utf-8' ) ) . hexdigest ( ) [ 0 : 5 ] ) )


signature:
def flux ( self ) :
    """The flux value in the most recent solution .
 Flux is the primal value of the corresponding variable in the model .
 Warnings
 * Accessing reaction fluxes through a ` Solution ` object is the safer ,
 preferred , and only guaranteed to be correct way . You can see how to
 do so easily in the examples .
 * Reaction flux is retrieved from the currently defined
 ` self . _ model . solver ` . The solver status is checked but there are no
 guarantees that the current solver state is the one you are looking
 for .
 * If you modify the underlying model after an optimization , you will
 retrieve the old optimization values .
 Raises
 RuntimeError
 If the underlying model was never optimized beforehand or the
 reaction is not part of a model .
 OptimizationError
 If the solver status is anything other than ' optimal ' .
 AssertionError
 If the flux value is not within the bounds .
 Examples
 > > > import cobra . test
 > > > model = cobra . test . create _ test _ model ( " textbook " )
 > > > solution = model . optimize ( )
 > > > model . reactions . PFK . flux
 7.477381962160283
 > > > solution . fluxes . PFK
 7.4773819621602833"""

implementation:
try :
    check_solver_status ( self . _model . solver . status )
    return self . forward_variable . primal - self . reverse_variable . primal
except AttributeError :
    raise RuntimeError ( "reaction '{}' is not part of a model" . format ( self . id ) )
# Due to below all - catch , which sucks , need to reraise these .
except ( RuntimeError , OptimizationError ) as err :
    raise_with_traceback ( err )
# Would love to catch CplexSolverError and GurobiError here .
except Exception as err :
    raise_from ( OptimizationError ( "Likely no solution exists. Original solver message: {}." "" . format ( str ( err ) ) ) , err )


signature:
def gene_name_reaction_rule ( self ) :
    """Display gene _ reaction _ rule with names intead .
 Do NOT use this string for computation . It is intended to give a
 representation of the rule using more familiar gene names instead of
 the often cryptic ids ."""

implementation:
names = { i . id : i . name for i in self . _genes }
ast = parse_gpr ( self . _gene_reaction_rule ) [ 0 ]
return ast2str ( ast , names = names )


signature:
def functional ( self ) :
    """All required enzymes for reaction are functional .
 Returns
 bool
 True if the gene - protein - reaction ( GPR ) rule is fulfilled for
 this reaction , or if reaction is not associated to a model ,
 otherwise False ."""

implementation:
if self . _model :
    tree , _ = parse_gpr ( self . gene_reaction_rule )
    return eval_gpr ( tree , { gene . id for gene in self . genes if not gene . functional } )
return True


signature:
def _update_awareness ( self ) :
    """Make sure all metabolites and genes that are associated with
 this reaction are aware of it ."""

implementation:
for x in self . _metabolites :
    x . _reaction . add ( self )
for x in self . _genes :
    x . _reaction . add ( self )


signature:
def remove_from_model ( self , remove_orphans = False ) :
    """Removes the reaction from a model .
 This removes all associations between a reaction the associated
 model , metabolites and genes .
 The change is reverted upon exit when using the model as a context .
 Parameters
 remove _ orphans : bool
 Remove orphaned genes and metabolites from the model as well"""

implementation: self . _model . remove_reactions ( [ self ] , remove_orphans = remove_orphans )


signature:
def delete ( self , remove_orphans = False ) :
    """Removes the reaction from a model .
 This removes all associations between a reaction the associated
 model , metabolites and genes .
 The change is reverted upon exit when using the model as a context .
 Deprecated , use ` reaction . remove _ from _ model ` instead .
 Parameters
 remove _ orphans : bool
 Remove orphaned genes and metabolites from the model as well"""

implementation:
warn ( "delete is deprecated. Use reaction.remove_from_model instead" , DeprecationWarning )
self . remove_from_model ( remove_orphans = remove_orphans )


signature:
def copy ( self ) :
    """Copy a reaction
 The referenced metabolites and genes are also copied ."""

implementation:
# no references to model when copying
model = self . _model
self . _model = None
for i in self . _metabolites :
    i . _model = None
for i in self . _genes :
    i . _model = None
# now we can copy
new_reaction = deepcopy ( self )
# restore the references
self . _model = model
for i in self . _metabolites :
    i . _model = model
for i in self . _genes :
    i . _model = model
return new_reaction


signature:
def get_coefficient ( self , metabolite_id ) :
    """Return the stoichiometric coefficient of a metabolite .
 Parameters
 metabolite _ id : str or cobra . Metabolite"""

implementation:
if isinstance ( metabolite_id , Metabolite ) :
    return self . _metabolites [ metabolite_id ]
_id_to_metabolites = { m . id : m for m in self . _metabolites }
return self . _metabolites [ _id_to_metabolites [ metabolite_id ] ]


signature:
def add_metabolites ( self , metabolites_to_add , combine = True , reversibly = True ) :
    """Add metabolites and stoichiometric coefficients to the reaction .
 If the final coefficient for a metabolite is 0 then it is removed
 from the reaction .
 The change is reverted upon exit when using the model as a context .
 Parameters
 metabolites _ to _ add : dict
 Dictionary with metabolite objects or metabolite identifiers as
 keys and coefficients as values . If keys are strings ( name of a
 metabolite ) the reaction must already be part of a model and a
 metabolite with the given name must exist in the model .
 combine : bool
 Describes behavior a metabolite already exists in the reaction .
 True causes the coefficients to be added .
 False causes the coefficient to be replaced .
 reversibly : bool
 Whether to add the change to the context to make the change
 reversibly or not ( primarily intended for internal use ) ."""

implementation:
old_coefficients = self . metabolites
new_metabolites = [ ]
_id_to_metabolites = dict ( [ ( x . id , x ) for x in self . _metabolites ] )
for metabolite , coefficient in iteritems ( metabolites_to_add ) : # Make sure metabolites being added belong to the same model , or
# else copy them .
    if isinstance ( metabolite , Metabolite ) :
        if ( ( metabolite . model is not None ) and ( metabolite . model is not self . _model ) ) :
            metabolite = metabolite . copy ( )
    met_id = str ( metabolite )
    # If a metabolite already exists in the reaction then
    # just add them .
    if met_id in _id_to_metabolites :
        reaction_metabolite = _id_to_metabolites [ met_id ]
        if combine :
            self . _metabolites [ reaction_metabolite ] += coefficient
        else :
            self . _metabolites [ reaction_metabolite ] = coefficient
    else : # If the reaction is in a model , ensure we aren ' t using
    # a duplicate metabolite .
        if self . _model :
            try :
                metabolite = self . _model . metabolites . get_by_id ( met_id )
            except KeyError as e :
                if isinstance ( metabolite , Metabolite ) :
                    new_metabolites . append ( metabolite )
                else : # do we want to handle creation here ?
                    raise e
        elif isinstance ( metabolite , string_types ) : # if we want to handle creation , this should be changed
            raise ValueError ( "Reaction '%s' does not belong to a " "model. Either add the reaction to a " "model or use Metabolite objects instead " "of strings as keys." % self . id )
        self . _metabolites [ metabolite ] = coefficient
        # make the metabolite aware that it is involved in this
        # reaction
        metabolite . _reaction . add ( self )
# from cameo . . .
model = self . model
if model is not None :
    model . add_metabolites ( new_metabolites )
    for metabolite , coefficient in self . _metabolites . items ( ) :
        model . constraints [ metabolite . id ] . set_linear_coefficients ( { self . forward_variable : coefficient , self . reverse_variable : - coefficient } )
for metabolite , the_coefficient in list ( self . _metabolites . items ( ) ) :
    if the_coefficient == 0 : # make the metabolite aware that it no longer participates
    # in this reaction
        metabolite . _reaction . remove ( self )
        self . _metabolites . pop ( metabolite )
context = get_context ( self )
if context and reversibly :
    if combine : # Just subtract the metabolites that were added
        context ( partial ( self . subtract_metabolites , metabolites_to_add , combine = True , reversibly = False ) )
    else : # Reset them with add _ metabolites
        mets_to_reset = { key : old_coefficients [ model . metabolites . get_by_any ( key ) [ 0 ] ] for key in iterkeys ( metabolites_to_add ) }
        context ( partial ( self . add_metabolites , mets_to_reset , combine = False , reversibly = False ) )


signature:
def subtract_metabolites ( self , metabolites , combine = True , reversibly = True ) :
    """Subtract metabolites from a reaction .
 That means add the metabolites with - 1 * coefficient . If the final
 coefficient for a metabolite is 0 then the metabolite is removed from
 the reaction .
 Notes
 * A final coefficient < 0 implies a reactant .
 * The change is reverted upon exit when using the model as a context .
 Parameters
 metabolites : dict
 Dictionary where the keys are of class Metabolite and the values
 are the coefficients . These metabolites will be added to the
 reaction .
 combine : bool
 Describes behavior a metabolite already exists in the reaction .
 True causes the coefficients to be added .
 False causes the coefficient to be replaced .
 reversibly : bool
 Whether to add the change to the context to make the change
 reversibly or not ( primarily intended for internal use ) ."""

implementation: self . add_metabolites ( { k : - v for k , v in iteritems ( metabolites ) } , combine = combine , reversibly = reversibly )


signature:
def build_reaction_string ( self , use_metabolite_names = False ) :
    """Generate a human readable reaction string"""

implementation:
def format ( number ) :
    return "" if number == 1 else str ( number ) . rstrip ( "." ) + " "
id_type = 'id'
if use_metabolite_names :
    id_type = 'name'
reactant_bits = [ ]
product_bits = [ ]
for met in sorted ( self . _metabolites , key = attrgetter ( "id" ) ) :
    coefficient = self . _metabolites [ met ]
    name = str ( getattr ( met , id_type ) )
    if coefficient >= 0 :
        product_bits . append ( format ( coefficient ) + name )
    else :
        reactant_bits . append ( format ( abs ( coefficient ) ) + name )
reaction_string = ' + ' . join ( reactant_bits )
if not self . reversibility :
    if self . lower_bound < 0 and self . upper_bound <= 0 :
        reaction_string += ' <-- '
    else :
        reaction_string += ' --> '
else :
    reaction_string += ' <=> '
reaction_string += ' + ' . join ( product_bits )
return reaction_string


signature:
def check_mass_balance ( self ) :
    """Compute mass and charge balance for the reaction
 returns a dict of { element : amount } for unbalanced elements .
 " charge " is treated as an element in this dict
 This should be empty for balanced reactions ."""

implementation:
reaction_element_dict = defaultdict ( int )
for metabolite , coefficient in iteritems ( self . _metabolites ) :
    if metabolite . charge is not None :
        reaction_element_dict [ "charge" ] += coefficient * metabolite . charge
    if metabolite . elements is None :
        raise ValueError ( "No elements found in metabolite %s" % metabolite . id )
    for element , amount in iteritems ( metabolite . elements ) :
        reaction_element_dict [ element ] += coefficient * amount
# filter out 0 values
return { k : v for k , v in iteritems ( reaction_element_dict ) if v != 0 }


signature:
def compartments ( self ) :
    """lists compartments the metabolites are in"""

implementation:
if self . _compartments is None :
    self . _compartments = { met . compartment for met in self . _metabolites if met . compartment is not None }
return self . _compartments


signature:
def _associate_gene ( self , cobra_gene ) :
    """Associates a cobra . Gene object with a cobra . Reaction .
 Parameters
 cobra _ gene : cobra . core . Gene . Gene"""

implementation:
self . _genes . add ( cobra_gene )
cobra_gene . _reaction . add ( self )
cobra_gene . _model = self . _model


signature:
def _dissociate_gene ( self , cobra_gene ) :
    """Dissociates a cobra . Gene object with a cobra . Reaction .
 Parameters
 cobra _ gene : cobra . core . Gene . Gene"""

implementation:
self . _genes . discard ( cobra_gene )
cobra_gene . _reaction . discard ( self )


signature:
def build_reaction_from_string ( self , reaction_str , verbose = True , fwd_arrow = None , rev_arrow = None , reversible_arrow = None , term_split = "+" ) :
    """Builds reaction from reaction equation reaction _ str using parser
 Takes a string and using the specifications supplied in the optional
 arguments infers a set of metabolites , metabolite compartments and
 stoichiometries for the reaction . It also infers the reversibility
 of the reaction from the reaction arrow .
 Changes to the associated model are reverted upon exit when using
 the model as a context .
 Parameters
 reaction _ str : string
 a string containing a reaction formula ( equation )
 verbose : bool
 setting verbosity of function
 fwd _ arrow : re . compile
 for forward irreversible reaction arrows
 rev _ arrow : re . compile
 for backward irreversible reaction arrows
 reversible _ arrow : re . compile
 for reversible reaction arrows
 term _ split : string
 dividing individual metabolite entries"""

implementation:
# set the arrows
forward_arrow_finder = _forward_arrow_finder if fwd_arrow is None else re . compile ( re . escape ( fwd_arrow ) )
reverse_arrow_finder = _reverse_arrow_finder if rev_arrow is None else re . compile ( re . escape ( rev_arrow ) )
reversible_arrow_finder = _reversible_arrow_finder if reversible_arrow is None else re . compile ( re . escape ( reversible_arrow ) )
if self . _model is None :
    warn ( "no model found" )
    model = None
else :
    model = self . _model
found_compartments = compartment_finder . findall ( reaction_str )
if len ( found_compartments ) == 1 :
    compartment = found_compartments [ 0 ]
    reaction_str = compartment_finder . sub ( "" , reaction_str )
else :
    compartment = ""
# reversible case
arrow_match = reversible_arrow_finder . search ( reaction_str )
if arrow_match is not None :
    self . lower_bound = - 1000
    self . upper_bound = 1000
else : # irreversible
# try forward
    arrow_match = forward_arrow_finder . search ( reaction_str )
    if arrow_match is not None :
        self . upper_bound = 1000
        self . lower_bound = 0
    else : # must be reverse
        arrow_match = reverse_arrow_finder . search ( reaction_str )
        if arrow_match is None :
            raise ValueError ( "no suitable arrow found in '%s'" % reaction_str )
        else :
            self . upper_bound = 0
            self . lower_bound = - 1000
reactant_str = reaction_str [ : arrow_match . start ( ) ] . strip ( )
product_str = reaction_str [ arrow_match . end ( ) : ] . strip ( )
self . subtract_metabolites ( self . metabolites , combine = True )
for substr , factor in ( ( reactant_str , - 1 ) , ( product_str , 1 ) ) :
    if len ( substr ) == 0 :
        continue
    for term in substr . split ( term_split ) :
        term = term . strip ( )
        if term . lower ( ) == "nothing" :
            continue
        if " " in term :
            num_str , met_id = term . split ( )
            num = float ( num_str . lstrip ( "(" ) . rstrip ( ")" ) ) * factor
        else :
            met_id = term
            num = factor
        met_id += compartment
        try :
            met = model . metabolites . get_by_id ( met_id )
        except KeyError :
            if verbose :
                print ( "unknown metabolite '%s' created" % met_id )
            met = Metabolite ( met_id )
        self . add_metabolites ( { met : num } )


signature:
def _clip ( sid , prefix ) :
    """Clips a prefix from the beginning of a string if it exists ."""

implementation: return sid [ len ( prefix ) : ] if sid . startswith ( prefix ) else sid


signature:
def _f_gene ( sid , prefix = "G_" ) :
    """Clips gene prefix from id ."""

implementation:
sid = sid . replace ( SBML_DOT , "." )
return _clip ( sid , prefix )


signature:
def read_sbml_model ( filename , number = float , f_replace = F_REPLACE , set_missing_bounds = False , ** kwargs ) :
    """Reads 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 .
 Parameters
 filename : path to SBML file , or SBML string , or SBML file handle
 SBML which is read into cobra model
 number : data type of stoichiometry : { float , int }
 In which data type should the stoichiometry be parsed .
 f _ replace : dict of replacement functions for id replacement
 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
 set _ missing _ bounds : boolean flag to set missing bounds
 Missing bounds are set to default bounds in configuration .
 Returns
 cobra . core . Model
 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 ."""

implementation:
try :
    doc = _get_doc_from_filename ( filename )
    return _sbml_to_model ( doc , number = number , f_replace = f_replace , set_missing_bounds = set_missing_bounds , ** kwargs )
except IOError as e :
    raise e
except Exception :
    LOGGER . error ( traceback . print_exc ( ) )
    raise CobraSBMLError ( "Something went wrong reading the SBML model. Most likely the SBML" " model is not valid. Please check that your model is valid using " "the `cobra.io.sbml.validate_sbml_model` function or via the " "online validator at http://sbml.org/validator .\n" "\t`(model, errors) = validate_sbml_model(filename)`" "\nIf the model is valid and cannot be read please open an issue " "at https://github.com/opencobra/cobrapy/issues ." )


signature:
def _get_doc_from_filename ( filename ) :
    """Get SBMLDocument from given filename .
 Parameters
 filename : path to SBML , or SBML string , or filehandle
 Returns
 libsbml . SBMLDocument"""

implementation:
if isinstance ( filename , string_types ) :
    if ( "win" in platform ) and ( len ( filename ) < 260 ) and os . path . exists ( filename ) : # path ( win )
        doc = libsbml . readSBMLFromFile ( filename )
        # noqa : E501 type : libsbml . SBMLDocument
    elif ( "win" not in platform ) and os . path . exists ( filename ) : # path other
        doc = libsbml . readSBMLFromFile ( filename )
        # noqa : E501 type : libsbml . SBMLDocument
    else : # string representation
        if "<sbml" not in filename :
            raise IOError ( "The file with 'filename' does not exist, " "or is not an SBML string. Provide the path to " "an existing SBML file or a valid SBML string " "representation: \n%s" , filename )
        doc = libsbml . readSBMLFromString ( filename )
# noqa : E501 type : libsbml . SBMLDocument
elif hasattr ( filename , "read" ) : # file handle
    doc = libsbml . readSBMLFromString ( filename . read ( ) )
    # noqa : E501 type : libsbml . SBMLDocument
else :
    raise CobraSBMLError ( "Input type '%s' for 'filename' is not supported." " Provide a path, SBML str, " "or file handle." , type ( filename ) )
return doc


signature:
def write_sbml_model ( cobra_model , filename , f_replace = F_REPLACE , ** kwargs ) :
    """Writes 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 " .
 Parameters
 cobra _ model : cobra . core . Model
 Model instance which is written to SBML
 filename : string
 path to which the model is written
 use _ fbc _ package : boolean { True , False }
 should the fbc package be used
 f _ replace : dict of replacement functions for id replacement"""

implementation:
doc = _model_to_sbml ( cobra_model , f_replace = f_replace , ** kwargs )
if isinstance ( filename , string_types ) : # write to path
    libsbml . writeSBMLToFile ( doc , filename )
elif hasattr ( filename , "write" ) : # write to file handle
    sbml_str = libsbml . writeSBMLToString ( doc )
    filename . write ( sbml_str )


signature:
def _model_to_sbml ( cobra_model , f_replace = None , units = True ) :
    """Convert Cobra model to SBMLDocument .
 Parameters
 cobra _ model : cobra . core . Model
 Cobra model instance
 f _ replace : dict of replacement functions
 Replacement to apply on identifiers .
 units : boolean
 Should the FLUX _ UNITS be written in the SBMLDocument .
 Returns
 libsbml . SBMLDocument"""

implementation:
if f_replace is None :
    f_replace = { }
sbml_ns = libsbml . SBMLNamespaces ( 3 , 1 )
# SBML L3V1
sbml_ns . addPackageNamespace ( "fbc" , 2 )
# fbc - v2
doc = libsbml . SBMLDocument ( sbml_ns )
# noqa : E501 type : libsbml . SBMLDocument
doc . setPackageRequired ( "fbc" , False )
doc . setSBOTerm ( SBO_FBA_FRAMEWORK )
model = doc . createModel ( )
# type : libsbml . Model
model_fbc = model . getPlugin ( "fbc" )
# type : libsbml . FbcModelPlugin
model_fbc . setStrict ( True )
if cobra_model . id is not None :
    model . setId ( cobra_model . id )
    model . setMetaId ( "meta_" + cobra_model . id )
else :
    model . setMetaId ( "meta_model" )
if cobra_model . name is not None :
    model . setName ( cobra_model . name )
_sbase_annotations ( model , cobra_model . annotation )
# Meta information ( ModelHistory )
if hasattr ( cobra_model , "_sbml" ) :
    meta = cobra_model . _sbml
    if "annotation" in meta :
        _sbase_annotations ( doc , meta [ "annotation" ] )
    if "notes" in meta :
        _sbase_notes_dict ( doc , meta [ "notes" ] )
    history = libsbml . ModelHistory ( )
    # type : libsbml . ModelHistory
    if "created" in meta and meta [ "created" ] :
        history . setCreatedDate ( meta [ "created" ] )
    else :
        time = datetime . datetime . now ( )
        timestr = time . strftime ( '%Y-%m-%dT%H:%M:%S' )
        date = libsbml . Date ( timestr )
        _check ( history . setCreatedDate ( date ) , 'set creation date' )
        _check ( history . setModifiedDate ( date ) , 'set modified date' )
    if "creators" in meta :
        for cobra_creator in meta [ "creators" ] :
            creator = libsbml . ModelCreator ( )
            # noqa : E501 type : libsbml . ModelCreator
            if cobra_creator . get ( "familyName" , None ) :
                creator . setFamilyName ( cobra_creator [ "familyName" ] )
            if cobra_creator . get ( "givenName" , None ) :
                creator . setGivenName ( cobra_creator [ "givenName" ] )
            if cobra_creator . get ( "organisation" , None ) :
                creator . setOrganisation ( cobra_creator [ "organisation" ] )
            if cobra_creator . get ( "email" , None ) :
                creator . setEmail ( cobra_creator [ "email" ] )
            _check ( history . addCreator ( creator ) , "adding creator to ModelHistory." )
    _check ( model . setModelHistory ( history ) , 'set model history' )
# Units
if units :
    flux_udef = model . createUnitDefinition ( )
    # noqa : E501 type : libsbml . UnitDefinition
    flux_udef . setId ( UNITS_FLUX [ 0 ] )
    for u in UNITS_FLUX [ 1 ] :
        unit = flux_udef . createUnit ( )
        # type : libsbml . Unit
        unit . setKind ( u . kind )
        unit . setExponent ( u . exponent )
        unit . setScale ( u . scale )
        unit . setMultiplier ( u . multiplier )
# minimum and maximum value from model
if len ( cobra_model . reactions ) > 0 :
    min_value = min ( cobra_model . reactions . list_attr ( "lower_bound" ) )
    max_value = max ( cobra_model . reactions . list_attr ( "upper_bound" ) )
else :
    min_value = config . lower_bound
    max_value = config . upper_bound
_create_parameter ( model , pid = LOWER_BOUND_ID , value = min_value , sbo = SBO_DEFAULT_FLUX_BOUND )
_create_parameter ( model , pid = UPPER_BOUND_ID , value = max_value , sbo = SBO_DEFAULT_FLUX_BOUND )
_create_parameter ( model , pid = ZERO_BOUND_ID , value = 0 , sbo = SBO_DEFAULT_FLUX_BOUND )
_create_parameter ( model , pid = BOUND_MINUS_INF , value = - float ( "Inf" ) , sbo = SBO_FLUX_BOUND )
_create_parameter ( model , pid = BOUND_PLUS_INF , value = float ( "Inf" ) , sbo = SBO_FLUX_BOUND )
# Compartments
# FIXME : use first class compartment model ( and write notes & annotations )
# ( https : / / github . com / opencobra / cobrapy / issues / 811)
for cid , name in iteritems ( cobra_model . compartments ) :
    compartment = model . createCompartment ( )
    # type : libsbml . Compartment
    compartment . setId ( cid )
    compartment . setName ( name )
    compartment . setConstant ( True )
    # FIXME : write annotations and notes
    # _ sbase _ notes ( c , com . notes )
    # _ sbase _ annotations ( c , com . annotation )
# Species
for metabolite in cobra_model . metabolites :
    specie = model . createSpecies ( )
    # type : libsbml . Species
    mid = metabolite . id
    if f_replace and F_SPECIE_REV in f_replace :
        mid = f_replace [ F_SPECIE_REV ] ( mid )
    specie . setId ( mid )
    specie . setConstant ( False )
    specie . setBoundaryCondition ( False )
    specie . setHasOnlySubstanceUnits ( False )
    specie . setName ( metabolite . name )
    specie . setCompartment ( metabolite . compartment )
    s_fbc = specie . getPlugin ( "fbc" )
    # type : libsbml . FbcSpeciesPlugin
    if metabolite . charge is not None :
        s_fbc . setCharge ( metabolite . charge )
    if metabolite . formula is not None :
        s_fbc . setChemicalFormula ( metabolite . formula )
    _sbase_annotations ( specie , metabolite . annotation )
    _sbase_notes_dict ( specie , metabolite . notes )
# Genes
for cobra_gene in cobra_model . genes :
    gp = model_fbc . createGeneProduct ( )
    # type : libsbml . GeneProduct
    gid = cobra_gene . id
    if f_replace and F_GENE_REV in f_replace :
        gid = f_replace [ F_GENE_REV ] ( gid )
    gp . setId ( gid )
    gname = cobra_gene . name
    if gname is None or len ( gname ) == 0 :
        gname = gid
    gp . setName ( gname )
    gp . setLabel ( gid )
    _sbase_annotations ( gp , cobra_gene . annotation )
    _sbase_notes_dict ( gp , cobra_gene . notes )
# Objective
objective = model_fbc . createObjective ( )
# type : libsbml . Objective
objective . setId ( "obj" )
objective . setType ( SHORT_LONG_DIRECTION [ cobra_model . objective . direction ] )
model_fbc . setActiveObjectiveId ( "obj" )
# Reactions
reaction_coefficients = linear_reaction_coefficients ( cobra_model )
for cobra_reaction in cobra_model . reactions :
    rid = cobra_reaction . id
    if f_replace and F_REACTION_REV in f_replace :
        rid = f_replace [ F_REACTION_REV ] ( rid )
    reaction = model . createReaction ( )
    # type : libsbml . Reaction
    reaction . setId ( rid )
    reaction . setName ( cobra_reaction . name )
    reaction . setFast ( False )
    reaction . setReversible ( ( cobra_reaction . lower_bound < 0 ) )
    _sbase_annotations ( reaction , cobra_reaction . annotation )
    _sbase_notes_dict ( reaction , cobra_reaction . notes )
    # stoichiometry
    for metabolite , stoichiometry in iteritems ( cobra_reaction . _metabolites ) : # noqa : E501
        sid = metabolite . id
        if f_replace and F_SPECIE_REV in f_replace :
            sid = f_replace [ F_SPECIE_REV ] ( sid )
        if stoichiometry < 0 :
            sref = reaction . createReactant ( )
            # noqa : E501 type : libsbml . SpeciesReference
            sref . setSpecies ( sid )
            sref . setStoichiometry ( - stoichiometry )
            sref . setConstant ( True )
        else :
            sref = reaction . createProduct ( )
            # noqa : E501 type : libsbml . SpeciesReference
            sref . setSpecies ( sid )
            sref . setStoichiometry ( stoichiometry )
            sref . setConstant ( True )
    # bounds
    r_fbc = reaction . getPlugin ( "fbc" )
    # type : libsbml . FbcReactionPlugin
    r_fbc . setLowerFluxBound ( _create_bound ( model , cobra_reaction , "lower_bound" , f_replace = f_replace , units = units , flux_udef = flux_udef ) )
    r_fbc . setUpperFluxBound ( _create_bound ( model , cobra_reaction , "upper_bound" , f_replace = f_replace , units = units , flux_udef = flux_udef ) )
    # GPR
    gpr = cobra_reaction . gene_reaction_rule
    if gpr is not None and len ( gpr ) > 0 : # replace ids in string
        if f_replace and F_GENE_REV in f_replace :
            gpr = gpr . replace ( '(' , '( ' )
            gpr = gpr . replace ( ')' , ' )' )
            tokens = gpr . split ( ' ' )
            for k in range ( len ( tokens ) ) :
                if tokens [ k ] not in [ ' ' , 'and' , 'or' , '(' , ')' ] :
                    tokens [ k ] = f_replace [ F_GENE_REV ] ( tokens [ k ] )
            gpr_new = " " . join ( tokens )
        gpa = r_fbc . createGeneProductAssociation ( )
        # noqa : E501 type : libsbml . GeneProductAssociation
        gpa . setAssociation ( gpr_new )
    # objective coefficients
    if reaction_coefficients . get ( cobra_reaction , 0 ) != 0 :
        flux_obj = objective . createFluxObjective ( )
        # noqa : E501 type : libsbml . FluxObjective
        flux_obj . setReaction ( rid )
        flux_obj . setCoefficient ( cobra_reaction . objective_coefficient )
# write groups
if len ( cobra_model . groups ) > 0 :
    doc . enablePackage ( "http://www.sbml.org/sbml/level3/version1/groups/version1" , "groups" , True )
    doc . setPackageRequired ( "groups" , False )
    model_group = model . getPlugin ( "groups" )
    # noqa : E501 type : libsbml . GroupsModelPlugin
    for cobra_group in cobra_model . groups :
        group = model_group . createGroup ( )
        # type : libsbml . Group
        group . setId ( cobra_group . id )
        group . setName ( cobra_group . name )
        group . setKind ( cobra_group . kind )
        _sbase_notes_dict ( group , cobra_group . notes )
        _sbase_annotations ( group , cobra_group . annotation )
        for cobra_member in cobra_group . members :
            member = group . createMember ( )
            # type : libsbml . Member
            mid = cobra_member . id
            m_type = str ( type ( cobra_member ) )
            # id replacements
            if "Reaction" in m_type :
                if f_replace and F_REACTION_REV in f_replace :
                    mid = f_replace [ F_REACTION_REV ] ( mid )
            if "Metabolite" in m_type :
                if f_replace and F_SPECIE_REV in f_replace :
                    mid = f_replace [ F_SPECIE_REV ] ( mid )
            if "Gene" in m_type :
                if f_replace and F_GENE_REV in f_replace :
                    mid = f_replace [ F_GENE_REV ] ( mid )
            member . setIdRef ( mid )
            if cobra_member . name and len ( cobra_member . name ) > 0 :
                member . setName ( cobra_member . name )
return doc


signature:
def _create_bound ( model , reaction , bound_type , f_replace , units = None , flux_udef = None ) :
    """Creates bound in model for given reaction .
 Adds the parameters for the bounds to the SBML model .
 Parameters
 model : libsbml . Model
 SBML model instance
 reaction : cobra . core . Reaction
 Cobra reaction instance from which the bounds are read .
 bound _ type : { LOWER _ BOUND , UPPER _ BOUND }
 Type of bound
 f _ replace : dict of id replacement functions
 units : flux units
 Returns
 Id of bound parameter ."""

implementation:
value = getattr ( reaction , bound_type )
if value == config . lower_bound :
    return LOWER_BOUND_ID
elif value == 0 :
    return ZERO_BOUND_ID
elif value == config . upper_bound :
    return UPPER_BOUND_ID
elif value == - float ( "Inf" ) :
    return BOUND_MINUS_INF
elif value == float ( "Inf" ) :
    return BOUND_PLUS_INF
else : # new parameter
    rid = reaction . id
    if f_replace and F_REACTION_REV in f_replace :
        rid = f_replace [ F_REACTION_REV ] ( rid )
    pid = rid + "_" + bound_type
    _create_parameter ( model , pid = pid , value = value , sbo = SBO_FLUX_BOUND , units = units , flux_udef = flux_udef )
    return pid


signature:
def _create_parameter ( model , pid , value , sbo = None , constant = True , units = None , flux_udef = None ) :
    """Create parameter in SBML model ."""

implementation:
parameter = model . createParameter ( )
# type : libsbml . Parameter
parameter . setId ( pid )
parameter . setValue ( value )
parameter . setConstant ( constant )
if sbo :
    parameter . setSBOTerm ( sbo )
if units :
    parameter . setUnits ( flux_udef . getId ( ) )


signature:
def _check_required ( sbase , value , attribute ) :
    """Get required attribute from SBase .
 Parameters
 sbase : libsbml . SBase
 value : existing value
 attribute : name of attribute
 Returns
 attribute value ( or value if already set )"""

implementation:
if ( value is None ) or ( value == "" ) :
    msg = "Required attribute '%s' cannot be found or parsed in '%s'" % ( attribute , sbase )
    if hasattr ( sbase , "getId" ) and sbase . getId ( ) :
        msg += " with id '%s'" % sbase . getId ( )
    elif hasattr ( sbase , "getName" ) and sbase . getName ( ) :
        msg += " with name '%s'" % sbase . getName ( )
    elif hasattr ( sbase , "getMetaId" ) and sbase . getMetaId ( ) :
        msg += " with metaId '%s'" % sbase . getName ( )
    raise CobraSBMLError ( msg )
return value


signature:
def _check ( value , message ) :
    """Checks the libsbml return value and logs error messages .
 If ' value ' is None , 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."""

implementation:
if value is None :
    LOGGER . error ( 'Error: LibSBML returned a null value trying ' 'to <' + message + '>.' )
elif type ( value ) is int :
    if value == libsbml . LIBSBML_OPERATION_SUCCESS :
        return
    else :
        LOGGER . error ( 'Error encountered trying to <' + message + '>.' )
        LOGGER . error ( 'LibSBML error code {}: {}' . format ( str ( value ) , libsbml . OperationReturnValue_toString ( value ) . strip ( ) ) )
else :
    return


signature:
def _parse_notes_dict ( sbase ) :
    """Creates dictionary of COBRA notes .
 Parameters
 sbase : libsbml . SBase
 Returns
 dict of notes"""

implementation:
notes = sbase . getNotesString ( )
if notes and len ( notes ) > 0 :
    pattern = r"<p>\s*(\w+\s*\w*)\s*:\s*([\w|\s]+)<"
    matches = re . findall ( pattern , notes )
    d = { k . strip ( ) : v . strip ( ) for ( k , v ) in matches }
    return { k : v for k , v in d . items ( ) if len ( v ) > 0 }
else :
    return { }


signature:
def _sbase_notes_dict ( sbase , notes ) :
    """Set SBase notes based on dictionary .
 Parameters
 sbase : libsbml . SBase
 SBML object to set notes on
 notes : notes object
 notes information from cobra object"""

implementation:
if notes and len ( notes ) > 0 :
    tokens = [ '' ] + [ "
{}: {}
" . format ( k , v ) for ( k , v ) in notes . items ( ) ] + [ "" ]
    _check ( sbase . setNotes ( "\n" . join ( tokens ) ) , "Setting notes on sbase: {}" . format ( sbase ) )


signature:
def _parse_annotations ( sbase ) :
    """Parses cobra annotations from a given SBase object .
 Annotations are dictionaries with the providers as keys .
 Parameters
 sbase : libsbml . SBase
 SBase from which the SBML annotations are read
 Returns
 dict ( annotation dictionary )
 FIXME : annotation format must be updated ( this is a big collection of
 fixes ) - see : https : / / github . com / opencobra / cobrapy / issues / 684)"""

implementation:
annotation = { }
# SBO term
if sbase . isSetSBOTerm ( ) : # FIXME : correct handling of annotations
    annotation [ "sbo" ] = sbase . getSBOTermID ( )
# RDF annotation
cvterms = sbase . getCVTerms ( )
if cvterms is None :
    return annotation
for cvterm in cvterms : # type : libsbml . CVTerm
    for k in range ( cvterm . getNumResources ( ) ) : # FIXME : read and store the qualifier
        uri = cvterm . getResourceURI ( k )
        match = URL_IDENTIFIERS_PATTERN . match ( uri )
        if not match :
            LOGGER . warning ( "%s does not conform to " "http(s)://identifiers.org/collection/id" , uri )
            continue
        provider , identifier = match . group ( 1 ) , match . group ( 2 )
        if provider in annotation :
            if isinstance ( annotation [ provider ] , string_types ) :
                annotation [ provider ] = [ annotation [ provider ] ]
            # FIXME : use a list
            if identifier not in annotation [ provider ] :
                annotation [ provider ] . append ( identifier )
        else : # FIXME : always in list
            annotation [ provider ] = identifier
return annotation


signature:
def _sbase_annotations ( sbase , annotation ) :
    """Set SBase annotations based on cobra annotations .
 Parameters
 sbase : libsbml . SBase
 SBML object to annotate
 annotation : cobra annotation structure
 cobra object with annotation information
 FIXME : annotation format must be updated
 ( https : / / github . com / opencobra / cobrapy / issues / 684)"""

implementation:
if not annotation or len ( annotation ) == 0 :
    return
# standardize annotations
annotation_data = deepcopy ( annotation )
for key , value in annotation_data . items ( ) : # handling of non - string annotations ( e . g . integers )
    if isinstance ( value , ( float , int ) ) :
        value = str ( value )
    if isinstance ( value , string_types ) :
        annotation_data [ key ] = [ ( "is" , value ) ]
for key , value in annotation_data . items ( ) :
    for idx , item in enumerate ( value ) :
        if isinstance ( item , string_types ) :
            value [ idx ] = ( "is" , item )
# set metaId
meta_id = "meta_{}" . format ( sbase . getId ( ) )
sbase . setMetaId ( meta_id )
# rdf _ items = [ ]
for provider , data in iteritems ( annotation_data ) : # set SBOTerm
    if provider in [ "SBO" , "sbo" ] :
        if provider == "SBO" :
            LOGGER . warning ( "'SBO' provider is deprecated, " "use 'sbo' provider instead" )
        sbo_term = data [ 0 ] [ 1 ]
        _check ( sbase . setSBOTerm ( sbo_term ) , "Setting SBOTerm: {}" . format ( sbo_term ) )
        # FIXME : sbo should also be written as CVTerm
        continue
    for item in data :
        qualifier_str , entity = item [ 0 ] , item [ 1 ]
        qualifier = QUALIFIER_TYPES . get ( qualifier_str , None )
        if qualifier is None :
            qualifier = libsbml . BQB_IS
            LOGGER . error ( "Qualifier type is not supported on " "annotation: '{}'" . format ( qualifier_str ) )
        qualifier_type = libsbml . BIOLOGICAL_QUALIFIER
        if qualifier_str . startswith ( "bqm_" ) :
            qualifier_type = libsbml . MODEL_QUALIFIER
        cv = libsbml . CVTerm ( )
        # type : libsbml . CVTerm
        cv . setQualifierType ( qualifier_type )
        if qualifier_type == libsbml . BIOLOGICAL_QUALIFIER :
            cv . setBiologicalQualifierType ( qualifier )
        elif qualifier_type == libsbml . MODEL_QUALIFIER :
            cv . setModelQualifierType ( qualifier )
        else :
            raise CobraSBMLError ( 'Unsupported qualifier: ' '%s' % qualifier )
        resource = "%s/%s/%s" % ( URL_IDENTIFIERS_PREFIX , provider , entity )
        cv . addResource ( resource )
        _check ( sbase . addCVTerm ( cv ) , "Setting cvterm: {}, resource: {}" . format ( cv , resource ) )


signature:
def validate_sbml_model ( filename , check_model = True , internal_consistency = True , check_units_consistency = False , check_modeling_practice = False , ** kwargs ) :
    """Validate SBML model and returns the model along with a list of errors .
 Parameters
 filename : str
 The filename ( or SBML string ) of the SBML model to be validated .
 internal _ consistency : boolean { True , False }
 Check internal consistency .
 check _ units _ consistency : boolean { True , False }
 Check consistency of units .
 check _ modeling _ practice : boolean { True , False }
 Check modeling practise .
 check _ model : boolean { True , False }
 Whether to also check some basic model properties such as reaction
 boundaries and compartment formulas .
 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 .
 Raises
 CobraSBMLError"""

implementation:
# Errors and warnings are grouped based on their type . SBML _ * types are
# from the libsbml validator . COBRA _ * types are from the cobrapy SBML
# parser .
keys = ( "SBML_FATAL" , "SBML_ERROR" , "SBML_SCHEMA_ERROR" , "SBML_WARNING" , "COBRA_FATAL" , "COBRA_ERROR" , "COBRA_WARNING" , "COBRA_CHECK" , )
errors = { key : [ ] for key in keys }
# [1 ] libsbml validation
doc = _get_doc_from_filename ( filename )
# type : libsbml . SBMLDocument
# set checking of units & modeling practise
doc . setConsistencyChecks ( libsbml . LIBSBML_CAT_UNITS_CONSISTENCY , check_units_consistency )
doc . setConsistencyChecks ( libsbml . LIBSBML_CAT_MODELING_PRACTICE , check_modeling_practice )
# check internal consistency
if internal_consistency :
    doc . checkInternalConsistency ( )
doc . checkConsistency ( )
for k in range ( doc . getNumErrors ( ) ) :
    e = doc . getError ( k )
    # type : libsbml . SBMLError
    msg = _error_string ( e , k = k )
    sev = e . getSeverity ( )
    if sev == libsbml . LIBSBML_SEV_FATAL :
        errors [ "SBML_FATAL" ] . append ( msg )
    elif sev == libsbml . LIBSBML_SEV_ERROR :
        errors [ "SBML_ERROR" ] . append ( msg )
    elif sev == libsbml . LIBSBML_SEV_SCHEMA_ERROR :
        errors [ "SBML_SCHEMA_ERROR" ] . append ( msg )
    elif sev == libsbml . LIBSBML_SEV_WARNING :
        errors [ "SBML_WARNING" ] . append ( msg )
# [2 ] cobrapy validation ( check that SBML can be read into model )
# all warnings generated while loading will be logged as errors
log_stream = StringIO ( )
stream_handler = logging . StreamHandler ( log_stream )
formatter = logging . Formatter ( '%(levelname)s:%(message)s' )
stream_handler . setFormatter ( formatter )
stream_handler . setLevel ( logging . INFO )
LOGGER . addHandler ( stream_handler )
LOGGER . propagate = False
try : # read model and allow additional parser arguments
    model = _sbml_to_model ( doc , ** kwargs )
except CobraSBMLError as e :
    errors [ "COBRA_ERROR" ] . append ( str ( e ) )
    return None , errors
except Exception as e :
    errors [ "COBRA_FATAL" ] . append ( str ( e ) )
    return None , errors
cobra_errors = log_stream . getvalue ( ) . split ( "\n" )
for cobra_error in cobra_errors :
    tokens = cobra_error . split ( ":" )
    error_type = tokens [ 0 ]
    error_msg = ":" . join ( tokens [ 1 : ] )
    if error_type == "WARNING" :
        errors [ "COBRA_WARNING" ] . append ( error_msg )
    elif error_type == "ERROR" :
        errors [ "COBRA_ERROR" ] . append ( error_msg )
# remove stream handler
LOGGER . removeHandler ( stream_handler )
LOGGER . propagate = True
# [3 ] additional model tests
if check_model :
    errors [ "COBRA_CHECK" ] . extend ( check_metabolite_compartment_formula ( model ) )
for key in [ "SBML_FATAL" , "SBML_ERROR" , "SBML_SCHEMA_ERROR" ] :
    if len ( errors [ key ] ) > 0 :
        LOGGER . error ( "SBML errors in validation, check error log " "for details." )
        break
for key in [ "SBML_WARNING" ] :
    if len ( errors [ key ] ) > 0 :
        LOGGER . error ( "SBML warnings in validation, check error log " "for details." )
        break
for key in [ "COBRA_FATAL" , "COBRA_ERROR" ] :
    if len ( errors [ key ] ) > 0 :
        LOGGER . error ( "COBRA errors in validation, check error log " "for details." )
        break
for key in [ "COBRA_WARNING" , "COBRA_CHECK" ] :
    if len ( errors [ key ] ) > 0 :
        LOGGER . error ( "COBRA warnings in validation, check error log " "for details." )
        break
return model , errors


signature:
def _error_string ( error , k = None ) :
    """String representation of SBMLError .
 Parameters
 error : libsbml . SBMLError
 k : index of error
 Returns
 string representation of error"""

implementation:
package = error . getPackage ( )
if package == '' :
    package = 'core'
template = 'E{} ({}): {} ({}, L{}); {}; {}'
error_str = template . format ( k , error . getSeverityAsString ( ) , error . getCategoryAsString ( ) , package , error . getLine ( ) , error . getShortMessage ( ) , error . getMessage ( ) )
return error_str


signature:
def production_envelope ( model , reactions , objective = None , carbon_sources = None , points = 20 , threshold = None ) :
    """Calculate the objective value conditioned on all combinations of
 fluxes for a set of chosen reactions
 The production envelope can be used to analyze a model ' s ability to
 produce a given compound conditional on the fluxes for another set of
 reactions , such as the uptake rates . The model is alternately optimized
 with respect to minimizing and maximizing the objective and the
 obtained fluxes are recorded . Ranges to compute production is set to the
 effective
 bounds , i . e . , the minimum / maximum fluxes that can be obtained given
 current reaction bounds .
 Parameters
 model : cobra . Model
 The model to compute the production envelope for .
 reactions : list or string
 A list of reactions , reaction identifiers or a single reaction .
 objective : string , dict , model . solver . interface . Objective , optional
 The objective ( reaction ) to use for the production envelope . Use the
 model ' s current objective if left missing .
 carbon _ sources : list or string , optional
 One or more reactions or reaction identifiers that are the source of
 carbon for computing carbon ( mol carbon in output over mol carbon in
 input ) and mass yield ( gram product over gram output ) . Only objectives
 with a carbon containing input and output metabolite is supported .
 Will identify active carbon sources in the medium if none are specified .
 points : int , optional
 The number of points to calculate production for .
 threshold : float , optional
 A cut - off under which flux values will be considered to be zero
 ( default model . tolerance ) .
 Returns
 pandas . DataFrame
 A data frame with one row per evaluated point and
 - reaction id : one column per input reaction indicating the flux at
 each given point ,
 - carbon _ source : identifiers of carbon exchange reactions
 A column for the maximum and minimum each for the following types :
 - flux : the objective flux
 - carbon _ yield : if carbon source is defined and the product is a
 single metabolite ( mol carbon product per mol carbon feeding source )
 - mass _ yield : if carbon source is defined and the product is a
 single metabolite ( gram product per 1 g of feeding source )
 Examples
 > > > import cobra . test
 > > > from cobra . flux _ analysis import production _ envelope
 > > > model = cobra . test . create _ test _ model ( " textbook " )
 > > > production _ envelope ( model , [ " EX _ glc _ _ D _ e " , " EX _ o2 _ e " ] )"""

implementation:
reactions = model . reactions . get_by_any ( reactions )
objective = model . solver . objective if objective is None else objective
data = dict ( )
if carbon_sources is None :
    c_input = find_carbon_sources ( model )
else :
    c_input = model . reactions . get_by_any ( carbon_sources )
if c_input is None :
    data [ 'carbon_source' ] = None
elif hasattr ( c_input , 'id' ) :
    data [ 'carbon_source' ] = c_input . id
else :
    data [ 'carbon_source' ] = ', ' . join ( rxn . id for rxn in c_input )
threshold = normalize_cutoff ( model , threshold )
size = points ** len ( reactions )
for direction in ( 'minimum' , 'maximum' ) :
    data [ 'flux_{}' . format ( direction ) ] = full ( size , nan , dtype = float )
    data [ 'carbon_yield_{}' . format ( direction ) ] = full ( size , nan , dtype = float )
    data [ 'mass_yield_{}' . format ( direction ) ] = full ( size , nan , dtype = float )
grid = pd . DataFrame ( data )
with model :
    model . objective = objective
    objective_reactions = list ( sutil . linear_reaction_coefficients ( model ) )
    if len ( objective_reactions ) != 1 :
        raise ValueError ( 'cannot calculate yields for objectives with ' 'multiple reactions' )
    c_output = objective_reactions [ 0 ]
    min_max = fva ( model , reactions , fraction_of_optimum = 0 )
    min_max [ min_max . abs ( ) < threshold ] = 0.0
    points = list ( product ( * [ linspace ( min_max . at [ rxn . id , "minimum" ] , min_max . at [ rxn . id , "maximum" ] , points , endpoint = True ) for rxn in reactions ] ) )
    tmp = pd . DataFrame ( points , columns = [ rxn . id for rxn in reactions ] )
    grid = pd . concat ( [ grid , tmp ] , axis = 1 , copy = False )
    add_envelope ( model , reactions , grid , c_input , c_output , threshold )
return grid


signature:
def total_yield ( input_fluxes , input_elements , output_flux , output_elements ) :
    """Compute total output per input unit .
 Units are typically mol carbon atoms or gram of source and product .
 Parameters
 input _ fluxes : list
 A list of input reaction fluxes in the same order as the
 ` ` input _ components ` ` .
 input _ elements : list
 A list of reaction components which are in turn list of numbers .
 output _ flux : float
 The output flux value .
 output _ elements : list
 A list of stoichiometrically weighted output reaction components .
 Returns
 float
 The ratio between output ( mol carbon atoms or grams of product ) and
 input ( mol carbon atoms or grams of source compounds ) ."""

implementation:
carbon_input_flux = sum ( total_components_flux ( flux , components , consumption = True ) for flux , components in zip ( input_fluxes , input_elements ) )
carbon_output_flux = total_components_flux ( output_flux , output_elements , consumption = False )
try :
    return carbon_output_flux / carbon_input_flux
except ZeroDivisionError :
    return nan


signature:
def reaction_elements ( reaction ) :
    """Split metabolites into the atoms times their stoichiometric coefficients .
 Parameters
 reaction : Reaction
 The metabolic reaction whose components are desired .
 Returns
 list
 Each of the reaction ' s metabolites ' desired carbon elements ( if any )
 times that metabolite ' s stoichiometric coefficient ."""

implementation:
c_elements = [ coeff * met . elements . get ( 'C' , 0 ) for met , coeff in iteritems ( reaction . metabolites ) ]
return [ elem for elem in c_elements if elem != 0 ]


signature:
def reaction_weight ( reaction ) :
    """Return the metabolite weight times its stoichiometric coefficient ."""

implementation:
if len ( reaction . metabolites ) != 1 :
    raise ValueError ( 'Reaction weight is only defined for single ' 'metabolite products or educts.' )
met , coeff = next ( iteritems ( reaction . metabolites ) )
return [ coeff * met . formula_weight ]


signature:
def total_components_flux ( flux , components , consumption = True ) :
    """Compute the total components consumption or production flux .
 Parameters
 flux : float
 The reaction flux for the components .
 components : list
 List of stoichiometrically weighted components .
 consumption : bool , optional
 Whether to sum up consumption or production fluxes ."""

implementation:
direction = 1 if consumption else - 1
c_flux = [ elem * flux * direction for elem in components ]
return sum ( [ flux for flux in c_flux if flux > 0 ] )


signature:
def find_carbon_sources ( model ) :
    """Find all active carbon source reactions .
 Parameters
 model : Model
 A genome - scale metabolic model .
 Returns
 list
 The medium reactions with carbon input flux ."""

implementation:
try :
    model . slim_optimize ( error_value = None )
except OptimizationError :
    return [ ]
reactions = model . reactions . get_by_any ( list ( model . medium ) )
reactions_fluxes = [ ( rxn , total_components_flux ( rxn . flux , reaction_elements ( rxn ) , consumption = True ) ) for rxn in reactions ]
return [ rxn for rxn , c_flux in reactions_fluxes if c_flux > 0 ]


signature:
def assess ( model , reaction , flux_coefficient_cutoff = 0.001 , solver = None ) :
    """Assesses production capacity .
 Assesses the capacity of the model to produce the precursors for the
 reaction and absorb the production of the reaction while the reaction is
 operating at , or above , the specified cutoff .
 Parameters
 model : cobra . Model
 The cobra model to assess production capacity for
 reaction : reaction identifier or cobra . Reaction
 The reaction to assess
 flux _ coefficient _ cutoff : float
 The minimum flux that reaction must carry to be considered active .
 solver : basestring
 Solver name . If None , the default solver will be used .
 Returns
 bool or dict
 True if the model can produce the precursors and absorb the products
 for the reaction operating at , or above , flux _ coefficient _ cutoff .
 Otherwise , a dictionary of { ' precursor ' : Status , ' product ' : Status } .
 Where Status is the results from assess _ precursors and
 assess _ products , respectively ."""

implementation:
reaction = model . reactions . get_by_any ( reaction ) [ 0 ]
with model as m :
    m . objective = reaction
    if _optimize_or_value ( m , solver = solver ) >= flux_coefficient_cutoff :
        return True
    else :
        results = dict ( )
        results [ 'precursors' ] = assess_component ( model , reaction , 'reactants' , flux_coefficient_cutoff )
        results [ 'products' ] = assess_component ( model , reaction , 'products' , flux_coefficient_cutoff )
        return results


signature:
def assess_component ( model , reaction , side , flux_coefficient_cutoff = 0.001 , solver = None ) :
    """Assesses the ability of the model to provide sufficient precursors ,
 or absorb products , for a reaction operating at , or beyond ,
 the specified cutoff .
 Parameters
 model : cobra . Model
 The cobra model to assess production capacity for
 reaction : reaction identifier or cobra . Reaction
 The reaction to assess
 side : basestring
 Side of the reaction , ' products ' or ' reactants '
 flux _ coefficient _ cutoff : float
 The minimum flux that reaction must carry to be considered active .
 solver : basestring
 Solver name . If None , the default solver will be used .
 Returns
 bool or dict
 True if the precursors can be simultaneously produced at the
 specified cutoff . False , if the model has the capacity to produce
 each individual precursor at the specified threshold but not all
 precursors at the required level simultaneously . Otherwise a
 dictionary of the required and the produced fluxes for each reactant
 that is not produced in sufficient quantities ."""

implementation:
reaction = model . reactions . get_by_any ( reaction ) [ 0 ]
result_key = dict ( reactants = 'produced' , products = 'capacity' ) [ side ]
get_components = attrgetter ( side )
with model as m :
    m . objective = reaction
    if _optimize_or_value ( m , solver = solver ) >= flux_coefficient_cutoff :
        return True
    simulation_results = { }
    # build the demand reactions and add all at once
    demand_reactions = { }
    for component in get_components ( reaction ) :
        coeff = reaction . metabolites [ component ]
        demand = m . add_boundary ( component , type = 'demand' )
        demand . metabolites [ component ] = coeff
        demand_reactions [ demand ] = ( component , coeff )
    # First assess whether all precursors can be produced simultaneously
    joint_demand = Reaction ( "joint_demand" )
    for demand_reaction in demand_reactions :
        joint_demand += demand_reaction
    m . add_reactions ( [ joint_demand ] )
    m . objective = joint_demand
    if _optimize_or_value ( m , solver = solver ) >= flux_coefficient_cutoff :
        return True
    # Otherwise assess the ability of the model to produce each precursor
    # individually . Now assess the ability of the model to produce each
    # reactant for a reaction
    for demand_reaction , ( component , coeff ) in iteritems ( demand_reactions ) : # Calculate the maximum amount of the
        with m :
            m . objective = demand_reaction
            flux = _optimize_or_value ( m , solver = solver )
        # metabolite that can be produced .
        if flux_coefficient_cutoff > flux : # Scale the results to a single unit
            simulation_results . update ( { component : { 'required' : flux_coefficient_cutoff / abs ( coeff ) , result_key : flux / abs ( coeff ) } } )
    if len ( simulation_results ) == 0 :
        simulation_results = False
    return simulation_results


signature:
def assess_precursors ( model , reaction , flux_coefficient_cutoff = 0.001 , solver = None ) :
    """Assesses the ability of the model to provide sufficient precursors for
 a reaction operating at , or beyond , the specified cutoff .
 Deprecated : use assess _ component instead
 Parameters
 model : cobra . Model
 The cobra model to assess production capacity for
 reaction : reaction identifier or cobra . Reaction
 The reaction to assess
 flux _ coefficient _ cutoff : float
 The minimum flux that reaction must carry to be considered active .
 solver : basestring
 Solver name . If None , the default solver will be used .
 Returns
 bool or dict
 True if the precursors can be simultaneously produced at the
 specified cutoff . False , if the model has the capacity to produce
 each individual precursor at the specified threshold but not all
 precursors at the required level simultaneously . Otherwise a
 dictionary of the required and the produced fluxes for each reactant
 that is not produced in sufficient quantities ."""

implementation:
warn ( 'use assess_component instead' , DeprecationWarning )
return assess_component ( model , reaction , 'reactants' , flux_coefficient_cutoff , solver )


signature:
def assess_products ( model , reaction , flux_coefficient_cutoff = 0.001 , solver = None ) :
    """Assesses whether the model has the capacity to absorb the products of
 a reaction at a given flux rate .
 Useful for identifying which components might be blocking a reaction
 from achieving a specific flux rate .
 Deprecated : use assess _ component instead
 Parameters
 model : cobra . Model
 The cobra model to assess production capacity for
 reaction : reaction identifier or cobra . Reaction
 The reaction to assess
 flux _ coefficient _ cutoff : float
 The minimum flux that reaction must carry to be considered active .
 solver : basestring
 Solver name . If None , the default solver will be used .
 Returns
 bool or dict
 True if the model has the capacity to absorb all the reaction
 products being simultaneously given the specified cutoff . False ,
 if the model has the capacity to absorb each individual product but
 not all products at the required level simultaneously . Otherwise a
 dictionary of the required and the capacity fluxes for each product
 that is not absorbed in sufficient quantities ."""

implementation:
warn ( 'use assess_component instead' , DeprecationWarning )
return assess_component ( model , reaction , 'products' , flux_coefficient_cutoff , solver )


signature:
def add_loopless ( model , zero_cutoff = None ) :
    """Modify a model so all feasible flux distributions are loopless .
 In most cases you probably want to use the much faster ` loopless _ solution ` .
 May be used in cases where you want to add complex constraints and
 objecives ( for instance quadratic objectives ) to the model afterwards
 or use an approximation of Gibbs free energy directions in you model .
 Adds variables and constraints to a model which will disallow flux
 distributions with loops . The used formulation is described in [ 1 ] _ .
 This function * will * modify your model .
 Parameters
 model : cobra . Model
 The model to which to add the constraints .
 zero _ cutoff : positive float , optional
 Cutoff used for null space . Coefficients with an absolute value smaller
 than ` zero _ cutoff ` are considered to be zero ( default model . tolerance ) .
 Returns
 Nothing
 References
 . . [ 1 ] Elimination of thermodynamically infeasible loops in steady - state
 metabolic models . Schellenberger J , Lewis NE , Palsson BO . Biophys J .
 2011 Feb 2;100(3 ) : 544-53 . doi : 10.1016 / j . bpj . 2010.12.3707 . Erratum
 in : Biophys J . 2011 Mar 2;100(5 ) : 1381."""

implementation:
zero_cutoff = normalize_cutoff ( model , zero_cutoff )
internal = [ i for i , r in enumerate ( model . reactions ) if not r . boundary ]
s_int = create_stoichiometric_matrix ( model ) [ : , numpy . array ( internal ) ]
n_int = nullspace ( s_int ) . T
max_bound = max ( max ( abs ( b ) for b in r . bounds ) for r in model . reactions )
prob = model . problem
# Add indicator variables and new constraints
to_add = [ ]
for i in internal :
    rxn = model . reactions [ i ]
    # indicator variable a _ i
    indicator = prob . Variable ( "indicator_" + rxn . id , type = "binary" )
    # - M * ( 1 - a _ i ) < = v _ i < = M * a _ i
    on_off_constraint = prob . Constraint ( rxn . flux_expression - max_bound * indicator , lb = - max_bound , ub = 0 , name = "on_off_" + rxn . id )
    # - ( max _ bound + 1 ) * a _ i + 1 < = G _ i < = - ( max _ bound + 1 ) * a _ i + 1000
    delta_g = prob . Variable ( "delta_g_" + rxn . id )
    delta_g_range = prob . Constraint ( delta_g + ( max_bound + 1 ) * indicator , lb = 1 , ub = max_bound , name = "delta_g_range_" + rxn . id )
    to_add . extend ( [ indicator , on_off_constraint , delta_g , delta_g_range ] )
model . add_cons_vars ( to_add )
# Add nullspace constraints for G _ i
for i , row in enumerate ( n_int ) :
    name = "nullspace_constraint_" + str ( i )
    nullspace_constraint = prob . Constraint ( Zero , lb = 0 , ub = 0 , name = name )
    model . add_cons_vars ( [ nullspace_constraint ] )
    coefs = { model . variables [ "delta_g_" + model . reactions [ ridx ] . id ] : row [ i ] for i , ridx in enumerate ( internal ) if abs ( row [ i ] ) > zero_cutoff }
    model . constraints [ name ] . set_linear_coefficients ( coefs )


signature:
def _add_cycle_free ( model , fluxes ) :
    """Add constraints for CycleFreeFlux ."""

implementation:
model . objective = model . solver . interface . Objective ( Zero , direction = "min" , sloppy = True )
objective_vars = [ ]
for rxn in model . reactions :
    flux = fluxes [ rxn . id ]
    if rxn . boundary :
        rxn . bounds = ( flux , flux )
        continue
    if flux >= 0 :
        rxn . bounds = max ( 0 , rxn . lower_bound ) , max ( flux , rxn . upper_bound )
        objective_vars . append ( rxn . forward_variable )
    else :
        rxn . bounds = min ( flux , rxn . lower_bound ) , min ( 0 , rxn . upper_bound )
        objective_vars . append ( rxn . reverse_variable )
model . objective . set_linear_coefficients ( { v : 1.0 for v in objective_vars } )


signature:
def loopless_solution ( model , fluxes = None ) :
    """Convert an existing solution to a loopless one .
 Removes as many loops as possible ( see Notes ) .
 Uses the method from CycleFreeFlux [ 1 ] _ and is much faster than
 ` add _ loopless ` and should therefore be the preferred option to get loopless
 flux distributions .
 Parameters
 model : cobra . Model
 The model to which to add the constraints .
 fluxes : dict
 A dictionary { rxn _ id : flux } that assigns a flux to each reaction . If
 not None will use the provided flux values to obtain a close loopless
 solution .
 Returns
 cobra . Solution
 A solution object containing the fluxes with the least amount of
 loops possible or None if the optimization failed ( usually happening
 if the flux distribution in ` fluxes ` is infeasible ) .
 Notes
 The returned flux solution has the following properties :
 - it contains the minimal number of loops possible and no loops at all if
 all flux bounds include zero
 - it has an objective value close to the original one and the same
 objective value id the objective expression can not form a cycle
 ( which is usually true since it consumes metabolites )
 - it has the same exact exchange fluxes as the previous solution
 - all fluxes have the same sign ( flow in the same direction ) as the
 previous solution
 References
 . . [ 1 ] CycleFreeFlux : efficient removal of thermodynamically infeasible
 loops from flux distributions . Desouki AA , Jarre F , Gelius - Dietrich
 G , Lercher MJ . Bioinformatics . 2015 Jul 1;31(13 ) : 2159-65 . doi :
 10.1093 / bioinformatics / btv096."""

implementation:
# Need to reoptimize otherwise spurious solution artifacts can cause
# all kinds of havoc
# TODO : check solution status
if fluxes is None :
    sol = model . optimize ( objective_sense = None )
    fluxes = sol . fluxes
with model :
    prob = model . problem
    # Needs one fixed bound for cplex . . .
    loopless_obj_constraint = prob . Constraint ( model . objective . expression , lb = - 1e32 , name = "loopless_obj_constraint" )
    model . add_cons_vars ( [ loopless_obj_constraint ] )
    _add_cycle_free ( model , fluxes )
    solution = model . optimize ( objective_sense = None )
    solution . objective_value = loopless_obj_constraint . primal
return solution


signature:
def loopless_fva_iter ( model , reaction , solution = False , zero_cutoff = None ) :
    """Plugin to get a loopless FVA solution from single FVA iteration .
 Assumes the following about ` model ` and ` reaction ` :
 1 . the model objective is set to be ` reaction `
 2 . the model has been optimized and contains the minimum / maximum flux for
 ` reaction `
 3 . the model contains an auxiliary variable called " fva _ old _ objective "
 denoting the previous objective
 Parameters
 model : cobra . Model
 The model to be used .
 reaction : cobra . Reaction
 The reaction currently minimized / maximized .
 solution : boolean , optional
 Whether to return the entire solution or only the minimum / maximum for
 ` reaction ` .
 zero _ cutoff : positive float , optional
 Cutoff used for loop removal . Fluxes with an absolute value smaller
 than ` zero _ cutoff ` are considered to be zero ( default model . tolerance ) .
 Returns
 single float or dict
 Returns the minimized / maximized flux through ` reaction ` if
 all _ fluxes = = False ( default ) . Otherwise returns a loopless flux
 solution containing the minimum / maximum flux for ` reaction ` ."""

implementation:
zero_cutoff = normalize_cutoff ( model , zero_cutoff )
current = model . objective . value
sol = get_solution ( model )
objective_dir = model . objective . direction
# boundary reactions can not be part of cycles
if reaction . boundary :
    if solution :
        return sol
    else :
        return current
with model :
    _add_cycle_free ( model , sol . fluxes )
    model . slim_optimize ( )
    # If the previous optimum is maintained in the loopless solution it was
    # loopless and we are done
    if abs ( reaction . flux - current ) < zero_cutoff :
        if solution :
            return sol
        return current
    # If previous optimum was not in the loopless solution create a new
    # almost loopless solution containing only loops including the current
    # reaction . Than remove all of those loops .
    ll_sol = get_solution ( model ) . fluxes
    reaction . bounds = ( current , current )
    model . slim_optimize ( )
    almost_ll_sol = get_solution ( model ) . fluxes
with model : # find the reactions with loops using the current reaction and remove
# the loops
    for rxn in model . reactions :
        rid = rxn . id
        if ( ( abs ( ll_sol [ rid ] ) < zero_cutoff ) and ( abs ( almost_ll_sol [ rid ] ) > zero_cutoff ) ) :
            rxn . bounds = max ( 0 , rxn . lower_bound ) , min ( 0 , rxn . upper_bound )
    if solution :
        best = model . optimize ( )
    else :
        model . slim_optimize ( )
        best = reaction . flux
model . objective . direction = objective_dir
return best


signature:
def create_stoichiometric_matrix ( model , array_type = 'dense' , dtype = None ) :
    """Return a stoichiometric array representation of the given model .
 The the columns represent the reactions and rows represent
 metabolites . S [ i , j ] therefore contains the quantity of metabolite ` i `
 produced ( negative for consumed ) by reaction ` j ` .
 Parameters
 model : cobra . Model
 The cobra model to construct the matrix for .
 array _ type : string
 The type of array to construct . if ' dense ' , return a standard
 numpy . array , ' dok ' , or ' lil ' will construct a sparse array using
 scipy of the corresponding type and ' DataFrame ' will give a
 pandas ` DataFrame ` with metabolite indices and reaction columns
 dtype : data - type
 The desired data - type for the array . If not given , defaults to float .
 Returns
 matrix of class ` dtype `
 The stoichiometric matrix for the given model ."""

implementation:
if array_type not in ( 'DataFrame' , 'dense' ) and not dok_matrix :
    raise ValueError ( 'Sparse matrices require scipy' )
if dtype is None :
    dtype = np . float64
array_constructor = { 'dense' : np . zeros , 'dok' : dok_matrix , 'lil' : lil_matrix , 'DataFrame' : np . zeros , }
n_metabolites = len ( model . metabolites )
n_reactions = len ( model . reactions )
array = array_constructor [ array_type ] ( ( n_metabolites , n_reactions ) , dtype = dtype )
m_ind = model . metabolites . index
r_ind = model . reactions . index
for reaction in model . reactions :
    for metabolite , stoich in iteritems ( reaction . metabolites ) :
        array [ m_ind ( metabolite ) , r_ind ( reaction ) ] = stoich
if array_type == 'DataFrame' :
    metabolite_ids = [ met . id for met in model . metabolites ]
    reaction_ids = [ rxn . id for rxn in model . reactions ]
    return pd . DataFrame ( array , index = metabolite_ids , columns = reaction_ids )
else :
    return array


signature:
def nullspace ( A , atol = 1e-13 , rtol = 0 ) :
    """Compute an approximate basis for the nullspace of A .
 The algorithm used by this function is based on the singular value
 decomposition of ` A ` .
 Parameters
 A : numpy . ndarray
 A should be at most 2 - D . A 1 - D array with length k will be treated
 as a 2 - D with shape ( 1 , k )
 atol : float
 The absolute tolerance for a zero singular value . Singular values
 smaller than ` atol ` are considered to be zero .
 rtol : float
 The relative tolerance . Singular values less than rtol * smax are
 considered to be zero , where smax is the largest singular value .
 If both ` atol ` and ` rtol ` are positive , the combined tolerance is the
 maximum of the two ; that is : :
 tol = max ( atol , rtol * smax )
 Singular values smaller than ` tol ` are considered to be zero .
 Returns
 numpy . ndarray
 If ` A ` is an array with shape ( m , k ) , then ` ns ` will be an array
 with shape ( k , n ) , where n is the estimated dimension of the
 nullspace of ` A ` . The columns of ` ns ` are a basis for the
 nullspace ; each element in numpy . dot ( A , ns ) will be approximately
 zero .
 Notes
 Taken from the numpy cookbook ."""

implementation:
A = np . atleast_2d ( A )
u , s , vh = np . linalg . svd ( A )
tol = max ( atol , rtol * s [ 0 ] )
nnz = ( s >= tol ) . sum ( )
ns = vh [ nnz : ] . conj ( ) . T
return ns