Example #1
0
 def get_solution(self):
     """
     Overrides the cobra.thermo.solution method, to also get the supplementary
     variables we added to the cobra_model
     :return:
     """
     objective_value = self.solver.objective.value
     status = self.solver.status
     variables = pd.Series(data=self.solver.primal_values)
     solution = Solution(objective_value=objective_value,
                         status=status,
                         fluxes=variables)
     return solution
Example #2
0
    def get_solution(self):
        """
        Overrides the cobra.thermo.solution method, to also get the supplementary
        variables we added to the cobra_model

        *   :code:`solution.fluxes` in `cobrapy` is a transformed version of the solver
            output, as it actually calculates the _net_ flux of each reaction by
            substracting the reverse variable value to the forward variable value.
            This should be used anytime one needs the actual flux value

        *   :code:`solution.raw` is a clear copy of the solver output. From there one
            can access the value at solution for all the variables of the problem.
            However, looking for a reaction ID in there will only give the
            _forward_ flux. This should be used for any other variable than fluxes.

        *   :code:`solution.values` yields variables multiplied by their scaling factor
            (1 by default). Useful if you operated scaling on your equations for
            numerical reasons. This does _not_ include fluxes

        :return:
        """
        objective_value = self.solver.objective.value
        status = self.solver.status
        variables = pd.Series(data=self.solver.primal_values)

        fluxes = empty(len(self.reactions))
        rxn_index = list()
        var_primals = self.solver.primal_values

        for (i, rxn) in enumerate(self.reactions):
            rxn_index.append(rxn.id)
            fluxes[i] = var_primals[rxn.id] - var_primals[rxn.reverse_id]

        fluxes = pd.Series(index=rxn_index, data=fluxes, name="fluxes")

        solution = Solution(objective_value=objective_value,
                            status=status,
                            fluxes=fluxes)

        self.solution = solution

        self.solution.raw = variables

        self.\
            solution.values = pd.DataFrame.from_dict({k:v.unscaled
                                                 for k,v in self._var_dict.items()},
                                                 orient = 'index')

        return solution
Example #3
0
def MergeRev(model, update_solution=True):
    ###modify.revert_to_reversible(model, update_solution=update_solution)
    """
        The cobra function above fails to update the solution object when merging. 
        This results in how reactions that goes in the reversible direction to be missing from solution. 
        Fix is made by commenting the remove_reactions function and, instead, changing the solution dict 
        manually in GetSol.
    """

    ### Copied cobra code here

    reverse_reactions = [
        x for x in model.reactions
        if "reflection" in x.notes and x.id.endswith('_reverse')
    ]
    # If there are no reverse reactions, then there is nothing to do
    if len(reverse_reactions) == 0:
        return

    if update_solution:
        if isinstance(model.solution, Solution):
            fluxes = dict(model.solution.fluxes)
            reduced = dict(model.solution.reduced_costs)
            for reverse in reverse_reactions:
                forward = reverse.reflection
                if reverse.id in fluxes.keys():
                    fluxes[forward.id] -= fluxes.pop(reverse.id)
                    reduced[forward.id] -= reduced.pop(reverse.id)
            merged_sol = Solution(
                model.solution.objective_value, model.solution.status,
                Series(index=fluxes.keys(),
                       data=fluxes.values(),
                       name="fluxes"),
                Series(index=reduced.keys(),
                       data=reduced.values(),
                       name="reduced_costs"), model.solution.shadow_prices)
            model.UpdateSolution(merged_sol)

    for reverse in reverse_reactions:
        forward_id = reverse.notes.pop("reflection")
        forward = model.reactions.get_by_id(forward_id)
        forward.lower_bound = -reverse.upper_bound
        if forward.upper_bound == 0:
            forward.upper_bound = -reverse.lower_bound

        if "reflection" in forward.notes:
            forward.notes.pop("reflection")

    model.remove_reactions(reverse_reactions)
Example #4
0
def SplitRev(model, split_solution=True):
    #modify.convert_to_irreversible(model)
    reactions_to_add = []
    coefficients = {}
    for reaction in model.reactions:
        # If a reaction is reverse only, the forward reaction (which
        # will be constrained to 0) will be left in the model.
        if reaction.lower_bound < 0:
            reverse_reaction = Reaction(reaction.id + "_reverse")
            reverse_reaction.lower_bound = min(0, reaction.upper_bound) * -1
            reverse_reaction.upper_bound = reaction.lower_bound * -1
            coefficients[
                reverse_reaction] = reaction.objective_coefficient * -1
            reaction.lower_bound = 0
            reaction.upper_bound = max(0, reaction.upper_bound)
            #Make the directions aware of each other
            reaction.reflection = reverse_reaction
            reverse_reaction.reflection = reaction
            reaction.notes["reflection"] = reverse_reaction.id
            reverse_reaction.notes["reflection"] = reaction.id
            reaction_dict = {
                k: v * -1
                for k, v in iteritems(reaction._metabolites)
            }
            reverse_reaction.add_metabolites(reaction_dict)
            reverse_reaction._model = reaction._model
            reverse_reaction._genes = reaction._genes
            for gene in reaction._genes:
                gene._reaction.add(reverse_reaction)
            reverse_reaction._gene_reaction_rule = reaction._gene_reaction_rule
            reverse_reaction.subsystem = reaction.subsystem
            reactions_to_add.append(reverse_reaction)
    model.add_reactions(reactions_to_add)
    model.SetObjective(coefficients)

    if split_solution:
        reverse_reactions = [
            x for x in model.reactions
            if "reflection" in x.notes and x.id.endswith('_reverse')
        ]
        if isinstance(model.solution, Solution):
            fluxes = dict(model.solution.fluxes)
            reduced = dict(model.solution.reduced_costs)
            for reverse in reverse_reactions:
                forward = reverse.reflection
                if (forward.id in fluxes) and (reverse.id in fluxes):
                    if fluxes[forward.id] < 0:
                        fluxes[reverse.id] = -fluxes[forward.id]
                        fluxes[forward.id] = 0
                    else:
                        fluxes[reverse.id] = 0
                    if reduced[forward.id] < 0:
                        reduced[reverse.id] = -reduced[forward.id]
                        reduced[forward.id] = 0
                    else:
                        reduced[reverse.id] = 0


#                else:
#                    print(forward.id + ' and ' + reverse.id + ' not in solution')
            split_sol = Solution(
                model.solution.objective_value, model.solution.status,
                Series(index=fluxes.keys(),
                       data=fluxes.values(),
                       name="fluxes"),
                Series(index=reduced.keys(),
                       data=reduced.values(),
                       name="reduced_costs"), model.solution.shadow_prices)
            model.UpdateSolution(split_sol)
Example #5
0
    def simulate(self, objective=None, method=SimulationMethod.FBA, maximize=True,
                 constraints=None, reference=None, scalefactor=None):
        '''
        Simulates a phenotype when applying a set constraints using the specified method.

        :param dic objective: The simulation objective. If none, the model objective is considered.
        :param method: The SimulationMethod (FBA, pFBA, lMOMA, etc ...)
        :param boolean maximize: The optimization direction.
        :param dic constraints: A dictionary of constraints to be applied to the model.
        :param dic reference: A dictionary of reaction flux values.
        :param float scalefactor: A positive scaling factor for the solver. Default None.

        '''

        if not objective:
            objective = self.model.objective
        elif isinstance(objective, dict) and len(objective) > 0:
            objective = next(iter(objective.keys()))

        simul_constraints = OrderedDict()
        if constraints:
            simul_constraints.update(constraints)
        if self.constraints:
            simul_constraints.update(self.constraints)
        if self.environmental_conditions:
            simul_constraints.update(self.environmental_conditions)

        with self.model as model:
            model.objective = objective
            for rxn in list(simul_constraints.keys()):
                reac = model.reactions.get_by_id(rxn)
                # constraints defined as a tuple (lower_bound, upper_bound) or as a single float value
                if isinstance(simul_constraints.get(rxn), tuple):
                    reac.bounds = (simul_constraints.get(
                        rxn)[0], simul_constraints.get(rxn)[1])
                else:
                    reac.bounds = (simul_constraints.get(
                        rxn), simul_constraints.get(rxn))
            # NOTE: If working directly over optlang use 'max' and 'min'
            # such is the case with pytfa.core.Model... need to find some workaround
            objective_sense = 'maximize' if maximize else 'minimize'
            if method == SimulationMethod.FBA:
                solution = model.optimize(objective_sense=objective_sense)
            elif method == SimulationMethod.pFBA:
                # make fraction_of_optimum a configurable parameter?
                solution = pfba(model)
            elif method == SimulationMethod.lMOMA or method == SimulationMethod.MOMA:
                s = None
                if not maximize:
                    s = model.optimize(objective_sense=objective_sense)
                linear = True if method == SimulationMethod.lMOMA else False
                solution = moma(model, solution=s, linear=linear)
            elif method == SimulationMethod.ROOM:
                solution = room(model)
            # Special case in which only the simulation context is required without any simulation result
            elif method == SimulationMethod.NONE:
                solution = Solution(None, 'unknown', None)
                pass
            else:
                raise Exception(
                    "Unknown method to perform the simulation.")

        status = self.__status_mapping[solution.status]

        result = SimulationResult(model, solution.objective_value, fluxes=solution.fluxes.to_dict(OrderedDict),
                                  status=status, envcond=self.environmental_conditions,
                                  model_constraints=self.constraints,
                                  simul_constraints=constraints,
                                  maximize=maximize)
        return result