예제 #1
0
    def __init__(self, model, database_format):
        """
        Class constructor

        :param Model model: cobrapy model
        :param str database_format: ModelSEED, BiGG or KEGG
        """

        self.model = model

        self.objective = linear_reaction_coefficients(self.model)
        if self.objective:
            self.objective = list(self.objective.keys())[0]
        else:
            raise Exception("No objective found")

        self.__compounds_ontology = CompoundsDBAccessor()

        self.model = model
        self.__database_format = database_format
        self.__configs = file_utilities.read_conf_file(TOOL_CONFIG_PATH)
        self.__home_path__ = ROOT_DIR

        self.__modelseedCompoundsDb = ModelSeedCompoundsDB()

        self.__define_instance_variables()

        self.write_in_progress_bar("mapping model... ", 1)
        self.mapper.map_model(database_format)
        self.write_in_progress_bar("model mapped ", 10)
예제 #2
0
    def __init__(self,compounds_database = None, compounds_converter = None):
        self.target_pathways_map = {}
        self.__pathways_map = {}
        self.taxID_map = {}
        self.__home_path__ = ROOT_DIR

        if not compounds_converter:
            self.__compoundsIdConverter = CompoundsIDConverter()
        else:
            self.__compoundsIdConverter = compounds_converter

        if not compounds_database:
            self.__compounds_database = ModelSeedCompoundsDB()
        else:
            self.__compounds_database = compounds_database

        # if compounds_ontology:
        #     self.__compounds_ontology = compounds_ontology

        biocyc.set_organism('meta')
예제 #3
0
    def __init__(self, model: Model, database_format: str, db_accessor = CompoundsDBAccessor()):
        """
        Class constructor

        :param Model model: model being analysed
        :param database_format: database format (ModelSEED, BiGG or KEGG)
        :param modelseed_compoundsdb:
        """

        self.report_material = {}
        self.__universal_model = Model("universal_model")
        self.model = model
        self.__database_format = database_format
        self.__configs = file_utilities.read_conf_file(TOOL_CONFIG_PATH)
        self.__home_path__ = ROOT_DIR
        self.__compounds_ontology = db_accessor

        self.__modelseedCompoundsDb = ModelSeedCompoundsDB()

        self.__define_instance_variables()
예제 #4
0
    def __init__(self, model: Model, mapper: ModelMapper, database_format: str,
                 id_converter: CompoundsIDConverter,
                 compoundsAnnotationConfigs: dict):
        """
        Class constructor

        :param Model model: Cobrapy model
        :param ModelMapper mapper: model mapper
        :param str database_format: ModelSEED, KEGG or BiGG
        :param CompoundsIDConverter id_converter:
        :param dict compoundsAnnotationConfigs: compounds annotation configurations
        """

        self.__compoundsAnnotationConfigs = compoundsAnnotationConfigs
        self.__model = model
        self.__compoundsIdConverter = id_converter
        self.__modelseedCompoundsDb = ModelSeedCompoundsDB()
        self.__database_format = database_format
        self.mapper = mapper

        self.define_instance_variables()
예제 #5
0
class PathwayHandler(object):

    def __init__(self,compounds_database = None, compounds_converter = None):
        self.target_pathways_map = {}
        self.__pathways_map = {}
        self.taxID_map = {}
        self.__home_path__ = ROOT_DIR

        if not compounds_converter:
            self.__compoundsIdConverter = CompoundsIDConverter()
        else:
            self.__compoundsIdConverter = compounds_converter

        if not compounds_database:
            self.__compounds_database = ModelSeedCompoundsDB()
        else:
            self.__compounds_database = compounds_database

        # if compounds_ontology:
        #     self.__compounds_ontology = compounds_ontology

        biocyc.set_organism('meta')

    @property
    def target_pathways_map(self):
        return self.__target_pathways_map

    @target_pathways_map.setter
    def target_pathways_map(self,target_pathways_map):
        self.__target_pathways_map = target_pathways_map

    def __set_compounds_ontology(self):
        """
        Load the compound ontology
        """
        self.__compounds_ontology = CompoundOntologyGraph()
        self.__compounds_ontology.load_ontology(self.__home_path__ + self.__configs["compounds_ontology_file"],
                                                self.__home_path__ + self.__configs["compounds_entities_file"])

    def get_targets(self, pathwayid):
        return self.target_pathways_map[pathwayid]

    def save_in_file(self,filename):
        with open(filename,"w") as file:
            for pathway in self.target_pathways_map:
                lst = self.target_pathways_map[pathway]
                new_lst = []
                temp_lst = []
                for elem in lst:
                    ms_number = elem.split("cpd")[1]
                    if int(ms_number)>100:
                        new_lst.append(elem)

                if not new_lst:
                    new_lst = temp_lst.copy()

                if new_lst:
                    file.write(">"+ ",".join(new_lst) + "\n")
                    path = self.get_path_from_pathway(pathway)

                    file.write(pathway+": " + ">".join(path) +"\n")



    def load_from_file(self,filename):
        with open(filename,"r") as file:
            line = file.readline()
            while line:
                targets = re.sub(">","",line).strip()
                targets = targets.split(",")
                line = file.readline()
                while not re.search("^>",line) and line:

                    pathwayid_path = line.split(": ")
                    path = pathwayid_path[1].strip().split(">")
                    self.target_pathways_map[pathwayid_path[0]] = targets
                    network = MetabolicNetwork()
                    if len(path) == 1:
                        network.add_vertex(path[0])
                    else:
                        for i in range(0,len(path)-1):
                            network.add_edge(path[i],path[i+1])

                    self.__pathways_map[pathwayid_path[0]] = network
                    line=file.readline()


    def get_networks_from_target(self,target_modelseedid):
        return self.target_pathways_map[target_modelseedid]

    def get_target_pathways(self):
        return self.target_pathways_map

    def get_network_from_target_and_pathway_id(self,target_modelseedid,metacyc_pathway_id):
        return self.target_pathways_map.get(target_modelseedid).get(metacyc_pathway_id)


    def add_metacyc_pathway(self,metacyc_pathway_id,generic = False):
        biocyc.set_organism('meta')
        ptw = biocyc.get(metacyc_pathway_id)

        network = self.scrap_metacyc_path(ptw,generic)
        self.convert_compounds_into_modelseedid(network)


        pathway = network.get_pathway()
        if pathway:
            target_reaction = pathway[-1]
            last_reaction = biocyc.get(target_reaction)
            products = last_reaction.compounds_right
            targets = []

            for product in products:
                modelseedids = self.__compoundsIdConverter.convert_dbID_into_modelSeedId("MetaCyc",product.id)
                if modelseedids is not None:
                    targets.extend(modelseedids)

            self.__pathways_map[ptw.id] = network
            self.target_pathways_map[ptw.id]=targets

    def get_pathways(self):
        return self.__pathways_map

    def get_network_by_metacyc_pathway_id(self,id):
        return self.__pathways_map[id]

    def scrap_metacyc_path(self,ptw,generic):
        if generic:
            return self.__scrap_generic_metacyc_path(ptw)
        else:
            return self.__scrap_metacyc_path(ptw)

    def scrap_kegg_pathway(self,kegg_pathway):

        pathway = KeggPathway(kegg_pathway, False)
        return self.__scrap_generic_kegg_path(pathway)

    def __scrap_generic_kegg_path(self,pathway):

        network = MetabolicNetwork()

        for reaction in pathway.get_reactions():
            reaction = KeggReaction(reaction)
            reaction_id = reaction.id

            reactants = reaction.get_reactants()
            products = reaction.get_products()

            for reactant in reactants:
                reactant = KeggCompound(reactant)
                ids = self.__compoundsIdConverter.convert_dbID_into_modelSeedId("KEGG", reactant.id)
                for id in ids:
                    compound_container = self.__compounds_database.get_compound_by_id(id)
                    if "R" in compound_container.getFormula():
                        network.add_vertex(reaction_id)
                        network.node_types["reaction"].append(reaction_id)


                        network.node_types["metabolite"].append(reactant.id)
                        network.add_vertex(reactant.id)
                        network.add_edge(reactant.id, reaction_id)
                        network.add_edge(reaction_id, reactant.id)
                        break

            for product in products:
                product = KeggCompound(product)
                ids = self.__compoundsIdConverter.convert_dbID_into_modelSeedId("KEGG", product.id)
                for id in ids:
                    compound_container = self.__compounds_database.get_compound_by_id(id)
                    if "R" in compound_container.getFormula():
                        network.node_types["metabolite"].append(product.id)
                        network.add_vertex(product.id)
                        network.add_edge(reaction_id, product.id)
                        network.add_edge(product.id, reaction_id)
                        break

        metabolite_network = MetabolicNetwork()
        metabolite_network.convert_reaction_graph(network)
        return metabolite_network

    def __get_reactants_and_products_by_r_groups(self,reaction):

        products = reaction.get_products()
        reactants = reaction.get_reactants()

        products_r_groups = 0
        reactants_r_groups = 0

        for product in products:
            product = KeggCompound(product)
            formula = product.get_formula()
            if "R" in formula:
                match = re.match(formula, "R")
                start = match.start()
                number = formula[start+1]

                if re.match(number,"[2-9]"):
                    number= int(number)
                    products_r_groups+=number
                else:
                    products_r_groups+=1

        for reactant in reactants:
            reactant = KeggCompound(reactant)
            formula = reactant.get_formula()
            if "R" in formula:
                match = re.match(formula, "R")
                start = match.start()
                number = formula[start + 1]

                if re.match(number, "[2-9]"):
                    number = int(number)
                    reactants_r_groups += number
                else:
                    reactants_r_groups += 1

        if reactants_r_groups >= products_r_groups:

            return reactants,products

        else:
            return products,reactants

    def __scrap_metacyc_path(self,ptw):
        network = MetabolicNetwork()

        for reaction in ptw.reactions:
            reaction_id = reaction.id
            network.add_vertex(reaction_id)
            network.node_types["reaction"].append(reaction_id)

            reactants = reaction.compounds_left
            products = reaction.compounds_right

            for reactant in reactants:
                if reactant.id != "PROTON":
                    network.node_types["metabolite"].append(reactant.id)
                    network.add_vertex(reactant.id)
                    network.add_edge(reactant.id,reaction_id)

            for product in products:
                if product.id != "PROTON":
                    network.node_types["metabolite"].append(product.id)
                    network.add_vertex(product.id)
                    network.add_edge(reaction_id, product.id)

        metabolite_network = MetabolicNetwork()
        metabolite_network.convert_reaction_graph(network)
        return metabolite_network

    def __scrap_generic_metacyc_path(self,ptw):
        network = MetabolicNetwork()

        for reaction in ptw.reactions:
            reaction_id = reaction.id



            network.add_vertex(reaction_id)
            network.node_types["reaction"].append(reaction_id)

            reactants = reaction.compounds_left
            products = reaction.compounds_right

            if reaction_id == "RXN-17728":
                reactants = reaction.compounds_right
                products = reaction.compounds_left

            for reactant in reactants:
                ids = self.__compoundsIdConverter.convert_dbID_into_modelSeedId("MetaCyc",reactant.id)
                for id in ids:
                    compound_container = self.__compounds_database.get_compound_by_id(id)
                    if "R" in compound_container.getFormula():
                        network.node_types["metabolite"].append(reactant.id)
                        network.add_vertex(reactant.id)
                        network.add_edge(reactant.id, reaction_id)
                        break


            for product in products:
                ids = self.__compoundsIdConverter.convert_dbID_into_modelSeedId("MetaCyc", product.id)
                for id in ids:
                    compound_container = self.__compounds_database.get_compound_by_id(id)
                    if "R" in compound_container.getFormula():
                        network.node_types["metabolite"].append(product.id)
                        network.add_vertex(product.id)
                        network.add_edge(reaction_id, product.id)

        metabolite_network = MetabolicNetwork()
        metabolite_network.convert_reaction_graph(network)
        return metabolite_network

    def convert_compounds_into_modelseedid(self,network,db="MetaCyc"):
        res = {}
        # self.__babel = {}
        for compound in network.get_nodes():
            modelseedids = self.__compoundsIdConverter.convert_dbID_into_modelSeedId(db,compound)
            if modelseedids is not None:
                # self.__babel[compound] = modelseedid
                res[compound] = modelseedids
        return res


    def get_path_from_pathway(self,pathway_id):
        network = self.__pathways_map[pathway_id]
        return network.get_complete_pathway()


    def get_generic_targets_and_found_pathways(self,taxid):

        paths = self.get_pathway_by_taxID(taxid)
        targets_paths ={}
        for path in paths:
            targets = self.target_pathways_map[path]
            for target in targets:
                entity_id = self.__compounds_ontology.get_entity_id_by_model_seed_id(target)
                if entity_id:
                    # if target in targets_paths.keys():
                    targets_paths[target] = path

        targets = list(targets_paths.keys())

        res = {}

        for i in range(len(targets)):
            for j in range(i+1,len(targets)):

                entityid1 = self.__compounds_ontology.get_entity_id_by_model_seed_id(targets[i])
                entityid2 = self.__compounds_ontology.get_entity_id_by_model_seed_id(targets[j])

                container1 = self.__compounds_ontology.get_entity_container_by_id(entityid1)
                container2 = self.__compounds_ontology.get_entity_container_by_id(entityid2)

                if not container1.isGeneric() and not container2.isGeneric():
                    parent1 = self.__compounds_ontology.get_successors_by_relationship_type(entityid1,"is_a")
                    parent2 = self.__compounds_ontology.get_successors_by_relationship_type(entityid2,"is_a")

                    if parent1[0] == parent2[0]:

                        parent_modelseedid = self.__compounds_ontology.get_entity_modelseedid(parent1[0])
                        if parent_modelseedid not in res.keys():
                            res[parent_modelseedid] = [targets_paths[targets[i]]]
                            res[parent_modelseedid].append(targets_paths[targets[j]])
                        else:
                            res[parent_modelseedid].append(targets_paths[targets[i]])
                            res[parent_modelseedid].append(targets_paths[targets[j]])

        values_res = []
        for key in res:
            values_res.extend(res[key])

        values_res = self.get_unique(values_res)
        for target in targets:
            if targets_paths[target] not in values_res:
                if target not in res.keys():
                    res[target] = [targets_paths[target]]
                elif targets_paths[target] not in res[target]:
                    res[target].append(targets_paths[target])

        for key in res:
            res[key] = self.get_unique(res[key])

        return res

    def get_unique(self,lst):
        res=[]
        for elem in lst:
            if elem not in res: res.append(elem)

        return res

    def get_pathway_by_target(self,target):
        pathways = []
        for path in self.target_pathways_map:
            if target in self.target_pathways_map[path]:
                pathways.append(path)
        return pathways

    def get_pathway_by_taxID(self,taxID):
        # paths_species = []
        paths_tax_range = []
        taxa = NCBITaxa()
        lineage = taxa.get_lineage(taxID)
        for path in self.target_pathways_map:
            pathway = biocyc.get(path)

            # species = pathway.species
            # for s in species:
            #     if re.search("TAX-",s.id):
            #         id = int(s.id.replace("TAX-", ""))
            #         if id in lineage:
            #             paths_species.append((path,pathway.name))

            taxonomic_range = pathway.taxonomic_range
            for s in taxonomic_range:
                taxid = int(s.id.replace("TAX-",""))
                if taxid in lineage:
                    paths_tax_range.append(path)

        # res

        return paths_tax_range

    def get_all_paths_using_pathway_id(self,pathway_id,accept_cycles=False):
        network = self.get_network_by_metacyc_pathway_id(pathway_id)
        if not accept_cycles:
            network.prune_redundant_cycles()
        pathways = network.get_all_target_pathways()
        return pathways

    def get_path_model_seed_ids(self,ptw):
        network = self.__pathways_map[ptw]
        dict = self.convert_compounds_into_modelseedid(network)
        return dict

    def get_pathway_by_taxid_and_target(self,taxid,target):
        paths_tax_range = []
        taxa = NCBITaxa()
        lineage = taxa.get_lineage(taxid)
        for path in self.target_pathways_map:
            pathway = biocyc.get(path)

            taxonomic_range = pathway.taxonomic_range
            for s in taxonomic_range:
                taxid = int(s.id.replace("TAX-", ""))
                if taxid in lineage:
                    paths_tax_range.append(path)

        pathways = self.get_pathway_by_target(target)
        for p in paths_tax_range:
            if p in pathways:
                return p
예제 #6
0
class SimpleCaseSolver():
    def __init__(self,
                 model: Model,
                 database_format: str,
                 db_accessor=CompoundsDBAccessor()):
        """
        Class constructor

        :param Model model: model being analysed
        :param database_format: database format (ModelSEED, BiGG or KEGG)
        :param modelseed_compoundsdb:
        """

        self.__universal_model = Model("universal_model")
        self.model = model
        self.__database_format = database_format
        self.__configs = file_utilities.read_conf_file(TOOL_CONFIG_PATH)
        self.__home_path__ = ROOT_DIR
        self.__compounds_ontology = db_accessor

        self.__modelseedCompoundsDb = ModelSeedCompoundsDB()

        self.__define_instance_variables()

    def dump_maps(self, destination: str):
        """
        It creates a dump of all the model metabolite maps

        :param str destination: destination folder
        :return:
        """

        self.__mapper.create_map_dump(destination)

    def load_maps(self, folder):
        """
        Load all the metabolite maps in a given folder

        :param str folder: folder path
        :return:
        """

        self.__mapper.upload_maps(folder)

    def map_model(self):
        """
        Creates maps for all the metabolites in the model

        :return:
        """

        start = time.time()
        self.write_in_progress_bar("mapping the model... ", 10)

        self.__mapper.map_model(self.__database_format)

        self.write_in_progress_bar("model mapped ", 31)
        finished = time.time()
        logger.info("mapping finished: %d" % (finished - start))

    def write_in_progress_bar(self, message: str, value: float):
        """
        Write information related to the progress bar

        :param str message: message of what is being done
        :param float value: value to assign in the progress bar
        :return:
        """

        with open(PROGRESS_BAR, "w") as file:
            file.write(message + ":" + str(value))

    def get_progress_bar_state(self) -> float:
        """
        This method reads the progress bar message and the respective value

        :return float state: value to assign in the progress bar
        """
        with open(PROGRESS_BAR, "r") as file:
            line = file.read()
            line = line.strip()
            state = line.split(":")[1]
            return float(state)

    def calculate_division_for_progress_bar(self, state, total_processes_left):
        left = 100 - state
        for_each_part = left / total_processes_left

        return for_each_part

    @property
    def model(self):
        return self.__model

    @model.setter
    def model(self, value):
        if isinstance(value, Model):
            self.__model = value
        else:
            raise ValueError("introduce a cobrapy model")

    def __define_instance_variables(self):
        """
        Method to define a set of instance values

        :return:
        """

        self.__swapped = []
        self.lineage = []

        # self.__compounds_ontology = CompoundsDBAccessor()

        self.__compoundsAnnotationConfigs = file_utilities.read_conf_file(
            COMPOUNDS_ANNOTATION_CONFIGS_PATH)

        self.__reactionsAnnotationConfigs = file_utilities.read_conf_file(
            REACTIONS_ANNOTATION_CONFIGS_PATH)

        self.__compoundsAnnotationConfigs = file_utilities.read_conf_file(
            COMPOUNDS_ANNOTATION_CONFIGS_PATH)
        self.__reactionsAnnotationConfigs = file_utilities.read_conf_file(
            REACTIONS_ANNOTATION_CONFIGS_PATH)
        self.__compoundsIdConverter = CompoundsIDConverter()

        # self.__ptw_handler_quinones = PathwayHandler(self.__modelseedCompoundsDb, self.__compoundsIdConverter)
        # self.__ptw_handler_quinones.load_from_file(self.__home_path__ + self.__configs["quinones_pathways"])

        self.__not_to_change_classes = ["cpd03476"]
        self.__set_not_to_change_compounds()

        self.__compounds_revisor = CompoundsRevisor(self.model,
                                                    self.__universal_model)
        biocyc.set_organism("meta")

        self.__swapper = MetaboliteSwapper(
            self.model,
            None,
            None,
            0,
            self.__modelseedCompoundsDb,
            model_database=self.__database_format,
            compoundsIdConverter=self.__compoundsIdConverter,
            universal_model=self.__universal_model,
            not_to_change_compounds=self.__not_to_change_compounds)

        self.__mapper = ModelMapper(self.model,
                                    self.__compoundsAnnotationConfigs,
                                    self.__compoundsIdConverter)

        self.__swapper.set_model_mapper(self.__mapper)
        self.__compounds_revisor.set_model_mapper(self.__mapper)

    def __set_not_to_change_compounds(self):
        """
        One would want to protect few compounds of being changed.

        :return:
        """
        self.__not_to_change_compounds = []
        for compound_class in self.__not_to_change_classes:
            parent_id = self.__compounds_ontology.get_node_id_from_model_seed_id(
                compound_class)
            children = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type(
                parent_id, "is_a")
            self.__not_to_change_compounds.extend(children)

    def swap_compound(self,
                      compound_in_model: str,
                      compound_to_change: str,
                      compounds_left=1):
        """
        This method aims at swapping all the biosynthetic precursors, and the conjugated acid and base of a given target.
        It accepts all types of changes.

        :param str compound_in_model: compound in model
        :param str compound_to_change: compound to replace the one in the model
        :param str compounds_left: compounds left in the swapping operation
        :return:
        """

        if not self.__mapper.mapped:

            self.map_model()

        compound_in_model = self.transform_input_into_boimmg_ids(
            compound_in_model)
        if not compound_to_change:
            exit(2)

        compound_to_change = self.transform_input_into_boimmg_ids(
            compound_to_change)
        if not compound_to_change:
            exit(2)

        compound_in_model_node = self.__compounds_ontology.get_node_by_ont_id(
            compound_in_model)
        compound_to_change_node = self.__compounds_ontology.get_node_by_ont_id(
            compound_to_change)

        state = self.get_progress_bar_state()
        per_iteration = self.calculate_division_for_progress_bar(
            state, compounds_left)

        self.write_in_progress_bar(
            "Swapping " + compound_in_model_node.name + " to " +
            compound_to_change_node.name, state)

        logger.info(
            "Swapping " + compound_in_model_node.name + " to " +
            compound_to_change_node.name, state)

        type = 0

        if compound_in_model_node.generic and not compound_to_change_node.generic:
            parents = self.__compounds_ontology.get_successors_by_ont_id_rel_type(
                compound_to_change, "is_a")
            if compound_in_model in parents:
                type = 2
            else:
                type = 3

        elif compound_to_change_node.generic and not compound_in_model_node.generic:
            parents = self.__compounds_ontology.get_successors_by_ont_id_rel_type(
                compound_in_model, "is_a")
            if compound_to_change in parents:
                type = 2
            else:
                type = 3

        elif not compound_to_change_node.generic and not compound_in_model_node.generic:

            parents1 = self.__compounds_ontology.get_successors_by_ont_id_rel_type(
                compound_in_model, "is_a")
            parents2 = self.__compounds_ontology.get_successors_by_ont_id_rel_type(
                compound_to_change, "is_a")
            if parents1 and parents2:
                if parents1[0] == parents2[0]:
                    type = 1
                else:
                    type = 2

        if type != 0:
            self.__swapper.set_type(type)
            self.__swapper.set_compound_in_model(compound_in_model)
            self.__swapper.set_new_compound(compound_to_change)

            self.__swapper.swap_metabolites()

        else:
            self.__swapper.set_type(type)
            self.__swapper.set_compound_in_model(compound_in_model)
            self.__swapper.set_new_compound(compound_to_change)

            self.__swapper.swap_only_metabolites_and_conjugates()

        self.write_in_progress_bar("Swap performed", per_iteration)
        logger.info("Swap performed")

    def __check_if_compound_exists_in_model_by_ontology_id(
            self, ontology_id: int) -> list:
        """
        This method will check whether a BOIMMG compound exists in the model.

        :param int ontology_id: BOIMMG id
        :return list: compounds in model
        """
        res = []

        for model_id, boimmg_id in self.__mapper.boimmg_db_model_map.items():
            if boimmg_id == ontology_id:
                model_compound_container = self.model.metabolites.get_by_id(
                    model_id)
                res.append(model_compound_container)

        return res

    def __replace_electron_donors_and_acceptors(self):
        """
        This method will swap all the generic electron donors and acceptors eventually added when introducing
        MetaCyc reactions.

        :return:
        """

        donor_model_seed_id = "cpd26978"
        electron_transfer_quinol = 749301

        ontology_id = self.__compounds_ontology.get_node_id_from_model_seed_id(
            donor_model_seed_id)
        container = self.__compounds_ontology.get_node_by_ont_id(ontology_id)
        inchikey = container.inchikey
        aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID(
            donor_model_seed_id)
        metabolites_in_model = self.__mapper.check_metabolites_in_model(
            inchikey, aliases)
        self.__swapper.set_compound_in_model(ontology_id)
        self.__swapper.set_type(0)

        if metabolites_in_model:

            leaves = self.__compounds_ontology.get_leaves_from_ont_id(
                ontology_id)

            for metabolite in metabolites_in_model:
                compartment = metabolite.compartment
                found_leaf = False
                i = 0
                while not found_leaf and i < len(leaves):
                    parents = self.__compounds_ontology.get_all_parents(
                        leaves[i])
                    if electron_transfer_quinol not in parents:

                        leaf_container = self.__compounds_ontology.get_node_by_ont_id(
                            leaves[i])
                        modelseedid = leaf_container.model_seed_id
                        inchikey = leaf_container.inchikey
                        aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID(
                            modelseedid)

                        metabolites_in_model_to_change = \
                            self.__mapper.check_metabolites_in_model(inchikey, aliases,
                                                                     leaf_container)

                        found_compartment_leaf = False
                        j = 0
                        while not found_compartment_leaf and j < len(
                                metabolites_in_model_to_change):
                            if metabolites_in_model_to_change[
                                    j].compartment == compartment:
                                found_compartment_leaf = True
                                found_leaf = True

                                self.__swapper.set_new_compound(leaves[i])
                                self.__swapper.swap_only_metabolites_and_conjugates(
                                    metabolite,
                                    metabolites_in_model_to_change[j])
                            else:
                                j += 1
                    i += 1

    def __swap_metabolites(self,
                           metabolite_in_model: int,
                           new_metabolite: int,
                           type: int,
                           target=False) -> list:
        """
        This method aims at calling the MetaboliteSwapper to swap a given metabolite, their biosynthetic precursors
        and their conjugated base and acid, eventually.

        :param int metabolite_in_model: BOIMMG id of the metabolite in model
        :param int new_metabolite: BOIMMG id of the new metabolite
        :param int type: type of swap
        :param boolean target: whether the new metabolite is the target metabolite or not
        :return:
        """

        self.__swapper.set_compound_in_model(metabolite_in_model)
        self.__swapper.set_new_compound(new_metabolite)
        self.__swapper.set_type(type)

        if type == 2:
            self.__type_2_isGeneric_setter(metabolite_in_model)

        if not target:
            changed_reactions = self.__swapper.swap_only_metabolites_and_conjugates(
            )
            self.__swapped.append(new_metabolite)
        else:
            changed_reactions = self.__swapper.swap_metabolites()

        self.__universal_model = self.__swapper.get_universal_model()

        return changed_reactions

    def __type_2_isGeneric_setter(self, metabolite_in_model):

        container = self.__compounds_ontology.get_node_by_ont_id(
            metabolite_in_model)
        if container.generic:
            self.__swapper.setType2_isGenericInModel(True)
        else:
            self.__swapper.setType2_isGenericInModel(False)

    def __check_and_change_all_children(self,
                                        parent: int,
                                        new_metabolite: int,
                                        target=False) -> list:
        """
        This method absorbs all the compounds of a specific chemical type and swap them into the :param new_metabolite

        :param int parent: BOIMMG id of the structural parent
        :param int new_metabolite: BOIMMG id of the metabolite that will prevail
        :param boolean target: whether the new metabolite is the target or not
        :return list: changed reactions
        """

        children = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type(
            parent, "is_a")
        changed_reactions = []

        for child in children:
            if child != new_metabolite:

                child_container = self.__compounds_ontology.get_node_by_ont_id(
                    child)

                aliases = AliasesTransformer.transform_boimmg_aliases_into_model_seed(
                    child_container.aliases)

                model_seed_id = child_container.model_seed_id

                if model_seed_id:

                    converted_aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID(
                        model_seed_id)

                    merged_aliases = self.merge_dictionaries(
                        converted_aliases, aliases)

                    child_in_model = self.__mapper.check_metabolites_in_model(
                        child_container.inchikey, merged_aliases)

                else:

                    child_in_model = self.__mapper.check_metabolites_in_model(
                        child_container.inchikey, child_container.aliases,
                        child_container)

                if child_in_model:
                    changed_reactions = self.__swap_metabolites(
                        child, new_metabolite, 1, target)

        return changed_reactions

    def convert_aliases_into_mapper_format(self, aliases):
        """
        Such method can convert the aliases from retrieved from ModelSEED into the mapper format

        :param dict aliases: aliases from ModelSEED
        :return dict new_aliases: the converted dictionary
        """
        new_aliases = {}
        for alias in aliases:
            if alias in self.__compoundsAnnotationConfigs.keys():
                new_key = self.__compoundsAnnotationConfigs[alias]
                new_aliases[new_key] = aliases[alias]

        return new_aliases

    @staticmethod
    def merge_dictionaries(dict1, dict2):
        for key in dict1:
            if key in dict2:
                dict1[key].extend(dict2[key])
        return dict1

    def generate_new_metabolite(self, compound_container):
        """
        Such method generates a whole new metabolite using a ModelSEED compound wrapper or a CompoundNode

        :param compound_container: ModelSEED compound wrapper
        :return list: list of newly generated metabolites
        """

        if isinstance(compound_container, ModelSeedCompound):
            model_metabolites = \
                model_utilities.generate_model_compounds_by_database_format(self.model,
                                                                           compound_container.getDbId(),
                                                                           self.__compoundsIdConverter,
                                                                           self.__modelseedCompoundsDb,
                                                                           self.__database_format)
        elif isinstance(compound_container, CompoundNode):
            model_metabolites = model_utilities.generate_model_compounds_by_database_format(
                self.model, compound_container.model_seed_id,
                self.__compoundsIdConverter, self.__modelseedCompoundsDb,
                self.__database_format)

        else:
            raise ValueError("Not expected type")

        self.__model.add_metabolites(model_metabolites)
        self.__mapper.add_new_metabolites_to_maps(model_metabolites)
        return model_metabolites

    def generate_new_boimmg_metabolite(self,
                                       boimmg_container: CompoundNode) -> list:
        """
        Such method generates new BOIMMG compounds and adds them to the model (same compound in different compartments)

        :param CompoundNode boimmg_container: BOIMMG container for model addition
        :return list<Metabolite>: list of model metabolites in different compartments
        """

        model_metabolites = model_utilities.generate_boimmg_metabolites(
            self.model,
            boimmg_container,
            self.__database_format,
            self.__compoundsIdConverter,
            self.__compoundsAnnotationConfigs,
        )

        self.__model.add_metabolites(model_metabolites)
        self.__mapper.add_new_metabolites_to_maps(model_metabolites)
        return model_metabolites

    def add_metabolites_to_model(self, metabolites):

        for metabolite in metabolites:

            container = self.__compounds_ontology.get_node_by_ont_id(
                metabolite)
            metabolites_in_model = self.__mapper.check_metabolites_in_model(
                container.inchikey, container.aliases, container)

            if not metabolites_in_model:

                if container.model_seed_id:
                    ms_container = self.__modelseedCompoundsDb.get_compound_by_id(
                        container.model_seed_id)
                    self.generate_new_metabolite(ms_container)

                else:
                    self.generate_new_boimmg_metabolite(container)

    def transform_input_into_boimmg_ids(self, target: str) -> str:
        """
        Method that converts a target ID from an external database into BOIMMG's

        :param str target: target identifier of an external database
        :return str: boimmg identifier
        """

        accessor = CompoundsDBAccessor()

        boimmg_prefix = self.__compoundsAnnotationConfigs[
            "BOIMMG_ID_CONSTRUCTION"]
        target_res = self._transform_database_ids_into_boimmg_ids(
            target, accessor, boimmg_prefix)

        return target_res

    def _transform_database_ids_into_boimmg_ids(self, target: str,
                                                accessor: CompoundsDBAccessor,
                                                boimmg_prefix: str) -> str:
        """
        Such method transforms a target ID from an external database into BOIMMG's

        :param str target: target identifier from an external database
        :param CompoundsDBAccessor accessor:
        :param str boimmg_prefix: BOIMMG prefix
        :return:
        """

        targets_res = ''
        if boimmg_prefix in target:
            targets_res = int(target.replace(boimmg_prefix, ""))

        elif re.match("^[0-9]*$", target):

            targets_res = int(target)

        elif "cpd" not in target:
            model_seed_ids = self.__compoundsIdConverter.convert_db_id_to_model_seed_by_db_id(
                target)

        else:
            model_seed_ids = [target]

        if not targets_res:
            for model_seed_id in model_seed_ids:
                node1 = accessor.get_node_from_model_seed_id(model_seed_id)

                if node1:
                    targets_res = node1.id
                    break

        return targets_res