def gxFBA(cobramodel_1,cobramodel_2,gene_expressions,GPRlist,maxflux = 500, exprType = 2, verbose = True,FVAcondition = 2, wait = False,treshold = 0.5,objectiveweights = 'log',dumpmodel = False):
    if verbose:
        print 'Performing gxFBA. Verbose = True.'
        print 'Provided gene expression ratios:'
        print gene_expressions
        if exprType == 1:
            print 'Input gene expression ratios handled as absolute ratios.'
        else:
            print 'Input gene expression ratios handled as log ratios.'

    if exprType == 1:
        logvals = {gene:log(gene_expressions[gene],2) for gene in gene_expressions}
        ratios = gene_expressions
        if verbose:
            print 'Calculated log ratios:'
            print logvals
    else:
        logvals = gene_expressions
        ratios = {gene:2**gene_expressions[gene] for gene in gene_expressions}
    
    #Local variables:
    eps2 = 0.00001

    ##1) Generate the wild-type flux distribution v_i_wt for the starting condition:
    cobramodel_1.optimize(solver='gurobi')
    wildtype = cobramodel_1.solution.x_dict
    if verbose:
        print 'generated wild-type flux distribution.'
        #print cobramodel_1.solution.x_dict
        for key,value in sorted(cobramodel_1.solution.x_dict.items()):
            print key,value
    if wait:
        hold()
    ###2) Perform FVA with nutritional constraints for condition 1 or 2 (Default: condition 2) and minimum biomass flux = 0 to calculate the upper and lower fluxes each
    ###    reaction can carry.

    if FVAcondition == 1:
        FVA_result = cobra.flux_analysis.variability.flux_variability_analysis(cobramodel_1,fraction_of_optimum = 0)
    else:
        FVA_result = cobra.flux_analysis.variability.flux_variability_analysis(cobramodel_2,fraction_of_optimum = 0)
    if verbose:
        print 'Performed FVA for condition',FVAcondition
        for key,value in sorted(FVA_result.items()):
            print key,value
        #print FVA_result

    #Reset the objective function for condition 2:
    for reaction in cobramodel_2.reactions:
        reaction.objective_coefficient = 0

    ###    Calculate mean possible flux value for each reaction under condition 2, and the flux average for all active reactions under condition 1
    wt_avg = {key:np.mean([FVA_result[key]['minimum'],FVA_result[key]['maximum']])  for key in FVA_result}
    active_fluxes = [fluxvalue for fluxvalue in wildtype.values() if fluxvalue > eps2]
    wildtype_averageflux = np.mean(active_fluxes) #average wildtype flux

    if verbose:
        print 'FVA average fluxes:'
        #print wt_avg
        for key,value in wt_avg.items():
            print key,value
        print 'Total number of reactions in wildtype model:',len(wildtype.values())
        print 'Number of active reactions in wildtype FBA solution:',len(active_fluxes)
        print 'Average wildtype flux (Average of flux value for all fluxes in wildtype FBA solution):',wildtype_averageflux

    genemap = defaultdict(list)
    for gene in gene_expressions:
        if gene in GPRlist:
            for rx in GPRlist[gene]:
                genemap[rx].append(gene)

    if verbose:
        print 'Gene map:'
        print genemap


    if wait:
        hold()
    T = []
    ##3) Identify the set of reactions (called T) for which an mRNA expression value can be associated.
    if verbose:
        print 'Identifying reactions eligible for gx-regulation.'
    for reaction in cobramodel_2.reactions:
        #Skip reactions for which gene expression data is unavailable
        if reaction.id not in genemap:
            if verbose:
                print reaction.id,'not in genemap. Skipping reaction.'
            continue
        #Skip reactions for which the maximal up/down-regulation is below the set treshold:
        expressionratios = [ratios[gene] for gene in genemap[reaction.id] ]
        if max([abs(ratio-1) for ratio in expressionratios]) < treshold:
            if verbose:
                print reaction.id,': Level of regulation below treshold. Skipping reaction.'
            continue
        #Do not include the reaction if the average flux is too high:
        if wt_avg[reaction.id] >= maxflux:
            if verbose:
                print reaction.id,': FVA average flux too high. Skipping reaction.'
            continue
        #Do not include the reaction if it cannot carry any flux (as per FVA):
        if abs(wt_avg[reaction.id]) < eps2:
            if verbose:
                print reaction.id,': Reaction always inactive under specified conditions. Skipping reaction.'
            continue
        #Do not include the reaction if it is not irreversible under the given constraints:
        bounds = FVA_result[reaction.id].values()
        irreversible = not min(bounds) < 0 < max(bounds)
        if not irreversible:
            if verbose:
                print reaction.id,': Reaction may carry flux in both directions under specified conditions. Skipping reaction.'
            continue
        #Do not include the reaction if gene expression data is inconsistent (both up- and down-regulation):
        exprvalues = [logvals[gene] for gene in genemap[reaction.id] ]
        signs = [cmp(logvalue,0) for logvalue in exprvalues]
        if not (signs[1:] == signs[:-1]): #If all the signs are not the same value. Alternative: if not (signs.count(signs[0]) == signs(x))
            if verbose:
                print 'Gene expression information for reaction indicates mixed regulation (up/down). Skipping reaction.'
            continue
        #If none of the above checks failed, add the reaction to the list:
        if verbose:
            print 'Adding reaction',reaction.id,'to T.'
        T.append(reaction)


    ##4)  For each reaction in T; define a new upper bound UB = Ci_mRNA * v_i_wt if up-regulated or a new lower bound LB =
    ##    Ci_mRNA * v_i_wt if downregulated, where Ci_mRNA is the mRNA expression ratio.
    if verbose:
        print 'Calculating new bounds and objective function coefficients:'


    def reactionInfo(reaction_id):
        print 'Ci_mRNA:',Ci_mRNA
        print 'Wild-type flux:',wildtype[reaction.id]
        print 'Original reaction bounds:'
        print 'Lower:',cobramodel_1.reactions.get_by_id(reaction.id).lower_bound,'Upper:',cobramodel_1.reactions.get_by_id(reaction.id).upper_bound
        print 'New reaction bounds:'
        print 'Lower:',reaction.lower_bound,'Upper:',reaction.upper_bound
        print 'Objective coefficient:',reaction.objective_coefficient
    for reaction in T:
        if wait:
            hold()
        logvalues = [logvals[gene] for gene in genemap[reaction.id] ]
        expressionratios = [ratios[gene] for gene in genemap[reaction.id] ] 
        sign = cmp(logvalues[0],0)
        if verbose:
            print 'Processing reaction:',reaction.id
            print 'Logvalues:',logvalues
            print 'Ratios:',expressionratios
            
        if sign > 0:
            Ci_mRNA = 2**max(logvalues) ##    For reactions dependent on several genes (several mRNA values), use the maximal up/down-regulation value.
            if wildtype[reaction.id] == 0:
                reaction.upper_bound = Ci_mRNA * wildtype_averageflux
            else:
                reaction.upper_bound = Ci_mRNA * wildtype[reaction.id]
            #Set the objective function coefficient: Ci = log(Ci_mRNA) / (v_i average):
            if objectiveweights == 'log':
                reaction.objective_coefficient = max(logvalues) / wt_avg[reaction.id]
            elif objectiveweights =='logabs':
                reaction.objective_coefficient = max(logvalues) / wt_avg[reaction.id]
            elif objectiveweights == 'ratios':
                reaction.objective_coefficient = Ci_mRNA / wt_avg[reaction.id]
            elif objectiveweights == 'pureratios':
                reaction.objective_coefficient = Ci_mRNA
            
        elif sign < 0:
            Ci_mRNA = 2**min(logvalues) ##    For reactions dependent on several genes (several mRNA values), use the maximal up/down-regulation value.
            if wildtype[reaction.id] == 0:
                pass
            else:
                reaction.lower_bound = Ci_mRNA * wildtype[reaction.id]
            #Set the new objective function coefficient: Ci = log(Ci_mRNA) / (v_i average):
            if objectiveweights == 'log':
                reaction.objective_coefficient = min(logvalues) / wt_avg[reaction.id]
            elif objectiveweights =='logabs':
                reaction.objective_coefficient = abs(min(logvalues)) / wt_avg[reaction.id]
            elif objectiveweights =='ratios':
                reaction.objective_coefficient = Ci_mRNA / wt_avg[reaction.id]
            elif objectiveweights == 'pureratios':
                reaction.objective_coefficient = Ci_mRNA
        if verbose:
            reactionInfo(reaction.id)

    cobramodel_2.reactions.get_by_id('R5_akgdh').lower_bound = 0.65
    cobramodel_2.reactions.get_by_id('R5_akgdh').upper_bound = 1.3
    cobramodel_2.reactions.get_by_id('R2_lowergly').lower_bound = 0.8
    cobramodel_2.reactions.get_by_id('R2_lowergly').upper_bound = 3.42857

    cobramodel_2.reactions.get_by_id('R2_lowergly').objective_coefficient = 1.5
    cobramodel_2.reactions.get_by_id('R5_akgdh').objective_coefficient = 0.5
    cobramodel_2.reactions.get_by_id('R1_uppergly').objective_coefficient = 1.5
    cobramodel_2.reactions.get_by_id('R3_citsyn').objective_coefficient = 0.5
    if verbose:
        print 'New objective function:'
        #print {reaction.id:reaction.objective_coefficient for reaction in T}
        print {reaction.id:reaction.objective_coefficient for reaction in cobramodel_2.reactions}
        print 'New lower bounds:',[reaction.lower_bound for reaction in cobramodel_2.reactions]
        print 'New upper bounds:',[reaction.upper_bound for reaction in cobramodel_2.reactions]
        print 'Performing gx-FBA.'
        

    #Solve the gx-FBA problem:
    cobramodel_2.optimize(solver='gurobi')
    if verbose:
        print 'Flux solution:'
        print cobramodel_2.solution.x_dict
        print 'Objective value:',cobramodel_2.solution

    #Using Gurobi manually:
    gurobisolution = QPmindist.gurobiFBA(cobramodel_2)
    gurobisolutiondict = QPmindist.getgurobisolutiondict(gurobisolution)
    print 'gurobi solution:'
    print gurobisolutiondict
    print 'Objective value:',gurobisolution.Objval

    #Check that mass conservation is preserved:
    print 'Total metabolite fluxes:'
    for metabolite in cobramodel_2.metabolites:
        print metabolite.id,metabolitefluxsum(metabolite.id,cobramodel_2),metabolitefluxsum(metabolite.id,cobramodel_2, abs = True)

    #print 'ATP fluxes:',metabolitefluxes('atp_c',cobramodel_2)
    #print ''

    print 'Solution:'
    print cobramodel_2.solution.x
    vectorToText(cobramodel_2.solution.x,'flux.txt')
    print 'Flux solution dumped to flux.txt'
    #vectorToText([reaction.objective_coefficient for reaction in cobramodel_2.reactions],'objective.txt')
    vectorToText([reaction.objective_coefficient for reaction in cobramodel_2.reactions],'objective.txt', decimal = ',')
    vectorToText([reaction.lower_bound for reaction in cobramodel_1.reactions],'FBA-lb.txt')
    vectorToText([reaction.upper_bound for reaction in cobramodel_1.reactions],'FBA-ub.txt')
    vectorToText([reaction.lower_bound for reaction in cobramodel_2.reactions],'gxFBA-lb.txt')
    vectorToText([reaction.upper_bound for reaction in cobramodel_2.reactions],'gxFBA-ub.txt')

    vectorToText([reaction.objective_coefficient for reaction in cobramodel_2.reactions],'A.txt', decimal = ',', linestart = 'C:')
    #vectorToText([reaction.lower_bound for reaction in cobramodel_1.reactions],'A.txt',append = True, linestart = 'LB:')
    #vectorToText([reaction.upper_bound for reaction in cobramodel_1.reactions],'A.txt', append = True,linestart = 'UB:')
    vectorToText([reaction.lower_bound for reaction in cobramodel_2.reactions],'A.txt', append = True, linestart = 'LB:')
    vectorToText([reaction.upper_bound for reaction in cobramodel_2.reactions],'A.txt.', append = True, linestart = 'UB:')
    vectorToText(cobramodel_2.solution.x,'A.txt.', append = True, linestart = 'V:')

    if dumpmodel:
        write_cobra_model_to_sbml_file(cobramodel_2,'dumpedmodel.xml')
    
    return cobramodel_2


if __name__ == "__main__": #If the module is executed as a program, run a test.
    from cobra.io.sbml import create_cobra_model_from_sbml_file
    cobramodel = create_cobra_model_from_sbml_file('../SBML/SCHUETZR.xml')
    import loadData as load
    fluxvalues = load.ExpFluxesfromXML('expdata.xml','Perrenoud','Batch','aerobe')
    rmap = load.ReactionMapfromXML('reactionmaps.xml','Perrenoud','SCHUETZR')

    optreq = 1.0

    import QPmindist as qp

    gurobimodel = qp.QPmindist(cobramodel,fluxvalues,rmap,optreq)

    QPsolutiondict = qp.getgurobisolutiondict(gurobimodel)

    import extractflux2 as extract

    extractfluxdict = extract.extractfluxdict(QPsolutiondict,rmap)


    dictdist = compdistdict(extractfluxdict)

    print('dist:',dictdist)

    simple1 = {"A":1,"B":2,"C":3}
    simple2 = {"A":1,"B":2,"C":4}
    simpledist = compdistdict(simple1, expdata = simple2)
    return dist


if __name__ == "__main__":  #If the module is executed as a program, run a test.
    from cobra.io.sbml import read_sbml_model
    cobramodel = read_sbml_model('../SBML/SCHUETZR.xml')
    import loadData as load
    fluxvalues = load.ExpFluxesfromXML('expdata.xml', 'Perrenoud', 'Batch',
                                       'aerobe')
    rmap = load.ReactionMapfromXML('reactionmaps.xml', 'Perrenoud', 'SCHUETZR')

    optreq = 1.0

    import QPmindist as qp

    gurobimodel = qp.QPmindist(cobramodel, fluxvalues, rmap, optreq)

    QPsolutiondict = qp.getgurobisolutiondict(gurobimodel)

    import extractflux2 as extract

    extractfluxdict = extract.extractfluxdict(QPsolutiondict, rmap)

    dictdist = compdistdict(extractfluxdict)

    print('dist:', dictdist)

    simple1 = {"A": 1, "B": 2, "C": 3}
    simple2 = {"A": 1, "B": 2, "C": 4}
    simpledist = compdistdict(simple1, expdata=simple2)
Example #4
0
def optreqanalysis(modeldicts,
                   objectives,
                   experiments,
                   steps=10,
                   makeplots=True,
                   expfluxdict="Default",
                   plotter="easyviz"):
    '''Function for evaluating how the minimally achievable distance between a flux solution and a set of experimental fluxes
    changes when varying the required relative FBA objective-optimality of the flux solution.

    syntax: optreqanalysis(modeldicts,objectives,experiments,steps = 10,makeplots = True,expfluxdict)

    arguments:
    modeldicts: An array of python dictionaries with the following fields:
        modelobject: A CobraPy model object for the model in question.
        reactionmap: A reaction map array mapping between model reactions and experimental reactions for the model and experiment in question.
    objectives: A list of objectives to be used in the analysis.
    experiments: A list of experiments to be used in the analysis
    steps: The granularity of the analysis and produced plots.
    makeplots: Whether plots should be produced or not
    expfluxdict: A python dictionary with experiment-ids as keys and the corresponding flux value arrays as values.
    '''
    for objective in objectives:
        pass  #Placeholder

    for experiment in experiments:
        pass  #Placeholder

    if expfluxdict == "Default":  #This section should be rewritten to use an "expflux" dict.
        expdata = scipy.io.loadmat('expdata.mat')  #load experimentaldata
        perrenoud = expdata['expdata']['perrenoud']
        fluxvalarray = perrenoud[0][0][0][0][0][0][0][0][0][0][0][0][0][0]
        fluxvalues = [row[0] for row in fluxvalarray
                      ]  #expdata.perrenoud.abs.batch.aerobe.fluxvalues

        expfluxdict = load.ExpFluxesfromXML('expdata.xml', 'Perrenoud',
                                            'Batch', 'aerobe')

    resultlist = []
    for modeldict in modeldicts:
        cobramodel = modeldict['modelobject']
        #print 'modeldict:',modeldict
        reactionmap = modeldict['reactionmap']
        #print 'cobramodel:',cobramodel
        #print type(cobramodel)

        optreqs = []
        for i in range(steps + 1):
            optreqs.append(float(i) / steps)
        results = []
        #print 'opreqs:',optreqs
        #q = raw_input('Continue?')
        for optreq in optreqs:
            optimizedmodel = QPmindist(cobramodel, fluxvalues, reactionmap,
                                       optreq)
            results.append(math.sqrt(optimizedmodel.ObjVal))
        resultlist.append(results)
        #Using easyviz
        #ev.plot(optreqs,results)
        #ev.hold()

        #Using prettyplotlib
        #fig, ax = plt.subplots(1)
        #ppl.scatter(ax, x, y)
        #ppl.plot(optreqs,results)
    return resultlist