예제 #1
0
    def generate_merged_model(self):
        def _id_pattern(object_id, organism_id):
            return "{}_{}".format(object_id, organism_id)

        def _name_pattern(object_name, organism_name):
            return "{} ({})".format(object_name, organism_name)

        def _copy_object(obj, org_id, compartment=None):
            new_obj = obj.copy()
            new_obj.id = _id_pattern(obj.id, org_id)
            new_obj.name = _name_pattern(obj.name, org_id)
            if compartment:
                new_obj.compartment = compartment

            return new_obj

        models_missing_extracelullar_compartment = [
            m.id for m in self._organisms.itervalues()
            if self._extracellular_compartment not in m.compartments
        ]
        if models_missing_extracelullar_compartment:
            raise RuntimeError(
                "Extracellular compartment '{}' missing from models: '{}'".
                format(self._extracellular_compartment,
                       "', '".join(models_missing_extracelullar_compartment)))

        models_missing_biomass = [
            m.id for m in self._organisms.itervalues()
            if not m.biomass_reaction
        ]
        if models_missing_biomass:
            raise RuntimeError(
                "Biomass reaction not found in models: {}".format(
                    "', '".join(models_missing_biomass)))

        merged_model = CBModel(self.id)
        merged_model.biomass_reaction = None

        organisms_biomass_metabolites = {}
        community_metabolite_exchange_lookup = {}

        for org_id, model in self._organisms.items():
            self._organisms_reactions[org_id] = set()
            self._organisms_exchange_reactions[org_id] = {}
            self._organisms_biomass_reactions[org_id] = {}
            exchanged_metabolites = {
                m_id
                for r_id in model.get_exchange_reactions()
                for m_id in model.reactions[r_id].stoichiometry
            }
            #
            # Create additional extracellular compartment
            #
            if not self._merge_extracellular_compartments:
                pool_compartment = Compartment('pool', 'common pool')
                merged_model.add_compartment(pool_compartment)
                export_pool_compartment = Compartment(
                    'pool_blacklist', 'blacklisted metabolite pool')
                merged_model.add_compartment(export_pool_compartment)

            for c_id, comp in model.compartments.items():
                if c_id != self._extracellular_compartment or not self._merge_extracellular_compartments:
                    new_comp = _copy_object(comp, org_id)
                    merged_model.add_compartment(new_comp)
                elif c_id not in merged_model.compartments:
                    merged_model.add_compartment(deepcopy(comp))

            for m_id, met in model.metabolites.items():
                if met.compartment != self._extracellular_compartment or not self._merge_extracellular_compartments:
                    new_met = _copy_object(
                        met, org_id, _id_pattern(met.compartment, org_id))
                    merged_model.add_metabolite(new_met, clear_tmp=False)
                elif m_id not in merged_model.metabolites:
                    merged_model.add_metabolite(deepcopy(met), clear_tmp=False)

                m_blacklisted = met.id in self._exchanged_metabolites_blacklist

                if met.id in exchanged_metabolites and not self._merge_extracellular_compartments:
                    #
                    # For blacklisted metabolites create a separate pool from which metabolites can not be reuptaken
                    #
                    if m_blacklisted and self._interacting:
                        pool_id = _id_pattern(m_id, "pool_blacklist")
                        if pool_id not in merged_model.metabolites:
                            new_met = _copy_object(met, "pool_blacklist",
                                                   "pool_blacklist")
                            merged_model.add_metabolite(new_met,
                                                        clear_tmp=False)

                            exch_id = _id_pattern("R_EX_" + m_id,
                                                  "pool_blacklist")
                            exch_name = _name_pattern(
                                met.name, "pool (blacklist) exchange")
                            blk_rxn = CBReaction(exch_id,
                                                 name=exch_name,
                                                 reversible=False,
                                                 is_exchange=False,
                                                 is_sink=True)
                            blk_rxn.stoichiometry[pool_id] = -1.0
                            community_metabolite_exchange_lookup[
                                new_met.id] = exch_id
                            merged_model.add_reaction(blk_rxn)

                    pool_id = _id_pattern(m_id, "pool")
                    if pool_id not in merged_model.metabolites:
                        new_met = _copy_object(met, "pool", "pool")
                        merged_model.add_metabolite(new_met, clear_tmp=False)

                        exch_id = _id_pattern("R_EX_" + m_id, "pool")
                        exch_name = _name_pattern(met.name, "pool exchange")
                        new_rxn = CBReaction(exch_id,
                                             name=exch_name,
                                             reversible=True,
                                             is_exchange=True)
                        new_rxn.stoichiometry[pool_id] = -1.0
                        community_metabolite_exchange_lookup[
                            new_met.id] = exch_id
                        merged_model.add_reaction(new_rxn)

            for r_id, rxn in model.reactions.items():

                is_exchange = rxn.is_exchange

                if not is_exchange or not self._merge_extracellular_compartments:
                    new_rxn = _copy_object(rxn, org_id)
                    new_rxn.is_exchange = False

                    for m_id, coeff in rxn.stoichiometry.items():
                        m_blacklisted = m_id in self._exchanged_metabolites_blacklist
                        if model.metabolites[
                                m_id].compartment != self._extracellular_compartment or not self._merge_extracellular_compartments:
                            del new_rxn.stoichiometry[m_id]
                            new_id = _id_pattern(m_id, org_id)
                            new_rxn.stoichiometry[new_id] = coeff

                        if is_exchange:
                            if model.metabolites[
                                    m_id].compartment == self._extracellular_compartment and not self._merge_extracellular_compartments:
                                # TODO: if m_id in self._exchanged_metabolites_blacklist:
                                pool_id = _id_pattern(m_id, "pool")
                                new_rxn.stoichiometry[pool_id] = -coeff
                                cnm = CommunityNameMapping(
                                    organism_reaction=new_rxn.id,
                                    original_reaction=r_id,
                                    organism_metabolite=new_id,
                                    extracellular_metabolite=pool_id,
                                    original_metabolite=m_id,
                                    community_exchange_reaction=
                                    community_metabolite_exchange_lookup[
                                        pool_id])
                                self._organisms_exchange_reactions[org_id][
                                    new_rxn.id] = cnm

                                if not self.interacting:
                                    sink_rxn = CBReaction(
                                        'Sink_{}'.format(new_id),
                                        is_exchange=False,
                                        is_sink=True,
                                        reversible=False)
                                    sink_rxn.stoichiometry = {new_id: -1}
                                    sink_rxn.lb = 0.0
                                    merged_model.add_reaction(sink_rxn)
                                elif m_blacklisted:
                                    pool_blacklist_id = _id_pattern(
                                        m_id, "pool_blacklist")
                                    blacklist_export_rxn = CBReaction(
                                        'R_EX_BLACKLIST_{}'.format(new_id),
                                        is_exchange=False,
                                        is_sink=False,
                                        reversible=False)
                                    blacklist_export_rxn.stoichiometry = {
                                        new_id: -1,
                                        pool_blacklist_id: 1
                                    }
                                    blacklist_export_rxn.lb = 0.0
                                    merged_model.add_reaction(
                                        blacklist_export_rxn)

                    if is_exchange and not self._merge_extracellular_compartments:
                        new_rxn.reversible = True
                        new_rxn.lb = None
                        new_rxn.ub = None if self.interacting and not m_blacklisted else 0.0

                    if rxn.id == model.biomass_reaction:
                        new_rxn.reversible = False

                    if self._create_biomass and rxn.id == model.biomass_reaction:
                        new_rxn.objective = False

                        # Add biomass metabolite to biomass equation
                        m_id = _id_pattern('Biomass', org_id)
                        name = _name_pattern('Framed biomass', org_id)
                        comp = 'pool' if not self._merge_extracellular_compartments else self._extracellular_compartment
                        biomass_met = Metabolite(m_id, name, comp)
                        merged_model.add_metabolite(biomass_met,
                                                    clear_tmp=False)
                        new_rxn.stoichiometry[m_id] = 1
                        organisms_biomass_metabolites[org_id] = m_id

                    self._organisms_reactions[org_id].add(new_rxn.id)
                    merged_model.add_reaction(new_rxn)

                else:
                    if is_exchange and self._merge_extracellular_compartments:
                        self._organisms_exchange_reactions[org_id][
                            rxn.id] = CommunityNameMapping(
                                organism_reaction=r_id,
                                original_reaction=r_id,
                                extracellular_metabolite=rxn.stoichiometry.
                                keys()[0],
                                original_metabolite=rxn.stoichiometry.keys()
                                [0],
                                organism_metabolite=None)
                        self._organisms_reactions[org_id].add(rxn.id)

                    if r_id in merged_model.reactions:
                        continue

                    new_rxn = deepcopy(rxn)
                    new_rxn.is_exchange = True
                    if rxn.id == model.biomass_reaction and self._create_biomass:
                        new_rxn.reversible = False
                        new_rxn.objective = False

                        m_id = _id_pattern('Biomass', org_id)
                        name = _name_pattern('Biomass', org_id)
                        comp = 'pool' if not self._merge_extracellular_compartments else self._extracellular_compartment
                        biomass_met = Metabolite(m_id, name, comp)
                        merged_model.add_metabolite(biomass_met,
                                                    clear_tmp=False)
                        new_rxn.stoichiometry[m_id] = 1
                        organisms_biomass_metabolites[org_id] = m_id

                    merged_model.add_reaction(new_rxn)

                if r_id == model.biomass_reaction:
                    self._organisms_biomass_reactions[org_id] = new_rxn.id

        if self._create_biomass:
            biomass_rxn = CBReaction('R_Community_Growth',
                                     name="Community Growth",
                                     reversible=False,
                                     is_exchange=False,
                                     is_sink=True,
                                     objective=1.0)
            for org_biomass in organisms_biomass_metabolites.itervalues():
                biomass_rxn.stoichiometry[org_biomass] = -1

            merged_model.add_reaction(biomass_rxn)
            merged_model.biomass_reaction = biomass_rxn.id

        return merged_model
예제 #2
0
파일: model2.py 프로젝트: jinb88187/framed
    def merge_models(self):
        comm_model = CBModel(self.id)
        old_ext_comps = []
        ext_mets = []
        self.reaction_map = {}
        self.metabolite_map = {}

        # default IDs
        ext_comp_id = "ext"
        biomass_id = "community_biomass"
        comm_growth = "community_growth"

        # create external compartment

        comp = Compartment(ext_comp_id,
                           "extracellular environment",
                           external=True)
        comm_model.add_compartment(comp)

        # community biomass

        met = Metabolite(biomass_id, "Total community biomass", ext_comp_id)
        comm_model.add_metabolite(met, clear_tmp=False)

        rxn = CBReaction(comm_growth,
                         name="Community growth rate",
                         reversible=False,
                         stoichiometry={biomass_id: -1},
                         lb=0,
                         ub=None,
                         objective=1)

        comm_model.add_reaction(rxn, clear_tmp=False)

        # add each organism

        for org_id, model in self.organisms.items():

            def rename(old_id):
                return "{}_{}".format(old_id, org_id)

            # add internal compartments

            for c_id, comp in model.compartments.items():
                if comp.external:
                    old_ext_comps.append(c_id)
                else:
                    new_comp = Compartment(rename(c_id), comp.name)
                    comm_model.add_compartment(new_comp)

            # add metabolites

            for m_id, met in model.metabolites.items():
                if met.compartment not in old_ext_comps:  # if is internal
                    new_id = rename(m_id)
                    new_met = Metabolite(new_id, met.name,
                                         rename(met.compartment))
                    new_met.metadata = met.metadata.copy()
                    comm_model.add_metabolite(new_met)
                    self.metabolite_map[(org_id, m_id)] = new_id

                elif m_id not in comm_model.metabolites:  # if is external but was not added yet
                    new_met = Metabolite(m_id, met.name, ext_comp_id)
                    new_met.metadata = met.metadata.copy()
                    comm_model.add_metabolite(new_met, clear_tmp=False)
                    ext_mets.append(new_met.id)

            # add internal reactions

            for r_id, rxn in model.reactions.items():

                if rxn.reaction_type == ReactionType.EXCHANGE:
                    continue

                new_id = rename(r_id)
                new_stoichiometry = {
                    m_id if m_id in ext_mets else rename(m_id): coeff
                    for m_id, coeff in rxn.stoichiometry.items()
                }

                if r_id == model.biomass_reaction:
                    new_stoichiometry[biomass_id] = 1

                new_rxn = CBReaction(
                    new_id,
                    name=rxn.name,
                    reversible=rxn.reversible,
                    stoichiometry=new_stoichiometry,
                    reaction_type=rxn.reaction_type,
                    lb=rxn.lb,
                    ub=rxn.ub,
                )

                comm_model.add_reaction(new_rxn, clear_tmp=False)
                new_rxn.metadata = rxn.metadata.copy()
                self.reaction_map[(org_id, r_id)] = new_id

        # Add exchange reactions

        for m_id in ext_mets:
            rxn = CBReaction("R_EX_{}".format(m_id),
                             reversible=True,
                             stoichiometry={m_id: -1},
                             reaction_type=ReactionType.EXCHANGE)
            comm_model.add_reaction(rxn, clear_tmp=False)

        return comm_model
예제 #3
0
    def __parse(self, text, filename=None):
        text = text.replace("\r\n", "\n")
        text = text.replace("\r", "\n")

        re_long = re.compile("%.*?%", re.DOTALL | re.MULTILINE)
        text = re_long.sub("\n", text)

        re_short = re.compile("#.*?\n")
        text = re_short.sub("\n", text)

        sections = self.find_sections(text)

        model = CBModel(basename(filename))
        react_name, react_text, react_line = self.__find_section(
            text, sections, lambda x: re.search(r"reac", x, re.I))
        const_name, const_text, const_line = self.__find_section(
            text, sections, lambda x: re.search(r"cons", x, re.I))
        ext_m_name, ext_m_text, ext_m_line = self.__find_section(
            text, sections, lambda x: re.search(r"ext", x, re.I))
        obj_name, obj_text, obj_line = self.__find_section(
            text, sections,
            lambda x: re.search(r"obj", x, re.I) and not re.search(
                "des", x, re.I))

        if react_text:
            reactions = self.__parse_reactions_section(
                react_text,
                filename=filename,
                section_start=react_line,
                strip_comments=False)

            for reaction, r_i in reactions:
                for m_id in reaction.stoichiometry:
                    if m_id not in model.metabolites:
                        model.add_metabolite(Metabolite(elem_id=m_id,
                                                        compartment=None),
                                             clear_tmp=True)

                model.add_reaction(reaction, clear_tmp=True)
        else:
            warnings.warn("Could not find '-REACTIONS' section",
                          BiooptParseWarning)

        if const_text:
            for (r_id, lb, ub), i in self.__parse_constraints_section(
                    const_text,
                    filename=filename,
                    section_start=const_line,
                    strip_comments=False):
                if r_id in model.reactions and lb < 0 and not model.reactions[
                        r_id].reversible:
                    warnings.warn_explicit(
                        "Reaction '{0}' from '{1}' has effective bounds not compatible with reaction direction in '{2}' section ({3} : [{4}, {5}])"
                        .format(r_id, const_name, react_name,
                                "<->" if reactions[r_id].reversibl else "->",
                                lb, ub),
                        BiooptParseWarning,
                        filename=filename,
                        lineno=const_line + i + 1)

                if r_id in model.reactions:
                    model.reactions[r_id].lb = lb
                    model.reactions[r_id].ub = ub
                elif react_text:
                    warnings.warn_explicit(
                        "Reaction '{0}' from '{1}' section is not present in '{2}' section"
                        .format(r_id, const_name, react_name),
                        BiooptParseWarning,
                        filename=filename,
                        lineno=const_line + i + 1)
        else:
            warnings.warn("Could not find '-CONSTRAINS' section",
                          BiooptParseWarning)

        if ext_m_text:
            met2rxn = model.metabolite_reaction_lookup()
            for m_external, i in self.__parse_external_metabolites_section(
                    ext_m_text,
                    filename=filename,
                    section_start=ext_m_line,
                    strip_comments=False):
                if m_external.id in model.metabolites:
                    model.metabolites[m_external.id].boundary = True
                    for external_r_id, coef in met2rxn[m_external.id].items():
                        model.reactions[external_r_id].is_exchange = True
                        del model.reactions[external_r_id].stoichiometry[
                            m_external.id]
                elif react_text:
                    warnings.warn_explicit(
                        "Metabolite '{0}' from '{1}' section is not present in any reaction from '{2}' section"
                        .format(m_external.id, ext_m_name, react_name),
                        BiooptParseWarning,
                        filename=filename,
                        lineno=ext_m_line + i + 1)
        else:
            warnings.warn("Could not find '-EXTERNAL METABOLITES' section",
                          BiooptParseWarning)

        if obj_text:
            r_id, coef = self.parse_objective_section(
                obj_text,
                section_name=obj_name,
                reactions_section_name=react_name,
                filename=filename,
                section_start=obj_line,
                reactions=reactions,
                strip_comments=False)
            model.reactions[r_id].objective = coef
        else:
            warnings.warn("Could not find '-OBJECTIVE' section",
                          BiooptParseWarning)

        return model