示例#1
0
def test_pfba(model, all_solvers):
    """Test pFBA functionality."""
    model.solver = all_solvers
    with model:
        add_pfba(model)
        with pytest.raises(ValueError):
            add_pfba(model)

    expression = model.objective.expression
    n_constraints = len(model.constraints)
    solution = pfba(model)
    assert solution.status == "optimal"
    assert solution.fluxes["Biomass_Ecoli_core"] == pytest.approx(0.8739,
                                                                  abs=1e-4,
                                                                  rel=0.0)
    assert solution.fluxes.abs().sum() == pytest.approx(518.4221,
                                                        abs=1e-4,
                                                        rel=0.0)

    # test changes to model reverted
    assert expression == model.objective.expression
    assert len(model.constraints) == n_constraints

    # needed?
    # Test desired_objective_value
    # desired_objective = 0.8
    # pfba(model, solver=solver,
    #                       desired_objective_value=desired_objective)
    # abs_x = [abs(i) for i in model.solution.x]
    # assert model.solution.status == "optimal"
    # assert abs(model.solution.f - desired_objective) < 0.001
    # assert abs(sum(abs_x) - 476.1594) < 0.001

    # TODO: parametrize fraction (DRY it up)
    # Test fraction_of_optimum
    solution = pfba(model, fraction_of_optimum=0.95)
    assert solution.status == "optimal"
    assert solution.fluxes["Biomass_Ecoli_core"] == pytest.approx(0.95 *
                                                                  0.8739,
                                                                  abs=1e-4,
                                                                  rel=0.0)
    abs_x = [abs(i) for i in solution.fluxes.values]
    assert sum(abs_x) == pytest.approx(493.4400, abs=1e-4, rel=0.0)

    # Infeasible solution
    model.reactions.ATPM.lower_bound = 500
    with warnings.catch_warnings():
        warnings.simplefilter("error", UserWarning)
        with pytest.raises((UserWarning, Infeasible, ValueError)):
            pfba(model)
示例#2
0
def test_pfba(model, all_solvers):
    """Test pFBA functionality."""
    model.solver = all_solvers
    with model:
        add_pfba(model)
        with pytest.raises(ValueError):
            add_pfba(model)

    expression = model.objective.expression
    n_constraints = len(model.constraints)
    solution = pfba(model)
    assert solution.status == "optimal"
    assert solution.fluxes["Biomass_Ecoli_core"] == \
        pytest.approx(0.8739, abs=1e-4, rel=0.0)
    assert solution.fluxes.abs().sum() == \
        pytest.approx(518.4221, abs=1e-4, rel=0.0)

    # test changes to model reverted
    assert expression == model.objective.expression
    assert len(model.constraints) == n_constraints

    # needed?
    # Test desired_objective_value
    # desired_objective = 0.8
    # pfba(model, solver=solver,
    #                       desired_objective_value=desired_objective)
    # abs_x = [abs(i) for i in model.solution.x]
    # assert model.solution.status == "optimal"
    # assert abs(model.solution.f - desired_objective) < 0.001
    # assert abs(sum(abs_x) - 476.1594) < 0.001

    # TODO: parametrize fraction (DRY it up)
    # Test fraction_of_optimum
    solution = pfba(model, fraction_of_optimum=0.95)
    assert solution.status == "optimal"
    assert solution.fluxes["Biomass_Ecoli_core"] == pytest.approx(
        0.95 * 0.8739, abs=1e-4, rel=0.0)
    abs_x = [abs(i) for i in solution.fluxes.values]
    assert sum(abs_x) == pytest.approx(493.4400, abs=1e-4, rel=0.0)

    # Infeasible solution
    model.reactions.ATPM.lower_bound = 500
    with warnings.catch_warnings():
        warnings.simplefilter("error", UserWarning)
        with pytest.raises((UserWarning, Infeasible, ValueError)):
            pfba(model)
示例#3
0
def moma(model, solution=None, linear=True):
    with model:
        add_moma(model=model, solution=solution, linear=lenear)
        solution = model.oprimize()
        return solutiondef, optimize_minimal_flux(*args, **kwargs)
        warn("optimize_minimal_flux has been renamed to pfba",
             DeprecationWarning)
        return pfba(*args, **kwargs)
        """
def test_metabolite_summary_to_frame_previous_solution(model, opt_solver, met):
    """Test metabolite summary.to_frame() of previous solution."""
    model.solver = opt_solver
    solution = pfba(model)

    expected_percent = [100.0, 88.4, 11.6]

    out_df = model.metabolites.get_by_id(met).summary(solution).to_frame()

    assert out_df['PERCENT'].round(1).tolist() == expected_percent
示例#5
0
def test_single_point_space(model):
    """Test the reduction of the sampling space to one point."""
    pfba_sol = pfba(model)
    pfba_const = model.problem.Constraint(
        sum(model.variables), ub=pfba_sol.objective_value)
    model.add_cons_vars(pfba_const)
    model.reactions.Biomass_Ecoli_core.lower_bound = \
        pfba_sol.fluxes.Biomass_Ecoli_core
    with pytest.raises(ValueError):
        s = sample(model, 1)
示例#6
0
def test_single_point_space(model):
    """Test the reduction of the sampling space to one point."""

    pfba_sol = pfba(model)
    pfba_const = model.problem.Constraint(
        sum(model.variables), ub=pfba_sol.objective_value)
    model.add_cons_vars(pfba_const)
    model.reactions.Biomass_Ecoli_core.lower_bound = \
        pfba_sol.fluxes.Biomass_Ecoli_core

    with pytest.raises(ValueError):
        s = sample(model, 1)
def test_metabolite_summary_to_table_previous_solution(model, opt_solver, met):
    """Test metabolite summary._to_table() of previous solution."""
    model.solver = opt_solver
    solution = pfba(model)

    expected_entry = [
        'PRODUCING CYTBD     100    43.6  2.0 h_c + 0.5 o2_c + '
        'q8h2_c --> h2o_c + 2.0 h_'
    ]

    with captured_output() as (out, _):
        print(model.metabolites.get_by_id(met).summary(solution))
        check_in_line(out.getvalue(), expected_entry)
示例#8
0
def get_pfba_fluxes(cobra_model):
    convert_to_irreversible(cobra_model)
    pfba_sol = pfba(cobra_model, solver='cglpk', already_irreversible=True)
    x_dict = dict(pfba_sol.x_dict.items())
    print("FBA JSON: %s, %f" % (pfba_sol.status, x_dict[BM_RXN]))

    # revert the solution to a reversible one:
    reverse_reactions = [x for x in x_dict.keys() if x.endswith('_reverse')]

    for rxn_id in reverse_reactions:
        fwd_id = rxn_id.replace('_reverse', '')
        x_dict[fwd_id] -= x_dict[rxn_id]
        x_dict.pop(rxn_id)
    return x_dict
示例#9
0
def fbaSol(m):
    if type(m) == cmo.DynamicModel:
        cm = m.cbModel
    else:
        cm = m
    solution = parsimonious.pfba(cm)
    sdf = pandas.DataFrame(solution.x_dict)
    sdf.columns = ['flux']
    sdf['rxn'] = sdf.index
    print('FBA solution')
    print(cm.summary())

    print('FVA=1. solution')
    print(cm.summary(fva=1.))

    return
示例#10
0
def add_moma(model, solution=None, linear=True):
    r"""Add constraints and objective representing for MOMA.

    This adds variables and constraints for the minimization of metabolic
    adjustment (MOMA) to the model.

    Parameters
    ----------
    model : cobra.Model
        The model to add MOMA constraints and objective to.
    solution : cobra.Solution, optional
        A previous solution to use as a reference. If no solution is given,
        one will be computed using pFBA.
    linear : bool, optional
        Whether to use the linear MOMA formulation or not (default True).

    Notes
    -----
    In the original MOMA [1]_ specification one looks for the flux distribution
    of the deletion (v^d) closest to the fluxes without the deletion (v).
    In math this means:

    minimize \sum_i (v^d_i - v_i)^2
    s.t. Sv^d = 0
         lb_i <= v^d_i <= ub_i

    Here, we use a variable transformation v^t := v^d_i - v_i. Substituting
    and using the fact that Sv = 0 gives:

    minimize \sum_i (v^t_i)^2
    s.t. Sv^d = 0
         v^t = v^d_i - v_i
         lb_i <= v^d_i <= ub_i

    So basically we just re-center the flux space at the old solution and then
    find the flux distribution closest to the new zero (center). This is the
    same strategy as used in cameo.

    In the case of linear MOMA [2]_, we instead minimize \sum_i abs(v^t_i). The
    linear MOMA is typically significantly faster. Also quadratic MOMA tends
    to give flux distributions in which all fluxes deviate from the reference
    fluxes a little bit whereas linear MOMA tends to give flux distributions
    where the majority of fluxes are the same reference with few fluxes
    deviating a lot (typical effect of L2 norm vs L1 norm).

    The former objective function is saved in the optlang solver interface as
    ``"moma_old_objective"`` and this can be used to immediately extract the
    value of the former objective after MOMA optimization.

    See Also
    --------
    pfba : parsimonious FBA

    References
    ----------
    .. [1] Segrè, Daniel, Dennis Vitkup, and George M. Church. “Analysis of
           Optimality in Natural and Perturbed Metabolic Networks.”
           Proceedings of the National Academy of Sciences 99, no. 23
           (November 12, 2002): 15112. https://doi.org/10.1073/pnas.232349399.
    .. [2] Becker, Scott A, Adam M Feist, Monica L Mo, Gregory Hannum,
           Bernhard Ø Palsson, and Markus J Herrgard. “Quantitative
           Prediction of Cellular Metabolism with Constraint-Based Models:
           The COBRA Toolbox.” Nature Protocols 2 (March 29, 2007): 727.
    """
    if 'moma_old_objective' in model.solver.variables:
        raise ValueError('model is already adjusted for MOMA')

    # Fall back to default QP solver if current one has no QP capability
    if not linear:
        model.solver = sutil.choose_solver(model, qp=True)

    if solution is None:
        solution = pfba(model)
    prob = model.problem
    v = prob.Variable("moma_old_objective")
    c = prob.Constraint(model.solver.objective.expression - v,
                        lb=0.0,
                        ub=0.0,
                        name="moma_old_objective_constraint")
    to_add = [v, c]
    model.objective = prob.Objective(Zero, direction="min", sloppy=True)
    obj_vars = []
    for r in model.reactions:
        flux = solution.fluxes[r.id]
        if linear:
            components = sutil.add_absolute_expression(model,
                                                       r.flux_expression,
                                                       name="moma_dist_" +
                                                       r.id,
                                                       difference=flux,
                                                       add=False)
            to_add.extend(components)
            obj_vars.append(components.variable)
        else:
            dist = prob.Variable("moma_dist_" + r.id)
            const = prob.Constraint(r.flux_expression - dist,
                                    lb=flux,
                                    ub=flux,
                                    name="moma_constraint_" + r.id)
            to_add.extend([dist, const])
            obj_vars.append(dist**2)
    model.add_cons_vars(to_add)
    if linear:
        model.objective.set_linear_coefficients({v: 1.0 for v in obj_vars})
    else:
        model.objective = prob.Objective(add(obj_vars),
                                         direction="min",
                                         sloppy=True)
示例#11
0
def test_metabolite_summary_previous_solution(model, opt_solver, met):
    """Test metabolite summary of previous solution."""
    model.solver = opt_solver
    solution = pfba(model)
    model.metabolites.get_by_id(met).summary(solution)
示例#12
0
文件: room.py 项目: mmundy42/cobrapy
def add_room(model, solution=None, linear=False, delta=0.03, epsilon=1E-03):
    r"""
    Add constraints and objective for ROOM.

    This function adds variables and constraints for applying regulatory
    on/off minimization (ROOM) to the model.

    Parameters
    ----------
    model : cobra.Model
        The model to add ROOM constraints and objective to.
    solution : cobra.Solution, optional
        A previous solution to use as a reference. If no solution is given,
        one will be computed using pFBA.
    linear : bool, optional
        Whether to use the linear ROOM formulation or not (default False).
    delta: float, optional
        The relative tolerance range which is additive in nature
        (default 0.03).
    epsilon: float, optional
        The absolute range of tolerance which is multiplicative
        (default 0.001).

    Notes
    -----
    The formulation used here is the same as stated in the original paper [1]_.
    The mathematical expression is given below:

    minimize \sum_{i=1}^m y^i
    s.t. Sv = 0
         v_min <= v <= v_max
         v_j = 0
         j ∈ A
         for 1 <= i <= m
         v_i - y_i(v_{max,i} - w_i^u) <= w_i^u      (1)
         v_i - y_i(v_{min,i} - w_i^l) <= w_i^l      (2)
         y_i ∈ {0,1}                                (3)
         w_i^u = w_i + \delta|w_i| + \epsilon
         w_i^l = w_i - \delta|w_i| - \epsilon

    So, for the linear version of the ROOM , constraint (3) is relaxed to
    0 <= y_i <= 1.

    See Also
    --------
    pfba : parsimonious FBA

    References
    ----------
    .. [1] Tomer Shlomi, Omer Berkman and Eytan Ruppin, "Regulatory on/off
     minimization of metabolic flux changes after genetic perturbations",
     PNAS 2005 102 (21) 7695-7700; doi:10.1073/pnas.0406346102

    """

    if 'room_old_objective' in model.solver.variables:
        raise ValueError('model is already adjusted for ROOM')

    # optimizes if no reference solution is provided
    if solution is None:
        solution = pfba(model)

    prob = model.problem
    variable = prob.Variable("room_old_objective", ub=solution.objective_value)
    constraint = prob.Constraint(
        model.solver.objective.expression - variable,
        ub=0.0,
        lb=0.0,
        name="room_old_objective_constraint"
    )
    model.objective = prob.Objective(Zero, direction="min", sloppy=True)
    vars_and_cons = [variable, constraint]
    obj_vars = []

    for rxn in model.reactions:
        flux = solution.fluxes[rxn.id]

        if linear:
            y = prob.Variable("y_" + rxn.id, lb=0, ub=1)
            delta = epsilon = 0.0
        else:
            y = prob.Variable("y_" + rxn.id, type="binary")

        # upper constraint
        w_u = flux + (delta * abs(flux)) + epsilon
        upper_const = prob.Constraint(
            rxn.flux_expression - y * (rxn.upper_bound - w_u),
            ub=w_u, name="room_constraint_upper_" + rxn.id)
        # lower constraint
        w_l = flux - (delta * abs(flux)) - epsilon
        lower_const = prob.Constraint(
            rxn.flux_expression - y * (rxn.lower_bound - w_l),
            lb=w_l, name="room_constraint_lower_" + rxn.id)
        vars_and_cons.extend([y, upper_const, lower_const])
        obj_vars.append(y)

    model.add_cons_vars(vars_and_cons)
    model.objective.set_linear_coefficients({v: 1.0 for v in obj_vars})
示例#13
0
def add_room(model, solution=None, linear=False, delta=0.03, epsilon=1E-03):
    r"""
    Add constraints and objective for ROOM.

    This function adds variables and constraints for applying regulatory
    on/off minimization (ROOM) to the model.

    Parameters
    ----------
    model : cobra.Model
        The model to add ROOM constraints and objective to.
    solution : cobra.Solution, optional
        A previous solution to use as a reference. If no solution is given,
        one will be computed using pFBA.
    linear : bool, optional
        Whether to use the linear ROOM formulation or not (default False).
    delta: float, optional
        The relative tolerance range which is additive in nature
        (default 0.03).
    epsilon: float, optional
        The absolute range of tolerance which is multiplicative
        (default 0.001).

    Notes
    -----
    The formulation used here is the same as stated in the original paper [1]_.
    The mathematical expression is given below:

    minimize \sum_{i=1}^m y^i
    s.t. Sv = 0
         v_min <= v <= v_max
         v_j = 0
         j ∈ A
         for 1 <= i <= m
         v_i - y_i(v_{max,i} - w_i^u) <= w_i^u      (1)
         v_i - y_i(v_{min,i} - w_i^l) <= w_i^l      (2)
         y_i ∈ {0,1}                                (3)
         w_i^u = w_i + \delta|w_i| + \epsilon
         w_i^l = w_i - \delta|w_i| - \epsilon

    So, for the linear version of the ROOM , constraint (3) is relaxed to
    0 <= y_i <= 1.

    See Also
    --------
    pfba : parsimonious FBA

    References
    ----------
    .. [1] Tomer Shlomi, Omer Berkman and Eytan Ruppin, "Regulatory on/off
     minimization of metabolic flux changes after genetic perturbations",
     PNAS 2005 102 (21) 7695-7700; doi:10.1073/pnas.0406346102

    """

    if 'room_old_objective' in model.solver.variables:
        raise ValueError('model is already adjusted for ROOM')

    # optimizes if no reference solution is provided
    if solution is None:
        solution = pfba(model)

    prob = model.problem
    variable = prob.Variable("room_old_objective", ub=solution.objective_value)
    constraint = prob.Constraint(model.solver.objective.expression - variable,
                                 ub=0.0,
                                 lb=0.0,
                                 name="room_old_objective_constraint")
    model.objective = prob.Objective(Zero, direction="min", sloppy=True)
    vars_and_cons = [variable, constraint]
    obj_vars = []

    for rxn in model.reactions:
        flux = solution.fluxes[rxn.id]

        if linear:
            y = prob.Variable("y_" + rxn.id, lb=0, ub=1)
            delta = epsilon = 0.0
        else:
            y = prob.Variable("y_" + rxn.id, type="binary")

        # upper constraint
        w_u = flux + (delta * abs(flux)) + epsilon
        upper_const = prob.Constraint(rxn.flux_expression - y *
                                      (rxn.upper_bound - w_u),
                                      ub=w_u,
                                      name="room_constraint_upper_" + rxn.id)
        # lower constraint
        w_l = flux - (delta * abs(flux)) - epsilon
        lower_const = prob.Constraint(rxn.flux_expression - y *
                                      (rxn.lower_bound - w_l),
                                      lb=w_l,
                                      name="room_constraint_lower_" + rxn.id)
        vars_and_cons.extend([y, upper_const, lower_const])
        obj_vars.append(y)

    model.add_cons_vars(vars_and_cons)
    model.objective.set_linear_coefficients({v: 1.0 for v in obj_vars})
示例#14
0
def test_metabolite_summary_previous_solution(
        model, opt_solver, met):
    """Test metabolite summary of previous solution."""
    model.solver = opt_solver
    solution = pfba(model)
    model.metabolites.get_by_id(met).summary(solution)
示例#15
0
文件: moma.py 项目: opencobra/cobrapy
def add_moma(model, solution=None, linear=True):
    r"""Add constraints and objective representing for MOMA.

    This adds variables and constraints for the minimization of metabolic
    adjustment (MOMA) to the model.

    Parameters
    ----------
    model : cobra.Model
        The model to add MOMA constraints and objective to.
    solution : cobra.Solution, optional
        A previous solution to use as a reference. If no solution is given,
        one will be computed using pFBA.
    linear : bool, optional
        Whether to use the linear MOMA formulation or not (default True).

    Notes
    -----
    In the original MOMA [1]_ specification one looks for the flux distribution
    of the deletion (v^d) closest to the fluxes without the deletion (v).
    In math this means:

    minimize \sum_i (v^d_i - v_i)^2
    s.t. Sv^d = 0
         lb_i <= v^d_i <= ub_i

    Here, we use a variable transformation v^t := v^d_i - v_i. Substituting
    and using the fact that Sv = 0 gives:

    minimize \sum_i (v^t_i)^2
    s.t. Sv^d = 0
         v^t = v^d_i - v_i
         lb_i <= v^d_i <= ub_i

    So basically we just re-center the flux space at the old solution and then
    find the flux distribution closest to the new zero (center). This is the
    same strategy as used in cameo.

    In the case of linear MOMA [2]_, we instead minimize \sum_i abs(v^t_i). The
    linear MOMA is typically significantly faster. Also quadratic MOMA tends
    to give flux distributions in which all fluxes deviate from the reference
    fluxes a little bit whereas linear MOMA tends to give flux distributions
    where the majority of fluxes are the same reference with few fluxes
    deviating a lot (typical effect of L2 norm vs L1 norm).

    The former objective function is saved in the optlang solver interface as
    ``"moma_old_objective"`` and this can be used to immediately extract the
    value of the former objective after MOMA optimization.

    See Also
    --------
    pfba : parsimonious FBA

    References
    ----------
    .. [1] Segrè, Daniel, Dennis Vitkup, and George M. Church. “Analysis of
           Optimality in Natural and Perturbed Metabolic Networks.”
           Proceedings of the National Academy of Sciences 99, no. 23
           (November 12, 2002): 15112. https://doi.org/10.1073/pnas.232349399.
    .. [2] Becker, Scott A, Adam M Feist, Monica L Mo, Gregory Hannum,
           Bernhard Ø Palsson, and Markus J Herrgard. “Quantitative
           Prediction of Cellular Metabolism with Constraint-Based Models:
           The COBRA Toolbox.” Nature Protocols 2 (March 29, 2007): 727.
    """
    if 'moma_old_objective' in model.solver.variables:
        raise ValueError('model is already adjusted for MOMA')

    # Fall back to default QP solver if current one has no QP capability
    if not linear:
        model.solver = sutil.choose_solver(model, qp=True)

    if solution is None:
        solution = pfba(model)
    prob = model.problem
    v = prob.Variable("moma_old_objective")
    c = prob.Constraint(model.solver.objective.expression - v,
                        lb=0.0, ub=0.0, name="moma_old_objective_constraint")
    to_add = [v, c]
    model.objective = prob.Objective(Zero, direction="min", sloppy=True)
    obj_vars = []
    for r in model.reactions:
        flux = solution.fluxes[r.id]
        if linear:
            components = sutil.add_absolute_expression(
                model, r.flux_expression, name="moma_dist_" + r.id,
                difference=flux, add=False)
            to_add.extend(components)
            obj_vars.append(components.variable)
        else:
            dist = prob.Variable("moma_dist_" + r.id)
            const = prob.Constraint(r.flux_expression - dist, lb=flux, ub=flux,
                                    name="moma_constraint_" + r.id)
            to_add.extend([dist, const])
            obj_vars.append(dist ** 2)
    model.add_cons_vars(to_add)
    if linear:
        model.objective.set_linear_coefficients({v: 1.0 for v in obj_vars})
    else:
        model.objective = prob.Objective(
            add(obj_vars), direction="min", sloppy=True)
示例#16
0
def main():
    '''
    Reproduce results from
    ** Enjalbert et al 2015
    With Single EC model
    '''
    args = options()
    verbose = args.verbose

    bmname = 'BIOMASS_Ecoli_core_w_GAM'
    m = cobra.io.read_sbml_model(args.model)
    exrxnname = ['EX_glc__D_e', 'EX_ac_e', 'EX_o2_e']
    exrxn = []

    otname = args.pathout+'tab_v.csv'
    if args.constraintAcSec:
        m.reactions.get_by_id('EX_ac_e').upper_bound = 3
        otname = args.pathout+'maxAcOut_tab_v.csv'
        
    for n in exrxnname:
        exrxn.append(m.reactions.get_by_id(n))

    vsp = np.linspace(-10, 0, 11)
    for r in exrxn:
        r.lower_bound = vsp[0]

    msol = parsimonious.pfba(m)
    df_tmp = msol.x_dict[exrxnname+[bmname]]

    idxlab = '_'.join(3*['%.1f' % vsp[0]])
    df = pandas.DataFrame(data=df_tmp).T
    df.index = [idxlab]

    # with glucose
    for r in exrxn:
        for v in vsp:
            r.lower_bound = v
            msol = parsimonious.pfba(m)
            df_tmp = msol.x_dict[exrxnname+[bmname]]
            lab = []
            for rl in exrxn:
                lab.append('%.1f' % rl.lower_bound)
            df_tmp.name = '_'.join(lab)
            df = df.append(df_tmp)
        r.lower_bound = vsp[0]

    # without glucose
    exrxn[0].lower_bound = 0
    for r in exrxn[1:]:
        for v in vsp:
            r.lower_bound = v
            try:
                msol = parsimonious.pfba(m)
                df_tmp = msol.x_dict[exrxnname+[bmname]]
            except:
                msol = None
                df_tmp = pandas.Series(dict(zip(exrxnname+[bmname], 4*[np.nan])))
            lab = []
            for rl in exrxn:
                lab.append('%.1f' % rl.lower_bound)
            df_tmp.name = '_'.join(lab)
            df = df.append(df_tmp)
        r.lower_bound = vsp[0]

    df.to_csv(otname)
    return
示例#17
0
def MinFluxSolve(model,
                 PrintStatus=True,
                 PrimObjVal=True,
                 norm="linear",
                 weighting='uniform',
                 ExcReacs=[],
                 adjusted=False,
                 tol_step=1e-9,
                 max_tol=1e-8,
                 DisplayMsg=True,
                 cobra=True,
                 subopt=1.0):
    """ norm = "linear" | "euclidean"
        weighting = "uniform" | "random" """

    #    """Temporary fix, need to change the structure of saving solution objects"""
    if norm == "linear" and weighting == "uniform" and (not ExcReacs) and (
            not adjusted) and cobra:
        #            """Temporary fix, need to change the structure of saving solution objects"""
        #            from cobra.flux_analysis.parsimonious import pfba
        sol = None
        try:
            sol = pfba(model, fraction_of_optimum=subopt)
        except Infeasible:
            if DisplayMsg:
                print("no solution")
            model.UpdateSolution(None)
            return
        model.UpdateSolution(sol)
        if DisplayMsg:
            try:
                print(sol.status)
            except AttributeError:
                print("no solution")

        return
#            return sol.fluxes
#
#    RemoveReverse(model)
    model.Solve(PrintStatus=PrintStatus)
    if model.Optimal():
        state = model.GetState()
        objective = model.GetObjective()
        objval = model.GetObjVal()
        objbounds = (objval - abs(1 - subopt) * objval,
                     objval + abs(1 - subopt) * objval)
        #SetValAsConstraint(model,name="MinFlux_Objective", objval=objval,objective=objective)
        #model.SetSumReacsConstraint(reacsdic=objective, bounds=objval,name="MinFlux_Objective")
        model.SetSumReacsConstraint(reacsdic=objective,
                                    bounds=objbounds,
                                    name="MinFlux_Objective")
        if norm == "linear":
            #modify.convert_to_irreversible(model)
            model.SplitRev()
            SetLinearMinFluxObjective(model=model,
                                      weighting=weighting,
                                      ExcReacs=ExcReacs)
            #            ExcReacs = model.GetReactionNames(ExcReacs)
            #            for reaction in model.reactions:
            #                if not (reaction.id.endswith("_sum_reaction") or
            #                        reaction.id.endswith("_metbounds") or
            #                        (reaction.id.split('_reverse')[0] in ExcReacs)):
            #                    if weighting == 'uniform':
            #                        reaction.objective_coefficient = 1
            #                    elif weighting == 'random':
            #                        reaction.objective_coefficient = random.random()
            #                    else:
            #                        #print "wrong weighting"
            #                        raise NameError(weighting)

            model.SetObjDirec("Min")
            model.Solve(PrintStatus=DisplayMsg)

            if adjusted:
                Tolerance = 0
                while (model.Optimal() == False and Tolerance < max_tol):
                    Tolerance = Tolerance + tol_step
                    model.DelObjAsConstraint("MinFlux_Objective")
                    bounds = (objval - Tolerance, objval + Tolerance)
                    if DisplayMsg:
                        print('Objective value = ' + str(objval))
                        print("Modified 'MinFlux_Objective' bounds = " +
                              str(bounds))
                    model.SetSumReacsConstraint(reacsdic=objective,
                                                bounds=bounds,
                                                name="MinFlux_Objective")
                    model.SetObjDirec("Min")
                    model.Solve(PrintStatus=DisplayMsg)
            #modify.revert_to_reversible(model)
            model.MergeRev(True)
            #print(model.GetConstraints())

        if norm == "euclidean":
            num_reacs = len(model.reactions)
            model.quadratic_component = scipy.sparse.identity(
                num_reacs).todok()
            model.SetObjDirec("Min")
            model.Solve(PrintStatus=DisplayMsg)

#"""This whole section used to be run after, either linear or euclidean norms, but tabbed to accomodate temporary change described above"""

        model.DelObjAsConstraint("MinFlux_Objective")
        model.SetState(state, IncSol=False)
        if PrimObjVal:
            try:
                model.solution.objective_value = state[
                    "solution"].objective_value
            except AttributeError:
                pass
        #return model.GetSol()
    else:
        print("not feasible")