def maximize(self, is_pfba=False, growth=True):

        if is_pfba:

            if growth:
                try:
                    return pfba(self.model).fluxes[self.biomass_reaction.id]

                except Infeasible:
                    return 0

            try:
                return pfba(self.model)

            except Infeasible:

                return Solution(objective_value=0, status='infeasible', fluxes=Series())

        if growth:
            try:
                return self.model.optimize(objective_sense="maximize").objective_value

            except Infeasible:
                return 0

        try:
            return self.model.optimize(objective_sense="maximize")

        except Infeasible:
            return Solution(objective_value=0, status='infeasible', fluxes=Series())
def test_metabolite_summary_interface(model, opt_solver):
    """Test that a summary can be created successfully."""
    model.solver = opt_solver
    metabolite = model.metabolites.get_by_id("q8_c")
    MetaboliteSummary(
        metabolite=metabolite,
        model=model,
    )
    MetaboliteSummary(
        metabolite=metabolite,
        model=model,
        solution=pfba(model),
    )
    MetaboliteSummary(
        metabolite=metabolite,
        model=model,
        fva=0.95,
    )
    MetaboliteSummary(
        metabolite=metabolite,
        model=model,
        fva=flux_variability_analysis(
            model, reaction_list=["CYTBD", "NADH16", "SUCDi"]
        ),
    )
Beispiel #3
0
 def _calc_fluxes(self, alg='fba', sampling_n=0):
     try:
         if sampling_n == 0:
             self.model.solver.problem.write(self.__class__.__name__ +
                                             '.lp')
             if alg == 'pfba':
                 solution = pfba(self.model)
             else:
                 solution = self.model.optimize()
             if solution.status == OPTIMAL:
                 reversible_fluxes = solution.fluxes
                 self.logger.info(
                     f"Optimal objective: {solution.objective_value:.2f}")
             else:
                 raise OptimizationError(solution.status)
         else:
             reversible_fluxes = sample(
                 self.model,
                 n=sampling_n,
                 thinning=10,
                 processes=multiprocessing.cpu_count()).mean(axis=0)
         irreversible_fluxes = {}
         for reaction, flux in reversible_fluxes.iteritems():
             if flux < 0:
                 irreversible_fluxes[reaction + '_b'] = -flux
             else:
                 irreversible_fluxes[reaction] = flux
         return Series(irreversible_fluxes.values(),
                       index=irreversible_fluxes.keys())
     except (AttributeError, SolverError, OptimizationError) as e:
         self.logger.error(f'{str(e).capitalize()}')
         return Series([], dtype=object)
Beispiel #4
0
def runCobra(
    sim_type: str,
    rpsbml: rpSBML,
    objective_id: str,
    hidden_species: List[str] = [],
    fraction_coeff: float = 0.95,
    medium: pd.DataFrame = None,
    logger: Logger = getLogger(__name__)
) -> Tuple[cobra_solution, pd.DataFrame]:
    """Run Cobra to optimize model.

    :param sim_type: The type of simulation to use. Available simulation types include: fraction, fba, rpfba
    :param rpsbml: The model to analyse.
    :param objective_id: Overwrite the auto-generated id of the results (Default: None)
    :param hidden_species: List of species to mask (Optional).
    :param fraction_coeff: The fraction of the optimum. Used in pfba simulation (Default: 0.95).
    :param medium: A DataFrame describing medium composition (Optional).
    :param logger: A logger (Optional).

    :type sim_type: str
    :type rpsbml: rpSBML
    :type objective_id: str
    :type hidden_species: List[str]
    :type fraction_coeff: float
    :type medium: pd.DataFrame
    :type logger: Logger

    :return: Results of the simulation.
    :rtype: cobra.Solution
    """

    cobraModel = build_cobra_model(rpsbml=rpsbml,
                                   objective_id=objective_id,
                                   hidden_species=hidden_species,
                                   logger=logger)
    if not cobraModel:
        return None

    if is_df_medium_defined(medium):
        cobraModel.medium = df_to_medium(medium)
        logger.debug('Medium modify')
        logger.debug(cobraModel.medium)

    cobra_results = None
    if sim_type.lower() == 'pfba':
        cobra_results = pfba(cobraModel, fraction_coeff)
    else:
        cobra_results = cobraModel.optimize(objective_sense='maximize',
                                            raise_error=True)

    logger.debug(cobra_results)

    # Minimal medium.
    logger.debug('Minimal medium')
    minimal_medium = build_minimal_medium(model=cobraModel,
                                          solution=cobra_results)
    logger.debug(minimal_medium)

    return cobra_results, minimal_medium
Beispiel #5
0
    def simulate(self, overrideSimulProblem=None):
        """
        This method preforms the phenotype simulation of the GeckoModel with
            the modifications present in the overrideSimulProblem.
        Args:
            overrideSimulProblem (overrideStoicSimulProblem): override simulation Problem

        Returns:
            GeckoSimulationResult: Returns an object with the steady-state flux distribution,
                protein concentrations and solver status.
        """

        new_constraints = OrderedDict()
        if overrideSimulProblem is not None:
            new_constraints = overrideSimulProblem.get_modifications()

        if self.constraints is not None:
            new_constraints.update(self.constraints)

        with self.model:
            for rId in list(new_constraints.keys()):
                reac = self.model.reactions.get_by_id(rId)
                reac.bounds = (new_constraints.get(rId)[0] *
                               GeckoConfigurations.SCALE_CONSTANT,
                               new_constraints.get(rId)[1] *
                               GeckoConfigurations.SCALE_CONSTANT)

            if self.method_simul == 'pFBA':
                solution = pfba(self.model)
            else:
                if self.minimize:
                    solution = self.model.optimize(objective_sense="minimize")
                else:
                    solution = self.model.optimize()

        status = solverStatus.UNKNOWN

        if solution.status == "optimal":
            status = solverStatus.OPTIMAL

        fluxDist = solution.fluxes

        fluxes, prots = {}, {}
        for k, v in fluxDist.items():
            if k.startswith("draw_prot_"):
                prots[k[10:]] = v / GeckoConfigurations.SCALE_CONSTANT
            elif k.startswith("prot_"):
                prots[k[5:11]] = v / GeckoConfigurations.SCALE_CONSTANT
            else:
                fluxes[k] = v / GeckoConfigurations.SCALE_CONSTANT

        # for fixing the simulation errors during the optimization
        self.model._solver = copy(self.new_solver)

        return GeckoSimulationResult(self.model,
                                     solverStatus=status,
                                     ssFluxesDistrib=fluxes,
                                     protConcentrations=prots,
                                     overrideSimulProblem=overrideSimulProblem)
Beispiel #6
0
def evaluate_biomass_coupled_production(
    model: cobra.Model,
    production_id: str,
    biomass_id: str,
    carbon_source_id: str,
) -> Tuple[Optional[float], Optional[float]]:
    """
    Evaluate the biomass coupled production levels in the specific conditions.

    Warnings
    --------
    This function is expected to be called within a context since it modifies
    the model's objective.

    Parameters
    ----------
    model : cobra.Model
        The constraint-based metabolic model of the production organism.
    production_id : str
        The identifier of the reaction representing production, for example,
        a demand reaction on the compound.
    biomass_id : str
        The identifier of the reaction representing biomass accumulation, i.e.,
        growth.
    carbon_source_id : str
        The identifier of the reaction representing carbon uptake, for example,
        a glucose exchange reaction.

    Returns
    -------
    tuple
        float or None
            The theoretical maximum growth rate if any.
        float or None
            The maximum biomass coupled product yield if any.

    """
    bpcy = biomass_product_coupled_yield(
        biomass_id, production_id, carbon_source_id
    )
    try:
        model.objective = biomass_id
        solution = pfba(model)
        growth = solution[biomass_id]
    except OptimizationError as error:
        logger.error(
            "Could not determine biomass coupled production due to a solver "
            "error. %r",
            error,
        )
        growth = None
        bpc_yield = None
    else:
        try:
            bpc_yield = bpcy(model, solution, None)
        except ZeroDivisionError:
            logger.error("Division by zero in yield calculation.")
            bpc_yield = None
    return growth, bpc_yield
Beispiel #7
0
def test_model_summary_to_frame_previous_solution(model, opt_solver):
    """Test that the summary correctly uses an existing solution."""
    model.solver = opt_solver
    solution = pfba(model)
    rxn = model.reactions.EX_glc__D_e
    solution.fluxes[rxn.id] = -123
    summary = model.summary(solution=solution)
    assert summary.to_frame().at[rxn.id, "flux"] == 123
Beispiel #8
0
def capitulo_8():
    file = open("resultados_capitulo_8.txt", "w")
    salmonella = cobra.test.create_test_model('salmonella')
    nominal = salmonella.optimize()
    loopless = loopless_solution(salmonella)
    import pandas
    df = pandas.DataFrame(
        dict(loopless=loopless.fluxes, nominal=nominal.fluxes))
    df.plot.scatter(x='loopless', y='nominal')
    model = Model()
    model.add_metabolites([Metabolite(i) for i in "ABC"])
    model.add_reactions(
        [Reaction(i) for i in ["EX_A", "DM_C", "v1", "v2", "v3"]])
    model.reactions.EX_A.add_metabolites({"A": 1})
    model.reactions.DM_C.add_metabolites({"C": -1})
    model.reactions.v1.add_metabolites({"A": -1, "B": 1})
    model.reactions.v2.add_metabolites({"B": -1, "C": 1})
    model.reactions.v3.add_metabolites({"C": -1, "A": 1})
    model.objective = 'DM_C'
    with model:
        add_loopless(model)
        solution = model.optimize()
    file.write("loopless solution: status = " + solution.status)
    file.write("\n")
    file.write("loopless solution flux: v3 = %.1f" % solution.fluxes["v3"])
    file.write("\n")
    solution = pfba(model)
    file.write("parsimonious solution: status = " + solution.status)
    file.write("\n")
    file.write("loopless solution flux: v3 = %.1f" % solution.fluxes["v3"])
    file.write("\n")
    model.reactions.v3.lower_bound = 1
    with model:
        add_loopless(model)
        try:
            solution = model.optimize()
        except:
            file.write('model is infeasible')
            file.write("\n")
    solution = pfba(model)
    file.write("parsimonious solution: status = " + solution.status)
    file.write("\n")
    file.write("loopless solution flux: v3 = %.1f" % solution.fluxes["v3"])
    file.write("\n")
    file.close()
Beispiel #9
0
def test_model_summary_interface(model, opt_solver):
    """Test that a summary can be created successfully."""
    model.solver = opt_solver
    ModelSummary(model=model, )
    ModelSummary(
        model=model,
        solution=pfba(model),
    )
    ModelSummary(
        model=model,
        fva=0.95,
    )
    ModelSummary(
        model=model,
        fva=flux_variability_analysis(
            model, reaction_list=["CYTBD", "NADH16", "SUCDi"]),
    )
Beispiel #10
0
    def _generate(
        self,
        model: "Model",
        solution: Optional["Solution"],
        fva: Optional[Union[float, pd.DataFrame]],
    ) -> None:
        """
        Prepare the data for the summary instance.

        Parameters
        ----------
        model : cobra.Model
            The metabolic model for which to generate a metabolite summary.
        solution : cobra.Solution, optional
            A previous model solution to use for generating the summary. If
            ``None``, the summary method will generate a parsimonious flux
            distribution.
        fva : pandas.DataFrame or float, optional
            Whether or not to include flux variability analysis in the output.
            If given, `fva` should either be a previous FVA solution matching the
            model or a float between 0 and 1 representing the fraction of the
            optimum objective to be searched.

        """
        super()._generate(model=model, solution=solution, fva=fva)

        if solution is None:
            logger.info("Generating new parsimonious flux distribution.")
            solution = pfba(model)

        if isinstance(fva, float):
            logger.info("Performing flux variability analysis.")
            fva = flux_variability_analysis(
                model,
                reaction_list=[self._reaction],
                fraction_of_optimum=fva,
            )

        # Create the basic flux table.
        self._flux = pd.DataFrame(
            data={"flux": [solution[self._reaction.id]]},
            index=[self._reaction.id],
        )
        if fva is not None:
            self._flux = self._flux.join(fva)
def simulate(model, biomass_reaction, method, objective_id,
             objective_direction):
    if method not in METHODS:
        raise ValueError(f"Unsupported simulation method '{method}'")

    if objective_id:
        model.objective = model.reactions.get_by_id(objective_id)
    if objective_direction:
        model.objective_direction = objective_direction

    try:
        logger.info(f"Simulating model {model.id} with {method}")
        if method == "fba":
            solution = model.optimize(raise_error=True)
        elif method == "pfba":
            solution = pfba(model)
        elif method == "fva":
            # FIXME: accept list of relevant fva reactions to calculate
            solution = flux_variability_analysis(model)
        elif method == "pfba-fva":
            # FIXME: accept list of relevant fva reactions to calculate
            solution = flux_variability_analysis(model,
                                                 fraction_of_optimum=1,
                                                 pfba_factor=1.05)
    except OptimizationError as error:
        logger.info(f"Optimization Error: {error}")
        raise
    else:
        if method in ("fba", "pfba"):
            flux_distribution = solution.fluxes.to_dict()
            growth_rate = flux_distribution[biomass_reaction]
        elif method in ("fva", "pfba-fva"):
            df = solution.rename(index=str,
                                 columns={
                                     "maximum": "upper_bound",
                                     "minimum": "lower_bound"
                                 })
            for key in ["lower_bound", "upper_bound"]:
                df[key] = df[key].astype("float")
            flux_distribution = df.T.to_dict()
            growth_rate = flux_distribution[biomass_reaction]["upper_bound"]
        logger.info(
            f"Simulation was successful with growth rate {growth_rate}")
        return flux_distribution, growth_rate
Beispiel #12
0
def rp_pfba(rpsbml,
            reaction_id,
            coefficient=1.0,
            fraction_of_optimum=0.95,
            is_max=True,
            pathway_id='rp_pathway',
            objective_id=None,
            logger=None):
    """Run parsimonious FBA using a single objective

    :param reaction_id: The id of the reactions involved in the objective
    :param coefficient: The coefficient associated with the reactions id (Default: 1.0)
    :param fraction_of_optimum: Between 0.0 and 1.0 determining the fraction of optimum (Default: 0.95)
    :param is_max: Maximise or minimise the objective (Default: True)
    :param pathway_id: The id of the heterologous pathway (Default: rp_pathway)
    :param objective_id: Overwrite the default id (Default: None)

    :type reaction_id: str
    :type coefficient: float
    :type fraction_of_optimum: float
    :type is_max: bool
    :type pathway_id: str
    :type objective_id: str

    :return: Tuple with the results of the FBA and boolean indicating the success or failure of the function
    :rtype: tuple
    """
    logger = logger or logging.getLogger(__name__)
    fbc_plugin = rpsbml.getModel().getPlugin('fbc')
    rpsbml.checklibSBML(fbc_plugin, 'Getting FBC package')
    objective_id = rpsbml.findCreateObjective([reaction_id], [coefficient],
                                              is_max, objective_id)
    # run the FBA
    rpsbml.checklibSBML(fbc_plugin.setActiveObjectiveId(objective_id),
                        'Setting active objective ' + str(objective_id))
    cobraModel = rpsbml.convertToCobra()
    if not cobraModel:
        return 0.0, False
    cobra_results = pfba(cobraModel, fraction_of_optimum)
    rpsbml.addAnalysisResults(objective_id, cobra_results, pathway_id)
    return cobra_results.objective_value, rpsbml
Beispiel #13
0
def test_reaction_summary_interface(model, opt_solver):
    """Test that a summary can be created successfully."""
    model.solver = opt_solver
    reaction = model.reactions.get_by_id("FUM")
    ReactionSummary(
        reaction=reaction,
        model=model,
    )
    ReactionSummary(
        reaction=reaction,
        model=model,
        solution=pfba(model),
    )
    ReactionSummary(
        reaction=reaction,
        model=model,
        fva=0.95,
    )
    ReactionSummary(
        reaction=reaction,
        model=model,
        fva=flux_variability_analysis(model, reaction_list=["FUM"]),
    )
Beispiel #14
0
    def _generate(
        self,
        model: "Model",
        solution: Optional["Solution"],
        fva: Optional[Union[float, pd.DataFrame]],
    ) -> None:
        """
        Prepare the data for the summary instance.

        Parameters
        ----------
        model : cobra.Model
            The metabolic model for which to generate a metabolite summary.
        solution : cobra.Solution, optional
            A previous model solution to use for generating the summary. If
            ``None``, the summary method will generate a parsimonious flux
            distribution.
        fva : pandas.DataFrame or float, optional
            Whether or not to include flux variability analysis in the output.
            If given, `fva` should either be a previous FVA solution matching the
            model or a float between 0 and 1 representing the fraction of the
            optimum objective to be searched.

        """
        super()._generate(model=model, solution=solution, fva=fva)

        if solution is None:
            logger.info("Generating new parsimonious flux distribution.")
            solution = pfba(model)

        if isinstance(fva, float):
            logger.info("Performing flux variability analysis.")
            fva = flux_variability_analysis(
                model=model,
                reaction_list=[r.id for r in self._reactions],
                fraction_of_optimum=fva,
            )

        # Create the basic flux table.
        flux = pd.DataFrame(
            data=[(
                r.id,
                solution[r.id],
                r.get_coefficient(self._metabolite.id),
            ) for r in self._reactions],
            columns=["reaction", "flux", "factor"],
            index=[r.id for r in self._reactions],
        )
        # Scale fluxes by stoichiometric coefficient.
        flux["flux"] *= flux["factor"]

        if fva is not None:
            flux = flux.join(fva)
            view = flux[["flux", "minimum", "maximum"]]
            # Set fluxes below model tolerance to zero.
            flux[["flux", "minimum",
                  "maximum"]] = view.where(view.abs() >= model.tolerance, 0)
            # Create the scaled compound flux.
            flux[["minimum",
                  "maximum"]] = flux[["minimum",
                                      "maximum"]].mul(flux["factor"], axis=0)
            # Negative factors invert the minimum/maximum relationship.
            negative = flux["factor"] < 0
            tmp = flux.loc[negative, "maximum"]
            flux.loc[negative, "maximum"] = flux.loc[negative, "minimum"]
            flux.loc[negative, "minimum"] = tmp
            # Add zero to turn negative zero into positive zero for nicer display later.
            flux[["flux", "minimum", "maximum"]] += 0
        else:
            # Set fluxes below model tolerance to zero.
            flux.loc[flux["flux"].abs() < model.tolerance, "flux"] = 0
            # Add zero to turn negative zero into positive zero for nicer display later.
            flux["flux"] += 0

        # Create production table from producing fluxes or zero fluxes where the
        # metabolite is a product in the reaction.
        is_produced = (flux["flux"] > 0) | ((flux["flux"] == 0) &
                                            (flux["factor"] > 0))
        if fva is not None:
            self.producing_flux = flux.loc[
                is_produced,
                ["flux", "minimum", "maximum", "reaction"]].copy()
        else:
            self.producing_flux = flux.loc[is_produced,
                                           ["flux", "reaction"]].copy()
        production = self.producing_flux["flux"].abs()
        self.producing_flux["percent"] = production / production.sum()

        # Create consumption table from consuming fluxes or zero fluxes where the
        # metabolite is a substrate in the reaction.
        is_consumed = (flux["flux"] < 0) | ((flux["flux"] == 0) &
                                            (flux["factor"] < 0))
        if fva is not None:
            self.consuming_flux = flux.loc[
                is_consumed,
                ["flux", "minimum", "maximum", "reaction"]].copy()
        else:
            self.consuming_flux = flux.loc[is_consumed,
                                           ["flux", "reaction"]].copy()
        consumption = self.consuming_flux["flux"].abs()
        self.consuming_flux["percent"] = consumption / consumption.sum()

        self._flux = flux
Beispiel #15
0
 def run_parsimonous(self, selected_solver):
     solution = pfba(self.model)
     solution.method = "fba"
     self.add_solution(solution)
def path(m, s, p, pathfolder, specialgroup, specialgroup_begin):
    # calculate pathways between two metabolites in a model
    # m: model, s: substrate ID, p: product ID,pathfolder: the folder to save the calculated pathways
    with m as model:  # to avoid change of the original model
        substrate = model.metabolites.get_by_id(s)
        product = model.metabolites.get_by_id(p)
        if 'SK_' + s in model.reactions:  # add sink reaction
            model.reactions.get_by_id('SK_' + s).bounds = (-10, 0)
            #rea=model.reactions.get_by_id('SK_' + s)
            # rea.lb=-10.0
            # rea.ub=-10.0
        else:
            model.add_boundary(substrate, type='sink')
            model.reactions.get_by_id('SK_' + s).bounds = (-10, 0)
            #model.add_boundary(substrate, type='sink', lb=10)
        if 'DM_' + p in model.reactions:
            demand = model.reactions.get_by_id('DM_' + p)
            # for special metabolites, change to a new demand reaction to produce acCOA, acACP etc
            if p[-5:-2] in specialgroup or p[0:3] in specialgroup_begin:
                demand.remove_from_model()
                # model.remove_reactions([demand])
                demand = add_demand(model, product, specialgroup_begin)
        else:
            demand = add_demand(model, product, specialgroup_begin)
        model.objective = demand
        try:
            fluxes = pfba(model).fluxes
        except:
            metpair = [s, p, 'no solution']
        else:

            # solution = pfba(model,fraction_of_optimum=0.5) #using fraction_of_optimum to get the backbone pathway without carbon fixation
            # but it reduces the rate of the input reaction even it is fixed at -10
            # not work for AcCoA to pyr, as other compounds in reaction coa_c + 2.0 flxso_c + pyr_c <=> accoa_c + co2_c + 2.0 flxr_c
            # still need to be balanced
            # rate=solution.objective_value #not use this because it is the sum of the fluxes
            rate = model.reactions.get_by_id('DM_' + p).flux
            # sometimes the input flux is not equal to the upper bound
            influx = abs(model.reactions.get_by_id('SK_' + s).flux)
            # print(rate)
            if rate > 1e-6:
                # pathfile = open(pathfolder+ "/"+  s + "--" + p + ".txt", 'w')  # save the pathway for checking
                # for r,v in fluxes.iteritems():
                #    if abs(v)>1e-6:
                #        pathfile.write(r + '\t' + model.reactions.get_by_id(r).build_reaction_string() + '\t' + str(v) + '\n')
                # pathfile.close()
                sc = cnumber(substrate, specialgroup_begin)
                srd = reduction_degree(substrate, specialgroup_begin)
                pc = cnumber(product, specialgroup_begin)
                prd = reduction_degree(product, specialgroup_begin)
                cyield = rate * pc / sc / influx  # calculate the carbon yield
                if prd == 0:
                    cyieldrd = 0
                else:
                    cyieldrd = srd * pc / sc / prd
                metpair = [
                    s, substrate.formula, sc, srd, srd / sc, p,
                    product.formula, pc, prd, prd / pc, rate, cyield, cyieldrd,
                    cyieldrd - cyield
                ]
            else:
                metpair = "no path"

    return metpair
    def run(self, model, media):
        """This function mutates model."""

        # Select optimization solver
        model.solver = self.solver
        if self.solver == 'coinor_cbc':
            # Use all available processors
            model.solver.configuration.threads = -1

        # If specified, make all reactions reversible
        if self.is_all_reversible:
            for rct in model.reactions:
                rct.upper_bound = self.MAX_BOUND
                rct.lower_bound = self.MAX_BOUND * -1

        # Add custom bounds to reactions
        for rct_id, lb, ub in self.custom_bound_list:
            if rct_id in model.reactions:
                rct = model.reactions.get_by_id(rct_id)
                rct.lower_bound, rct.upper_bound = lb, ub

        # Filter out user specified genes to ko that are not in model.
        self.feature_ko_list = list(filter(lambda gene: gene in model.genes,
                                           self.feature_ko_list))
        # Knockout specified genes
        if self.feature_ko_list:
            cobra.manipulation.delete_model_genes(model, self.feature_ko_list)

        for rct_id in self.reaction_ko_list:
            if rct_id in model.reactions:
                rct = model.reactions.get_by_id(rct_id)
                rct.lower_bound, rct.upper_bound = 0, 0

        # Update exchange reaction variable bounds based on user
        # specified max uptakes. Add max uptake contraints.
        self.configure_media(model, media)

        # Set objective
        if self.target_reaction:
            model.objective = self.target_reaction

        # Set direction of the objective function, maximize by default.
        if self.is_minimize_objective:
            model.objective.direction = 'min'

        # Compute FBA solution
        if self.fba_type == 'pFBA':
            from cobra.flux_analysis import pfba
            fba_sol = pfba(model,
                           fraction_of_optimum=self.fraction_of_optimum_pfba)
        elif self.fba_type == 'Loopless FBA':
            # Run CycleFreeFlux algorithm
            fba_sol = cobra.flux_analysis.loopless_solution(model)
        else:
            # Run vanilla FBA
            fba_sol = model.optimize()

        # If specified, compute FVA solution
        fva_sol = None
        if self.fva_type != 'Neither':
            from cobra.flux_analysis import flux_variability_analysis as fva
            fva_sol = fva(model,
                          loopless=self.fva_type == 'Loopless FVA',
                          fraction_of_optimum=self.fraction_of_optimum_fva)
        
        # If specified, simulate all single gene knockouts
        essential_genes = set()
        if self.is_single_ko:
            essential_genes = cobra.flux_analysis.variability. \
                              find_essential_genes(model, threshold=1e-11)

        # Convert COBRApy model to kbase format
        fba_builder = KBaseFBABuilder.from_cobra(self.output_id,
                                                 model,
                                                 fba_sol,
                                                 media,
                                                 self.workspace)

        kbase_fba_obj = fba_builder.with_cobra_fva_solution(fva_sol).build()
        
        # TODO: essential_genes to this object in cobrakbase
        return kbase_fba_obj, fva_sol, fba_sol, essential_genes
Beispiel #18
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
Beispiel #19
0
    def _generate(
        self,
        model: "Model",
        solution: Optional["Solution"],
        fva: Optional[Union[float, pd.DataFrame]],
    ) -> None:
        """
        Prepare the data for the summary instance.

        Parameters
        ----------
        model : cobra.Model
            The metabolic model for which to generate a metabolite summary.
        solution : cobra.Solution, optional
            A previous model solution to use for generating the summary. If
            ``None``, the summary method will generate a parsimonious flux
            distribution.
        fva : pandas.DataFrame or float, optional
            Whether or not to include flux variability analysis in the output.
            If given, `fva` should either be a previous FVA solution matching the
            model or a float between 0 and 1 representing the fraction of the
            optimum objective to be searched.

        """
        super()._generate(model=model, solution=solution, fva=fva)

        coefficients = linear_reaction_coefficients(model)
        if solution is None:
            logger.info("Generating new parsimonious flux distribution.")
            solution = pfba(model)

        if isinstance(fva, float):
            logger.info("Performing flux variability analysis.")
            fva = flux_variability_analysis(
                model=model,
                reaction_list=model.boundary,
                fraction_of_optimum=fva,
            )
        if coefficients:
            self._objective: Dict["Reaction", float] = {
                rxn.copy(): coef
                for rxn, coef in coefficients.items()
            }
            self._objective_value: float = sum(
                solution[rxn.id] * coef
                for rxn, coef in self._objective.items())
        else:
            logger.warning(
                "Non-linear or non-reaction model objective. Falling back to minimal "
                "display.")
            self._objective = {
                Reaction(id="Expression", name="Expression"): float("nan")
            }
            self._objective_value: float = float("nan")
        self._boundary: List["Reaction"] = [
            rxn.copy() for rxn in sorted(model.boundary, key=attrgetter("id"))
        ]
        self._boundary_metabolites: List["Metabolite"] = [
            met.copy() for rxn in self._boundary for met in rxn.metabolites
        ]
        flux = pd.DataFrame(
            data=[
                (rxn.id, met.id, rxn.get_coefficient(met.id), solution[rxn.id])
                for rxn, met in zip(self._boundary, self._boundary_metabolites)
            ],
            columns=["reaction", "metabolite", "factor", "flux"],
            index=[r.id for r in self._boundary],
        )
        # Scale fluxes by stoichiometric coefficient.
        flux["flux"] *= flux["factor"]

        if fva is not None:
            flux = flux.join(fva)
            view = flux[["flux", "minimum", "maximum"]]
            # Set fluxes below model tolerance to zero.
            flux[["flux", "minimum",
                  "maximum"]] = view.where(view.abs() >= model.tolerance, 0)
            # Create the scaled compound flux.
            flux[["minimum",
                  "maximum"]] = flux[["minimum",
                                      "maximum"]].mul(flux["factor"], axis=0)
            # Negative factors invert the minimum/maximum relationship.
            negative = flux["factor"] < 0
            tmp = flux.loc[negative, "maximum"]
            flux.loc[negative, "maximum"] = flux.loc[negative, "minimum"]
            flux.loc[negative, "minimum"] = tmp
            # Add zero to turn negative zero into positive zero for nicer display later.
            flux[["flux", "minimum", "maximum"]] += 0
        else:
            # Set fluxes below model tolerance to zero.
            flux.loc[flux["flux"].abs() < model.tolerance, "flux"] = 0
            # Add zero to turn negative zero into positive zero for nicer display later.
            flux["flux"] += 0

        # Create production table from producing fluxes or zero fluxes where the
        # metabolite is a product in the reaction.
        is_produced = (flux["flux"] > 0) | ((flux["flux"] == 0) &
                                            (flux["factor"] > 0))
        if fva is not None:
            self.uptake_flux = flux.loc[
                is_produced,
                ["flux", "minimum", "maximum", "reaction", "metabolite"]].copy(
                )
        else:
            self.uptake_flux = flux.loc[
                is_produced, ["flux", "reaction", "metabolite"]].copy()

        # Create consumption table from consuming fluxes or zero fluxes where the
        # metabolite is a substrate in the reaction.
        is_consumed = (flux["flux"] < 0) | ((flux["flux"] == 0) &
                                            (flux["factor"] < 0))
        if fva is not None:
            self.secretion_flux = flux.loc[
                is_consumed,
                ["flux", "minimum", "maximum", "reaction", "metabolite"]].copy(
                )
        else:
            self.secretion_flux = flux.loc[
                is_consumed, ["flux", "reaction", "metabolite"]].copy()

        self._flux = flux