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)
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')
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()
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()
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
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