Exemplo n.º 1
0
 def test_add_reactions(self):
     r1 = Reaction('r1')
     r1.add_metabolites({Metabolite('A'): -1, Metabolite('B'): 1})
     r1.lower_bound, r1.upper_bound = -999999., 999999.
     r2 = Reaction('r2')
     r2.add_metabolites({
         Metabolite('A'): -1,
         Metabolite('C'): 1,
         Metabolite('D'): 1
     })
     r2.lower_bound, r2.upper_bound = 0., 999999.
     r2.objective_coefficient = 3.
     self.model.add_reactions([r1, r2])
     self.assertEqual(self.model.reactions[-2], r1)
     self.assertEqual(self.model.reactions[-1], r2)
     self.assertTrue(
         isinstance(self.model.reactions[-2].reverse_variable,
                    self.model.solver.interface.Variable))
     self.assertEqual(
         self.model.objective.expression.coeff(
             self.model.reactions.
             Biomass_Ecoli_core_N_LPAREN_w_FSLASH_GAM_RPAREN__Nmet2.
             forward_variable), 1.)
     self.assertEqual(
         self.model.objective.expression.coeff(
             self.model.reactions.
             Biomass_Ecoli_core_N_LPAREN_w_FSLASH_GAM_RPAREN__Nmet2.
             reverse_variable), -1.)
     self.assertEqual(
         self.model.objective.expression.coeff(
             self.model.reactions.r2.forward_variable), 3.)
     self.assertEqual(
         self.model.objective.expression.coeff(
             self.model.reactions.r2.reverse_variable), -3.)
        def test_one_left_to_right_reaction_set_positive_ub(self):

            model = Model("Toy Model")

            m1 = Metabolite("M1")
            d1 = Reaction("ex1")
            d1.add_metabolites({m1: -1})
            d1.upper_bound = 0
            d1.lower_bound = -1000
            model.add_reactions([d1])
            self.assertEqual(d1.reverse_variable.lb, 0)
            self.assertEqual(d1.reverse_variable.ub, 1000)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.lower_bound, -1000)
            self.assertEqual(d1._upper_bound, 0)
            self.assertEqual(d1.upper_bound, 0)
            self.assertEqual(d1.forward_variable.lb, 0)
            self.assertEqual(d1.forward_variable.ub, 0)
            d1.upper_bound = .1
            self.assertEqual(d1.forward_variable.lb, 0)
            self.assertEqual(d1.forward_variable.ub, .1)
            self.assertEqual(d1.reverse_variable.lb, 0)
            self.assertEqual(d1.reverse_variable.ub, 1000)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.upper_bound, .1)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.upper_bound, .1)
        def test_weird_left_to_right_reaction_issue(self):

            model = Model("Toy Model")

            m1 = Metabolite("M1")
            d1 = Reaction("ex1")
            d1.add_metabolites({m1: -1})
            d1.upper_bound = 0
            d1.lower_bound = -1000
            # print d1.reaction, d1.lower_bound, d1.upper_bound
            model.add_reactions([d1])
            self.assertFalse(d1.reversibility)
            self.assertEqual(d1.lower_bound, -1000)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.upper_bound, 0)
            self.assertEqual(d1._upper_bound, 0)
            with TimeMachine() as tm:
                d1.knock_out(time_machine=tm)
                self.assertEqual(d1.lower_bound, 0)
                self.assertEqual(d1._lower_bound, 0)
                self.assertEqual(d1.upper_bound, 0)
                self.assertEqual(d1._upper_bound, 0)
            self.assertEqual(d1.lower_bound, -1000)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.upper_bound, 0)
            self.assertEqual(d1._upper_bound, 0)
Exemplo n.º 4
0
    def _add_target_constraints(self, c):
        """Add the target constraints to the dual model"""
        targets = self._target_constraints

        w_reactions = []
        for i, target in enumerate(targets):
            assert isinstance(target, optlang.interface.Constraint)
            if not target.is_Linear:
                raise ValueError("Target constraints must be linear.")
            if (target.lb is None
                    and target.ub is None) or (target.lb is not None
                                               and target.ub is not None):
                raise ValueError(
                    "Target constraints must be one-sided inequalities.")
            coefficients_dict = target.expression.as_coefficients_dict()
            w_reac = Reaction("w_" + str(i))
            w_reac.lower_bound = c
            if target.ub is not None:
                coefficients = {
                    self._dual_model.metabolites.get_by_id(var.name): coef
                    for var, coef in coefficients_dict.items()
                    if var.name in self._dual_model.metabolites
                }
            elif target.lb is not None:
                coefficients = {
                    self._dual_model.metabolites.get_by_id(var.name): -coef
                    for var, coef in coefficients_dict.items()
                    if var.name in self._dual_model.metabolites
                }
            w_reac.add_metabolites(coefficients)
            w_reactions.append(w_reac)
        self._dual_model.add_reactions(w_reactions)

        return None
Exemplo n.º 5
0
    def _add_target_constraints(self, c):
        """Add the target constraints to the dual model"""
        targets = self._target_constraints

        w_reactions = []
        for i, target in enumerate(targets):
            assert isinstance(target, optlang.interface.Constraint)
            if not target.is_Linear:
                raise ValueError("Target constraints must be linear.")
            if (target.lb is None and target.ub is None) or (target.lb is not None and target.ub is not None):
                raise ValueError("Target constraints must be one-sided inequalities.")
            coefficients_dict = target.expression.as_coefficients_dict()
            w_reac = Reaction("w_" + str(i))
            w_reac.lower_bound = c
            if target.ub is not None:
                coefficients = {
                    self._dual_model.metabolites.get_by_id(var.name): coef for var, coef in coefficients_dict.items()
                    if var.name in self._dual_model.metabolites
                }
            elif target.lb is not None:
                coefficients = {
                    self._dual_model.metabolites.get_by_id(var.name): -coef for var, coef in coefficients_dict.items()
                    if var.name in self._dual_model.metabolites
                }
            w_reac.add_metabolites(coefficients)
            w_reactions.append(w_reac)
        self._dual_model.add_reactions(w_reactions)

        return None
Exemplo n.º 6
0
def create_adapter_reactions(original_metabolites, database, mapping,
                             compartment_regexp):
    adapter_reactions = []
    for metabolite in original_metabolites:  # model is the original host model
        if not compartment_regexp.match(metabolite.id):
            continue

        name = metabolite.id[0:-2]
        try:
            mapped_name = mapping[name]
        except KeyError:
            continue
            # print name, 'N/A'
        adapter_reaction = Reaction('adapter_' + metabolite.id + '_' +
                                    mapped_name)
        adapter_reaction.lower_bound = -1000
        try:
            adapter_reaction.add_metabolites({
                metabolite:
                -1,
                database.metabolites.get_by_id(mapped_name):
                1
            })
        except KeyError:
            pass
        else:
            adapter_reactions.append(adapter_reaction)

    return adapter_reactions
Exemplo n.º 7
0
        def test_one_left_to_right_reaction_set_positive_ub(self):

            model = Model("Toy Model")

            m1 = Metabolite("M1")
            d1 = Reaction("ex1")
            d1.add_metabolites({m1: -1})
            d1.upper_bound = 0
            d1.lower_bound = -1000
            model.add_reactions([d1])
            self.assertEqual(d1.reverse_variable.lb, 0)
            self.assertEqual(d1.reverse_variable.ub, 1000)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.lower_bound, -1000)
            self.assertEqual(d1._upper_bound, 0)
            self.assertEqual(d1.upper_bound, 0)
            self.assertEqual(d1.forward_variable.lb, 0)
            self.assertEqual(d1.forward_variable.ub, 0)
            d1.upper_bound = .1
            self.assertEqual(d1.forward_variable.lb, 0)
            self.assertEqual(d1.forward_variable.ub, .1)
            self.assertEqual(d1.reverse_variable.lb, 0)
            self.assertEqual(d1.reverse_variable.ub, 1000)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.upper_bound, .1)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.upper_bound, .1)
Exemplo n.º 8
0
        def test_weird_left_to_right_reaction_issue(self):

            model = Model("Toy Model")

            m1 = Metabolite("M1")
            d1 = Reaction("ex1")
            d1.add_metabolites({m1: -1})
            d1.upper_bound = 0
            d1.lower_bound = -1000
            # print d1.reaction, d1.lower_bound, d1.upper_bound
            model.add_reactions([d1])
            self.assertFalse(d1.reversibility)
            self.assertEqual(d1.lower_bound, -1000)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.upper_bound, 0)
            self.assertEqual(d1._upper_bound, 0)
            with TimeMachine() as tm:
                d1.knock_out(time_machine=tm)
                self.assertEqual(d1.lower_bound, 0)
                self.assertEqual(d1._lower_bound, 0)
                self.assertEqual(d1.upper_bound, 0)
                self.assertEqual(d1._upper_bound, 0)
            self.assertEqual(d1.lower_bound, -1000)
            self.assertEqual(d1._lower_bound, -1000)
            self.assertEqual(d1.upper_bound, 0)
            self.assertEqual(d1._upper_bound, 0)
 def test_add_reactions(self):
     r1 = Reaction('r1')
     r1.add_metabolites({Metabolite('A'): -1, Metabolite('B'): 1})
     r1.lower_bound, r1.upper_bound = -999999., 999999.
     r2 = Reaction('r2')
     r2.add_metabolites({Metabolite('A'): -1, Metabolite('C'): 1, Metabolite('D'): 1})
     r2.lower_bound, r2.upper_bound = 0., 999999.
     r2.objective_coefficient = 3.
     self.model.add_reactions([r1, r2])
     self.assertEqual(self.model.reactions[-2], r1)
     self.assertEqual(self.model.reactions[-1], r2)
     self.assertTrue(isinstance(self.model.reactions[-2].reverse_variable, self.model.solver.interface.Variable))
     self.assertEqual(self.model.objective.expression.coeff(
         self.model.reactions.Biomass_Ecoli_core_N_LPAREN_w_FSLASH_GAM_RPAREN__Nmet2.forward_variable), 1.)
     self.assertEqual(self.model.objective.expression.coeff(
         self.model.reactions.Biomass_Ecoli_core_N_LPAREN_w_FSLASH_GAM_RPAREN__Nmet2.reverse_variable), -1.)
     self.assertEqual(self.model.objective.expression.coeff(self.model.reactions.r2.forward_variable), 3.)
     self.assertEqual(self.model.objective.expression.coeff(self.model.reactions.r2.reverse_variable), -3.)
Exemplo n.º 10
0
def construct_universal_model(list_of_db_prefixes):
    # Select which reactions to include in universal reaction database

    reaction_selection = reac_prop[[
        any([source.startswith(db_prefix) for db_prefix in list_of_db_prefixes]) and re.match('.*biomass.*', source,
                                                                                              re.I) is None for source
        in reac_prop.Source]]
    reactions = list()
    for index, row in reaction_selection.iterrows():
        try:
            stoichiometry = parse_reaction(row.Equation, rev_arrow='=')
        except ValueError:
            continue
        else:
            for met, coeff in stoichiometry.items():
                met.name = chem_prop.loc[met.id]['name']
                try:
                    met.formula = Formula(chem_prop.loc[met.id].formula)
                except:
                    logger.debug('Cannot parse formula %s. Skipping formula' % chem_prop.loc[met.id].formula)
                    continue
                # if met.formula.weight is None:
                #     logger.debug('Cannot calculate weight for formula %s. Skipping reaction %s' % (met.formula, row.Equation))
                #     # print('Cannot calculate weight for formula %s. Skipping reaction %s' % (met.formula, row.Equation))
                #     continue
                try:
                    met.charge = int(chem_prop.loc[met.id].charge)
                except (ValueError, TypeError):
                    logger.debug('Cannot parse charge %s. Skipping charge' % chem_prop.loc[met.id].charge)
                    pass
                rest = chem_prop.loc[met.id].to_dict()
                met.annotation = dict((key, rest[key]) for key in rest if key in ('mass', 'InChI', 'source'))
            mets = [met.id for met in stoichiometry.keys()]
            if len(mets) != len(set(mets)):
                continue
            reaction = Reaction(index)
            reaction.add_metabolites(stoichiometry)
            try:
                if len(reaction.check_mass_balance()) != 0:
                    continue
            except AttributeError as e:
                logger.debug(str(e))
                continue
            if row.Balance:
                reaction.lower_bound = -1 * reaction.upper_bound
            reaction.name = row['Source']
            row = row.fillna("")
            rest = row.to_dict()
            reaction.annotation = dict((key, rest[key]) for key in rest if key in ('EC', 'Description'))
            reactions.append(reaction)

    model = Model('metanetx_universal_model_' + '_'.join(list_of_db_prefixes), solver_interface=optlang.interface)
    model.add_reactions(reactions)
    # Add sinks for all metabolites
    for metabolite in model.metabolites:
        model.add_demand(metabolite)
    return model
Exemplo n.º 11
0
def construct_universal_model(list_of_db_prefixes):
    # Select which reactions to include in universal reaction database

    reaction_selection = reac_prop[[
        any([source.startswith(db_prefix) for db_prefix in list_of_db_prefixes]) and re.match('.*biomass.*', source,
                                                                                              re.I) is None for source
        in reac_prop.Source]]
    reactions = list()
    for index, row in reaction_selection.iterrows():
        try:
            stoichiometry = parse_reaction(row.Equation, rev_arrow='=')
        except ValueError:
            continue
        else:
            for met, coeff in stoichiometry.iteritems():
                met.name = chem_prop.loc[met.id]['name']
                try:
                    met.formula = Formula(chem_prop.loc[met.id].formula)
                except:
                    logger.debug('Cannot parse formula %s. Skipping formula' % chem_prop.loc[met.id].formula)
                    continue
                # if met.formula.weight is None:
                #     logger.debug('Cannot calculate weight for formula %s. Skipping reaction %s' % (met.formula, row.Equation))
                #     # print('Cannot calculate weight for formula %s. Skipping reaction %s' % (met.formula, row.Equation))
                #     continue
                try:
                    met.charge = int(chem_prop.loc[met.id].charge)
                except (ValueError, TypeError):
                    logger.debug('Cannot parse charge %s. Skipping charge' % chem_prop.loc[met.id].charge)
                    pass
                rest = chem_prop.loc[met.id].to_dict()
                met.annotation = dict((key, rest[key]) for key in rest if key in ('mass', 'InChI', 'source'))
            mets = [met.id for met in stoichiometry.keys()]
            if len(mets) != len(set(mets)):
                continue
            reaction = Reaction(index)
            reaction.add_metabolites(stoichiometry)
            if reaction.check_mass_balance() != []:
                continue
            if row.Balance:
                reaction.lower_bound = -1 * reaction.upper_bound
            reaction.name = row['Source']
            rest = row.to_dict()
            reaction.annotation = dict((key, rest[key]) for key in rest if key in ('EC', 'Description'))
            reactions.append(reaction)

    model = Model('metanetx_universal_model_' + '_'.join(list_of_db_prefixes), solver_interface=optlang.interface)
    model.add_reactions(reactions)
    # Add sinks for all metabolites
    for metabolite in model.metabolites:
        model.add_demand(metabolite)
    return model
Exemplo n.º 12
0
 def test_make_lhs_irreversible_reversible(self):
     model = self.model
     rxn = Reaction('test')
     rxn.add_metabolites({model.metabolites[0]: -1., model.metabolites[1]: 1.})
     rxn.lower_bound = -999999.
     rxn.upper_bound = -100
     model.add_reaction(rxn)
     self.assertEqual(rxn.lower_bound, -999999.)
     self.assertEqual(rxn.upper_bound, -100.)
     self.assertEqual(rxn.forward_variable.lb, 0.)
     self.assertEqual(rxn.forward_variable.ub, 0.)
     self.assertEqual(rxn.reverse_variable.lb, 100.)
     self.assertEqual(rxn.reverse_variable.ub, 999999.)
     rxn.upper_bound = 666.
     self.assertEqual(rxn.lower_bound, -999999.)
     self.assertEqual(rxn.upper_bound, 666.)
     self.assertEqual(rxn.forward_variable.lb, 0.)
     self.assertEqual(rxn.forward_variable.ub, 666)
     self.assertEqual(rxn.reverse_variable.lb, 0.)
     self.assertEqual(rxn.reverse_variable.ub, 999999.)
Exemplo n.º 13
0
def create_adapter_reactions(original_metabolites, database, mapping, compartment_regexp):
    adapter_reactions = []
    for metabolite in original_metabolites:  # model is the original host model
        if not compartment_regexp.match(metabolite.id):
            continue

        name = metabolite.id[0:-2]
        try:
            mapped_name = mapping[name]
        except KeyError:
            continue
            # print name, 'N/A'
        adapter_reaction = Reaction('adapter_' + metabolite.id + '_' + mapped_name)
        adapter_reaction.lower_bound = -1000
        try:
            adapter_reaction.add_metabolites({metabolite: -1,
                                              database.metabolites.get_by_id(mapped_name): 1})
        except KeyError:
            pass
        else:
            adapter_reactions.append(adapter_reaction)

    return adapter_reactions
Exemplo n.º 14
0
 def test_make_lhs_irreversible_reversible(self):
     model = self.model
     rxn = Reaction('test')
     rxn.add_metabolites({
         model.metabolites[0]: -1.,
         model.metabolites[1]: 1.
     })
     rxn.lower_bound = -999999.
     rxn.upper_bound = -100
     model.add_reaction(rxn)
     self.assertEqual(rxn.lower_bound, -999999.)
     self.assertEqual(rxn.upper_bound, -100.)
     self.assertEqual(rxn.forward_variable.lb, 0.)
     self.assertEqual(rxn.forward_variable.ub, 0.)
     self.assertEqual(rxn.reverse_variable.lb, 100.)
     self.assertEqual(rxn.reverse_variable.ub, 999999.)
     rxn.upper_bound = 666.
     self.assertEqual(rxn.lower_bound, -999999.)
     self.assertEqual(rxn.upper_bound, 666.)
     self.assertEqual(rxn.forward_variable.lb, 0.)
     self.assertEqual(rxn.forward_variable.ub, 666)
     self.assertEqual(rxn.reverse_variable.lb, 0.)
     self.assertEqual(rxn.reverse_variable.ub, 999999.)
Exemplo n.º 15
0
    def _make_dual_model(self, model):
        dual_model = SolverBasedModel(solver_interface=model.solver.interface)

        # Add dual metabolites
        dual_metabolite_names = []
        irreversibles = []  # Metabolites for which a z-reaction must be added
        self._dual_to_primal_mapping = {}
        for re in model.reactions:
            forward_id = re._get_forward_id()
            reverse_id = re._get_reverse_id()
            if forward_id in self._split_vars or reverse_id in self._split_vars:
                if re.upper_bound > 0 or forward_id in self._split_vars:
                    dual_metabolite_names.append(forward_id)
                    irreversibles.append(forward_id)
                    self._dual_to_primal_mapping[forward_id] = re.id
                if re.lower_bound < 0 or reverse_id in self._split_vars:
                    dual_metabolite_names.append(reverse_id)
                    irreversibles.append(reverse_id)
                    self._dual_to_primal_mapping[reverse_id] = re.id
            else:
                dual_metabolite_names.append(re.id)
                if re.lower_bound >= 0:
                    irreversibles.append(re.id)
                self._dual_to_primal_mapping[re.id] = re.id
        dual_model.add_metabolites(
            [Metabolite(name) for name in dual_metabolite_names])

        # Add dual "u-reactions"
        transposed_stoichiometry = {}
        for reaction in model.reactions:
            for met, coef in reaction.metabolites.items():
                if reaction._get_reverse_id() in dual_metabolite_names:
                    transposed_stoichiometry.setdefault(
                        met, {})[dual_model.metabolites.get_by_id(
                            reaction._get_reverse_id())] = -coef
                if reaction._get_forward_id() in dual_metabolite_names:
                    transposed_stoichiometry.setdefault(
                        met, {})[dual_model.metabolites.get_by_id(
                            reaction._get_forward_id())] = coef
                elif reaction.id in dual_metabolite_names:  # This should be the same as forward_var.name but in general it might not be
                    transposed_stoichiometry.setdefault(
                        met, {})[dual_model.metabolites.get_by_id(
                            reaction.id)] = coef

        u_reactions = []
        for met, stoichiometry in transposed_stoichiometry.items():
            met_id = met.id
            reac = Reaction("u_" + met_id)
            reac.lower_bound = -reac.upper_bound  # Make reversible
            reac.add_metabolites(stoichiometry)
            u_reactions.append(reac)

        dual_model.add_reactions(u_reactions)

        # Add dual "v-reactions"
        v_reactions = []
        for dual_met in dual_model.metabolites:
            reac = Reaction("v_" + dual_met.id)
            reac.lower_bound = -reac.upper_bound  # Make reversible
            reac.add_metabolites({dual_met: 1})
            v_reactions.append(reac)
        dual_model.add_reactions(v_reactions)
        self._v_reactions = v_reactions

        # Add dual "z-reactions"
        z_reactions = []
        for dual_met in dual_model.metabolites:
            if dual_met.id in irreversibles:
                reac = Reaction("z_" + dual_met.id)
                reac.lower_bound = 0
                reac.add_metabolites({dual_met: -1})
                z_reactions.append(reac)
        dual_model.add_reactions(z_reactions)

        return dual_model
Exemplo n.º 16
0
    def _make_dual_model(self, model):
        dual_model = SolverBasedModel(solver_interface=model.solver.interface)

        # Add dual metabolites
        dual_metabolite_names = []
        irreversibles = []  # Metabolites for which a z-reaction must be added
        self._dual_to_primal_mapping = {}
        for re in model.reactions:
            forward_id = re._get_forward_id()
            reverse_id = re._get_reverse_id()
            if forward_id in self._split_vars or reverse_id in self._split_vars:
                if re.upper_bound > 0 or forward_id in self._split_vars:
                    dual_metabolite_names.append(forward_id)
                    irreversibles.append(forward_id)
                    self._dual_to_primal_mapping[forward_id] = re.id
                if re.lower_bound < 0 or reverse_id in self._split_vars:
                    dual_metabolite_names.append(reverse_id)
                    irreversibles.append(reverse_id)
                    self._dual_to_primal_mapping[reverse_id] = re.id
            else:
                dual_metabolite_names.append(re.id)
                if re.lower_bound >= 0:
                    irreversibles.append(re.id)
                self._dual_to_primal_mapping[re.id] = re.id
        dual_model.add_metabolites([Metabolite(name) for name in dual_metabolite_names])

        # Add dual "u-reactions"
        transposed_stoichiometry = {}
        for reaction in model.reactions:
            for met, coef in reaction.metabolites.items():
                if reaction._get_reverse_id() in dual_metabolite_names:
                    transposed_stoichiometry.setdefault(met, {})[
                        dual_model.metabolites.get_by_id(reaction._get_reverse_id())] = -coef
                if reaction._get_forward_id() in dual_metabolite_names:
                    transposed_stoichiometry.setdefault(met, {})[
                        dual_model.metabolites.get_by_id(reaction._get_forward_id())] = coef
                elif reaction.id in dual_metabolite_names:  # This should be the same as forward_var.name but in general it might not be
                    transposed_stoichiometry.setdefault(met, {})[
                        dual_model.metabolites.get_by_id(reaction.id)] = coef

        u_reactions = []
        for met, stoichiometry in transposed_stoichiometry.items():
            met_id = met.id
            reac = Reaction("u_" + met_id)
            reac.lower_bound = -reac.upper_bound  # Make reversible
            reac.add_metabolites(stoichiometry)
            u_reactions.append(reac)

        dual_model.add_reactions(u_reactions)

        # Add dual "v-reactions"
        v_reactions = []
        for dual_met in dual_model.metabolites:
            reac = Reaction("v_" + dual_met.id)
            reac.lower_bound = -reac.upper_bound  # Make reversible
            reac.add_metabolites({dual_met: 1})
            v_reactions.append(reac)
        dual_model.add_reactions(v_reactions)
        self._v_reactions = v_reactions

        # Add dual "z-reactions"
        z_reactions = []
        for dual_met in dual_model.metabolites:
            if dual_met.id in irreversibles:
                reac = Reaction("z_" + dual_met.id)
                reac.lower_bound = 0
                reac.add_metabolites({dual_met: -1})
                z_reactions.append(reac)
        dual_model.add_reactions(z_reactions)

        return dual_model