def __define_instance_variables(self): """ Define instance variables :return: """ self.__universal_model = Model("universal_model") self.__swapped = [] 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.__compoundsIdConverter = CompoundsIDConverter() self.__compounds_revisor = CompoundsRevisor(self.model, self.__universal_model) biocyc.set_organism("meta") self.mapper = ModelMapper(self.model, self.__compoundsAnnotationConfigs, self.__compoundsIdConverter) self.__compounds_revisor.set_model_mapper(self.mapper) self.granulator = Granulator(self.model, self.mapper, self.__database_format, self.__compoundsIdConverter, self.__compoundsAnnotationConfigs)
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 define_instance_variables(self): """ Define instance variables :return: """ self.report_material = {} self.__compoundsAnnotationConfigs = file_utilities.read_conf_file( COMPOUNDS_ANNOTATION_CONFIGS_PATH) self.__reactionsAnnotationConfigs = file_utilities.read_conf_file( REACTIONS_ANNOTATION_CONFIGS_PATH) self.__compounds_ontology = CompoundsDBAccessor() self.__home_path__ = ROOT_DIR self.__configs = file_utilities.read_conf_file(TOOL_CONFIG_PATH) self.changed_reactions = [] self.reactions_swapper = ReactionsChanger( self.model, self.__type, self.__model_database, self.__universal_model, compounds_converter=self.__compoundsIdConverter)
def __check_generic_complete_relationship(self,reactants,products,reaction): generic_reactants = [] complete_reactants = [] generic_products = [] complete_products = [] compounds_ontology = CompoundsDBAccessor() for reactant in reactants: if reactant.generic: generic_reactants.append(reactant) else: complete_reactants.append(reactant) for product in products: if product.generic: generic_products.append(product) else: complete_products.append(product) if len(complete_reactants) == len(generic_products) or len(generic_reactants) == len(complete_products): return True elif not generic_reactants and not generic_products: reactants_components = [] products_components = [] reactants_components_dict = {} products_components_dict = {} for complete_reactant in complete_reactants: reactant_components = compounds_ontology.get_predecessors_by_ont_id_rel_type(complete_reactant.id,"component_of") reactants_components.append(reactant_components) reactants_components_dict[complete_reactant.id] = reactant_components for complete_product in complete_products: product_components = compounds_ontology.get_predecessors_by_ont_id_rel_type(complete_product.id,"component_of") products_components.append(product_components) products_components_dict[complete_product.id] = products_components reactants_components = sorted(reactants_components) products_components = sorted(products_components) if reactants_components!=products_components: deleted = self.__delete_components_from_reaction(reactants_components, products_components,reactants_components_dict, products_components_dict,reaction) if deleted: return True else: return False return True
def get_targets_to_replace_by_type(self, target: int): compounds_ontology = CompoundsDBAccessor() res = {} precursors = compounds_ontology.get_all_predecessors_by_ont_id_rel_type( target, "precursor_of") for precursor in precursors: parent = compounds_ontology.get_successors_by_ont_id_rel_type( precursor, "is_a") if parent[0] in res: res.get(parent[0]).append(precursor) else: res[parent[0]] = [precursor] return 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
def transform_targets_and_components_into_boimmg_ids( self, targets, components): """ Conversion of components and lipid targets into BOIMMG's format :param targets: :param components: :return: """ targets_res = [] components_res = [] accessor = CompoundsDBAccessor() boimmg_prefix = self.__compoundsAnnotationConfigs[ "BOIMMG_ID_CONSTRUCTION"] for target in targets: new_target = self._transform_database_ids_into_boimmg_ids( target, accessor, boimmg_prefix) if not new_target: exit(2) targets_res.append(new_target) for component in components: new_component = self._transform_database_ids_into_boimmg_ids( component, accessor, boimmg_prefix) if not new_component: exit(2) components_res.append(new_component) return targets_res, components_res
def define_instance_variables(self): """ Instance variables definition :return: """ self.__compounds_ontology = CompoundsDBAccessor() self.__added_reactions_and_respective_target = {} self.__reactionsAnnotationConfigs = file_utilities.read_conf_file( REACTIONS_ANNOTATION_CONFIGS_PATH) self.metabolite_report_material = {} self.reaction_report_material = {} self.__set_components()
def __init__(self, model, compoundsAnnotationConfigs, compoundsIdConverter): self.model = model self.__compoundsAnnotationConfigs = compoundsAnnotationConfigs self.__compoundsIdConverter = compoundsIdConverter self.__compounds_ontology = CompoundsDBAccessor() self.mapped = False self.boimmg_db_model_map = {} self.boimmg_db_model_map_reverse = {} self.compounds_aliases_indexation = {} self.compound_inchikey_indexation = {} self.__compounds_aliases_indexation_reverse = {}
def test_components_scraping(self): db_acessor = CompoundsDBAccessor() components = [200, 437, 436, 129] all_new_met = [] compounds = db_acessor.get_compounds_with_specific_parent_within_set_of_components( 12, components) for compound in compounds: precursors = db_acessor.get_all_predecessors_by_ont_id_rel_type( compound, "precursor_of") all_new_met.extend(precursors) # res = [] # for new_met in all_new_met: # if new_met not in res: # res.append(new_met) print(len(all_new_met))
def define_instance_variables(self): """ Instance variables definition :return: """ self.__compounds_ontology = CompoundsDBAccessor() self.__added_reactions_and_respective_target = {} self.__reactionsAnnotationConfigs = file_utilities.read_conf_file( REACTIONS_ANNOTATION_CONFIGS_PATH) print("setting components...") start = time.time() self.__set_components() end = time.time() print("components set: %d" % (end - start))
def integrate_quinones(): accessor = CompoundsDBAccessor() ele_quinone = accessor.get_predecessors_by_ont_id_rel_type(749300, "is_a") ele_quinol = accessor.get_predecessors_by_ont_id_rel_type(749301, "is_a") for ele_quinon in ele_quinone: ele_quinone_precursors = accessor.get_all_predecessors_by_ont_id_rel_type( ele_quinon, "precursor_of") for pre in ele_quinone_precursors: accessor.add_relationship(pre, 321415, "is_a") for ele_quino in ele_quinol: ele_quinone_precursors = accessor.get_all_predecessors_by_ont_id_rel_type( ele_quino, "precursor_of") for pre in ele_quinone_precursors: accessor.add_relationship(pre, 321415, "is_a")
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 __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 check_compounds_representation_and_balance_reactions(self, reactions:list): res = [] self.__get_hydrogen_from_model() compounds_ontology = CompoundsDBAccessor() to_remove = [] for reaction in reactions: reaction_ontology_reactants = [] reaction_ontology_products = [] for compound in reaction.reactants: aliases = AnnotationUtils.get_annotation_from_cobra_annotation(compound) found = False for key in aliases: for alias in aliases[key]: new_key = self.compoundsAnnotationConfigs.get(key) if key == "BOIMMG": id = self.get_boimmg_id_from_annotation(aliases[key]) container = compounds_ontology.get_node_by_ont_id(id) reaction_ontology_reactants.append(container) found = True break elif new_key in self.__mapper.compounds_aliases_indexation.keys(): entities = self.__mapper.compounds_aliases_indexation.get(new_key).get(alias) if entities: for entity in entities: entity_id = entity.id if entity_id in self.__mapper.boimmg_db_model_map: ont_id = self.__mapper.boimmg_db_model_map.get(entity_id) entity_container = compounds_ontology.get_node_by_ont_id(ont_id) reaction_ontology_reactants.append(entity_container) found = True break if found: break for compound in reaction.products: found = False aliases = AnnotationUtils.get_annotation_from_cobra_annotation(compound) for key in aliases: new_key = self.compoundsAnnotationConfigs.get(key) for alias in aliases[key]: if key == "BOIMMG": id = self.get_boimmg_id_from_annotation(aliases[key]) container = compounds_ontology.get_node_by_ont_id(id) reaction_ontology_products.append(container) found = True break elif new_key in self.__mapper.compounds_aliases_indexation.keys(): entities = self.__mapper.compounds_aliases_indexation.get(new_key).get(alias) if entities: for entity in entities: entity_id = entity.id if entity_id in self.__mapper.boimmg_db_model_map: ont_id = self.__mapper.boimmg_db_model_map.get(entity_id) entity_container = compounds_ontology.get_node_by_ont_id(ont_id) reaction_ontology_products.append(entity_container) found = True break if found: break # self.__check_generic_complete_relationship(reaction_ontology_reactants,reaction_ontology_products,reaction) # if reaction_ontology_reactants and reaction_ontology_products: balanced = self.check_balanced_reaction(reaction) if not balanced: to_remove.append(reaction) else: res.append(reaction) # if generalization: # self.__check_if_generic_complete_relationship() # print("reactions to remove: ") # print(to_remove) self.__model.remove_reactions(to_remove) return res
class Granulator: 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() @property def model(self): return self.__model @model.setter def model(self, value): self.__model = value @property def mapper(self): return self.__mapper @mapper.setter def mapper(self, value): self.__mapper = value @property def virtual_model_mapper(self): return self.__virtual_model_mapper @virtual_model_mapper.setter def virtual_model_mapper(self, value): self.__virtual_model_mapper = value def define_instance_variables(self): """ Instance variables definition :return: """ self.__compounds_ontology = CompoundsDBAccessor() self.__added_reactions_and_respective_target = {} self.__reactionsAnnotationConfigs = file_utilities.read_conf_file( REACTIONS_ANNOTATION_CONFIGS_PATH) self.metabolite_report_material = {} self.reaction_report_material = {} self.__set_components() def set_virtual_model(self, virtual_model, virtual_model_mapper, virtual_compounds_revisor): self.__virtual_model = virtual_model self.__virtual_compounds_revisor = virtual_compounds_revisor self.__virtual_model_mapper = virtual_model_mapper def write_in_progress_bar(self, message, value): with open(PROGRESS_BAR, "w") as file: file.write(message + ":" + str(value)) def get_progress_bar_state(self): 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, total_processes_left): left = 100 - state for_each_part = left / total_processes_left for_each_iteration = for_each_part / total return for_each_iteration def granulate(self, target_generic_ontology_id, components, same_components, progress_bar_processes_left): """ Operation to granulate a given compound: 1st: Build up structurally defined compounds using the information on the components list. It builds up compounds by mixing :param components if :param same_components is False, otherwise it builds up compounds without a mix of :param components. 2nd: Calls a function to generate the whole biosynthetic pathway of all the built up compounds. :param int target_generic_ontology_id: generic compound database identifier :param list<int> components: list of BOIMMG identifiers of all the requested components :param bool same_components: :param int progress_bar_processes_left: :return: """ if same_components: targets_to_replace = \ self.__compounds_ontology.get_compounds_with_only_one_component(target_generic_ontology_id, components) else: targets_to_replace = \ self.__compounds_ontology.get_compounds_with_specific_parent_within_set_of_components( target_generic_ontology_id, components) targets_to_replace = self.filter_targets_to_replace( targets_to_replace, target_generic_ontology_id) state = self.get_progress_bar_state() for_each_iteration = self.calculate_division_for_progress_bar( state, len(targets_to_replace), progress_bar_processes_left) for target in targets_to_replace: self.write_in_progress_bar( "generating network for C_BOIMMG_" + str(target), state) self.handle_target_in_virtual_model(target, target_generic_ontology_id) state += for_each_iteration def handle_target_in_virtual_model(self, target: int, parent: int): """ Method to granulate a given lipid target in the virtual model. 1st: Processes the target biosynthesis pathway; 2nd: Balance the granulated reactions in the previously processed biosynthesis pathway; 3rd: Adds them to the model :param int target: lipid target BOIMMG identifier (structurally defined) :param int parent: lipid parent BOIMMG identifier (generic lipid) :return: """ granulated_reactions = self.__process_biosynthesis_pathway( target, parent) granulated_reactions = self.__virtual_compounds_revisor.balance_reactions( granulated_reactions) reactions_to_add = deepcopy(granulated_reactions) self.__add_new_reactions_to_model(reactions_to_add) def identify_biosynthesis_pathway(self, target_generic_ontology_id: int) -> list: """ Identifies the biosynthesis pathway of a given generic lipid. :param int target_generic_ontology_id: :return list<Reaction>: list of reactions """ reactions_to_delete = self.get_target_associated_network( target_generic_ontology_id) return reactions_to_delete def __process_biosynthesis_pathway(self, target: int, parent: int) -> list: """ Granulates the biosynthesis pathway of a given target lipid. It uses a "processing" stack to process each reaction and each new structurally defined lipid. When the stack is empty it is assumed the pathway to be fully processed. :param int target: lipid target BOIMMG identifier (structurally defined) :param int parent: lipid parent BOIMMG identifier (generic lipid) :return list<Reaction>: list of granulated reactions """ processed_compounds = [] new_compounds = [(target, parent)] granulated_reactions = [] while new_compounds: new_compound_and_parent = new_compounds.pop() if new_compound_and_parent[0] not in processed_compounds: new_reactions, added_compounds = self.__process_new_compound( new_compound_and_parent) processed_compounds.append(new_compound_and_parent[0]) self.__add_new_reactions_to_virtual_model(new_reactions) granulated_reactions.extend(new_reactions) new_compounds.extend(added_compounds) return granulated_reactions def __process_new_compound(self, new_compound_and_parent: tuple): """ Processes a new compound :param tuple new_compound_and_parent: (structurally defined compound, its generic parent) :return: """ new_compound = new_compound_and_parent[0] parent = new_compound_and_parent[1] model_boimmg_parents = self.virtual_model_mapper.check_if_boimmg_metabolite_in_model( parent) if not model_boimmg_parents: exit(2) raise Exception("please introduce a mapped biosynthetic target") parent_and_precursors = self.get_targets_to_replace_by_type( new_compound) new_reactions = [] added_compounds = [] processed = [] for model_parent in model_boimmg_parents: if model_parent not in processed: cobra_model_parent = self.__virtual_model.metabolites.get_by_id( model_parent) reactions_to_process = self.get_reactions_by_compound( cobra_model_parent) for reaction_to_process in reactions_to_process: if reaction_to_process.id not in self.__added_reactions_and_respective_target.keys() or \ new_compound not in self.__added_reactions_and_respective_target[reaction_to_process.id]: go = True compounds_ids = [ comp.id for comp in reaction_to_process.products ] if go and model_parent in compounds_ids: new_reaction, added = self._process_reaction( reaction_to_process, new_compound, cobra_model_parent, parent_and_precursors) if reaction_to_process.id in self.reaction_report_material: self.reaction_report_material[ reaction_to_process.id].append( new_reaction.id) else: self.reaction_report_material[ reaction_to_process.id] = [ new_reaction.id ] new_reactions.append(new_reaction) for compound in added: if compound not in added_compounds: added_compounds.append(compound) if reaction_to_process.id not in self.__added_reactions_and_respective_target.keys( ): self.__added_reactions_and_respective_target[ reaction_to_process.id] = [new_compound] else: self.__added_reactions_and_respective_target[ reaction_to_process.id].append( new_compound) processed.append(model_parent) return new_reactions, added_compounds def get_reactions_by_compound(self, compound): res = [] for reaction in self.__virtual_model.reactions: metabolites_ids = [m.id for m in reaction.metabolites] if compound.id in metabolites_ids: res.append(reaction) return res def _process_reaction( self, reaction_to_process: Reaction, new_compound: int, model_parent: Metabolite, parent_and_precursors: dict ) -> Tuple[Reaction, List[Tuple[Metabolite, int]]]: """ Granulates the :param reaction_to_process :param Reaction reaction_to_process: reaction in model to be granulated :param int new_compound: structurally defined lipid BOIMMG identifier :param Metabolite model_parent: model generic lipid :param dict parent_and_precursors: {parent: [children]} -> children of the generic precursors :return tuple: the granulated reaction in the cobrapy Reaction object and list of tuples: (added compound, BOIMMG ID) """ new_reaction = deepcopy(reaction_to_process) new_reaction_products = list(new_reaction.products) new_reaction, added = self.__process_reaction(new_reaction, new_compound, model_parent, parent_and_precursors, new_reaction_products) reaction_id = self.change_boimmg_reaction_id(new_reaction) new_reaction.id = reaction_id return new_reaction, added def change_boimmg_reaction_id(self, reaction: Reaction) -> str: """ Changes the reaction ID into a cannonical BOIMMG reaction identifier :param Reaction reaction: :return str: new identifier """ new_id = self.__reactionsAnnotationConfigs["BOIMMG_ID_CONSTRUCTION"] metabolites = reaction.metabolites metabolites = sorted([metabolite.id for metabolite in metabolites]) new_id += "_".join(metabolites) if len(new_id) > 250: new_id = new_id[:230] reaction.id = new_id return reaction.id def __process_reaction( self, new_reaction: Reaction, new_compound: int, model_parent: Metabolite, parent_and_precursors: dict, new_reaction_metabolites: List[Metabolite] ) -> Tuple[Reaction, List[Tuple[Metabolite, int]]]: """ Granulates a given reaction. Replaces the generic metabolite by its structurally defined child and corrects the precursors. :param Reaction new_reaction: the new reaction :param int new_compound: the reaction structurally defined product :param Metabolite model_parent: the model parent of the structurally defined product :param dict parent_and_precursors: dictionary with lipid parents and their children :param List[Metabolite] new_reaction_metabolites: list of possibly new metabolites :return Tuple[Reaction, List[Tuple[Metabolite, int]]]: returns a tuple with the granulated model reaction and the new added compounds that will be processed further. """ i = 0 found = False while not found and i < len(new_reaction_metabolites): if new_reaction_metabolites[i].id == model_parent.id: new_model_parent = new_reaction_metabolites[i] found = True i += 1 coef = new_reaction.get_coefficient(model_parent.id) new_metabolite = self.add_boimmg_metabolites_to_reaction( new_compound, coef, new_reaction, model_parent.compartment) if model_parent.id in self.metabolite_report_material: self.metabolite_report_material[model_parent.id].append( new_metabolite.id) else: self.metabolite_report_material[model_parent.id] = [ new_metabolite.id ] met_to_subtract = {} met_to_subtract[new_model_parent] = coef new_reaction.subtract_metabolites(met_to_subtract) added = self._correct_precursors(new_reaction, new_compound, parent_and_precursors) return new_reaction, added def _correct_precursors(self, new_reaction: Reaction, new_compound:int, parent_and_precursors:dict) -> \ List[Tuple[Metabolite, int]]: """ Correct the precursors in the new reaction. :param Reaction new_reaction: the new reaction :param int new_compound: the new structurally defined lipid species BOIMMG identifier :param dict parent_and_precursors: dictionary with lipid parents and their children :return List[Tuple[Metabolite, int]]: returns a tuple with the granulated model reaction and the new added compounds that will be processed further. """ new_compound_components = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( new_compound, "component_of") reactants = list(new_reaction.reactants) added = self.__correct_precursors(new_reaction, parent_and_precursors, reactants, new_compound_components) return added def __correct_precursors(self, new_reaction: Reaction, parent_and_precursors: dict, metabolites: List[Metabolite], new_compound_components: List[int]) -> \ List[Tuple[Metabolite, int]]: """ Correct the precursors in the new reaction. :param Reaction new_reaction: the new reaction :param dict parent_and_precursors: dictionary with lipid parents and their children :param List[Metabolite] metabolites: number of reactants in the new reaction to be granulated :param List[int] new_compound_components: components of the new product in the reaction :return: """ added = [] while metabolites: reactant = metabolites.pop() boimmg_id = self.virtual_model_mapper.get_boimmg_id_from_model_compound_id( reactant.id) if boimmg_id: coef = new_reaction.metabolites[reactant] if boimmg_id in parent_and_precursors: precursors = parent_and_precursors[boimmg_id] for precursor in precursors: self.add_boimmg_metabolites_to_reaction( precursor, coef, new_reaction, reactant.compartment) added.append((precursor, boimmg_id)) met_to_subtract = {} met_to_subtract[reactant] = coef new_reaction.subtract_metabolites(met_to_subtract) else: to_replace = self.__compounds_ontology.get_compounds_with_specific_parent_set_of_components( boimmg_id, new_compound_components) if to_replace: to_replace = self.filter_targets_to_replace( to_replace, boimmg_id) self.add_boimmg_metabolites_to_reaction( to_replace[0], coef, new_reaction, reactant.compartment) met_to_subtract = {} met_to_subtract[reactant] = coef new_reaction.subtract_metabolites(met_to_subtract) added.append((to_replace[0], boimmg_id)) return added def add_boimmg_metabolites_to_reaction(self, boimmg_id: int, coef: int, reaction: Reaction, compartment: str): """ Add a metabolite to a given reaction receiving BOIMMG identifier as input. :param int boimmg_id: BOIMMG identifier of the metabolite being inserted in the reaction :param int coef: stoichimetric coefficient in the reaction :param Reaction reaction: model reaction :param str compartment: compartment :return: """ model_seed_ids = self.__compounds_ontology.get_all_model_seed_ids( boimmg_id) node = self.__compounds_ontology.get_node_by_ont_id(boimmg_id) aliases = node.aliases found = False i = 0 while not found and i < len(model_seed_ids): aliases2 = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID( model_seed_ids[i]) aliases.update(aliases2) model_child = self.mapper.check_if_boimmg_metabolite_in_model( boimmg_id, aliases) if model_child: found = True i += 1 if not model_seed_ids: model_child = self.mapper.check_if_boimmg_metabolite_in_model( boimmg_id) if not model_child: new_model_compound = self.__create_boimmg_metabolite( boimmg_id, compartment) met_to_add = {} met_to_add[new_model_compound] = coef reaction.add_metabolites(met_to_add) else: found = False i = 0 while not found and i < len(model_child): cobra_child_container = self.model.metabolites.get_by_id( model_child[i]) if cobra_child_container.compartment == compartment: found = True if self.__virtual_model.metabolites.has_id(model_child[i]): found_model_compound = cobra_child_container else: virtual_compound = deepcopy(cobra_child_container) self.__virtual_model.add_metabolites( [virtual_compound]) found_model_compound = virtual_compound i += 1 if not found: new_model_compound = self.__create_boimmg_metabolite( boimmg_id, compartment) met_to_add = {} met_to_add[new_model_compound] = coef reaction.add_metabolites(met_to_add) else: met_to_add = {} met_to_add[found_model_compound] = coef reaction.add_metabolites(met_to_add) return new_model_compound def __create_boimmg_metabolite(self, boimmg_id: int, compartment: str) -> Metabolite: """ Generates a new model compound using the internal database information. :param int boimmg_id: BOIMMG identifier :param str compartment: compartment :return Metabolite: the new metabolite """ new_compound_node = self.__compounds_ontology.get_node_by_ont_id( boimmg_id) model_seed_ids = self.__compounds_ontology.get_all_model_seed_ids( boimmg_id) for model_seed_id in model_seed_ids: translation = self.__compoundsIdConverter.get_modelSeedIdToDb( ).get(model_seed_id) definitive_model_seed_id = model_seed_id if self.__database_format == "BiGG" and \ ("BiGG" in translation.keys() or "BiGG1" in translation.keys()): definitive_model_seed_id = model_seed_id break elif self.__database_format == "KEGG" and \ "KEGG" in translation.keys(): definitive_model_seed_id = model_seed_id break new_model_compound = model_utilities.generate_boimmg_metabolites_in_compartment( new_compound_node, compartment, self.__compoundsIdConverter, self.__compoundsAnnotationConfigs) self.add_metabolites_to_the_virtual_model([new_model_compound]) return new_model_compound def add_metabolites_to_the_virtual_model(self, metabolites): self.__virtual_model.add_metabolites(metabolites) self.virtual_model_mapper.add_new_metabolites_to_maps(metabolites) @staticmethod def merge_dictionaries(dict1, dict2): for key in dict1: if key in dict2: dict1[key].extend(dict2[key]) return dict1 def get_target_associated_network( self, target_generic_ontology_id: int) -> List[Reaction]: """ Identifies the target's biosynthesis network in the model :param int target_generic_ontology_id: :return List[Reaction]: list of reactions in the network """ res = [] res_ids = [] predecessors = \ self.__compounds_ontology.get_all_predecessors_by_ont_id_rel_type(target_generic_ontology_id, "precursor_of") predecessors_and_target = predecessors.copy() predecessors_and_target.append(target_generic_ontology_id) network_metabolites_in_model = [] for token in predecessors_and_target: metabolites_in_model = self.__check_if_compound_exists_in_model_by_ontology_id( token) network_metabolites_in_model.extend(metabolites_in_model) network_metabolites_ids = [m.id for m in network_metabolites_in_model] for metabolites_in_model in network_metabolites_in_model: reactions = metabolites_in_model.reactions for reaction in reactions: if reaction.id not in res_ids: reactants = reaction.reactants products = reaction.products reactant_found = False product_found = False i = 0 while not reactant_found and i < len(reactants): reactant = reactants[i] reactant_id = reactant.id if reactant_id in network_metabolites_ids: reactant_found = True i += 1 j = 0 while not product_found and j < len(products): product = products[j] product_id = product.id if product_id in network_metabolites_ids: product_found = True j += 1 if product_found and reactant_found: res.append(reaction) res_ids.append(reaction.id) return res def __check_if_compound_exists_in_model_by_ontology_id( self, ontology_id: int) -> List[Metabolite]: """ This method will check whether a BOIMMG compound exists in the model. :param int ontology_id: BOIMMG id :return List[Metabolite]: 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 __add_new_reactions_to_virtual_model(self, new_reactions): self.virtual_model_mapper.add_new_reactions_to_model(new_reactions) self.__virtual_model.add_reactions(new_reactions) def __add_new_reactions_to_model(self, new_reactions): self.mapper.add_new_reactions_to_model(new_reactions) self.model.add_reactions(new_reactions) def get_targets_to_replace_by_type(self, target: int) -> dict: """ Identifies targets components, precursors and successors in the biosynthesis network. Returns a dictionary with the precursors' generic parent as keys and a list of structurally defined precursors as values. :param int target: BOIMMG identifier :return dict: dictionary with the precursors' generic parent as keys and a list of structurally defined precursors as values """ res = {} precursors = self.__compounds_ontology.get_all_predecessors_by_ont_id_rel_type( target, "precursor_of") successors = self.__compounds_ontology.get_successors_by_ont_id_rel_type( target, "precursor_of") components = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( target, "component_of") for component in components: if component in self.fatty_acids: if self.generic_fatty_acid in res: res.get(self.generic_fatty_acid).append(component) else: res[self.generic_fatty_acid] = [component] for precursor in precursors: parent = self.__compounds_ontology.get_successors_by_ont_id_rel_type( precursor, "is_a") if parent[0] in res: res.get(parent[0]).append(precursor) else: res[parent[0]] = [precursor] for successor in successors: parent = self.__compounds_ontology.get_successors_by_ont_id_rel_type( successor, "is_a") if parent[0] in res: res.get(parent[0]).append(successor) else: res[parent[0]] = [successor] return res # def find_components_reactions_and_generalize(self): # # candidate_reactions = [] # # res = {} # # generic_compounds = [] # pseudo_components = [] # components = [] # components_boimmg_id = [] # # for compound in self.mapper.boimmg_db_model_map: # # boimmg_id =self.mapper.boimmg_db_model_map[compound] # if boimmg_id in self.__components: # model_compound = self.model.metabolites.get_by_id(compound) # pseudo_components.append(compound) # candidate_reactions.extend(list(model_compound.reactions)) # # if boimmg_id in self.fatty_acids: # components.append(compound) # # node = self.__compounds_ontology.get_node_by_ont_id(self.mapper.boimmg_db_model_map[compound]) # # if node.generic: # generic_compounds.append(compound) # # for reaction in candidate_reactions: # # regex = re.compile("[Bb][Ii][Oo][Mm][Aa][Ss][Ss]") # # if reaction.annotation != "SBO:0000629" and not regex.match(reaction.name): # # reactants = reaction.reactants # products = reaction.products # # reactant_found = False # product_found = False # # pseudo_component_in_reactants = False # # isComponent = False # # for reactant in reactants: # reactant_id = reactant.id # # if reactant_id in generic_compounds: # reactant_found = True # # elif reactant_id in pseudo_components: # pseudo_component_in_reactants = True # # if reactant_id in components: # isComponent = True # # for product in products: # product_id = product.id # if product_id in generic_compounds: # product_found = True # # elif product_id in components: # isComponent = True # # if reactant_found or product_found: # # new_reaction, subtracted = \ # self.remove_components_from_reaction(reaction,pseudo_components,pseudo_component_in_reactants,isComponent) # # for sub in subtracted: # if sub not in components_boimmg_id: # components_boimmg_id.append(sub) # # # res[reaction.id] = (new_reaction,isComponent,pseudo_component_in_reactants,subtracted) # # return res,components_boimmg_id # def remove_components_from_reaction(self,reaction,pseudo_components,pseudo_component_in_reactants,isComponent): # # new_reaction = deepcopy(reaction) # # component_parent = None # if pseudo_component_in_reactants: # # reactants = list(new_reaction.reactants) # # to_subtract = {} # # while reactants: # reactant = reactants.pop() # if reactant.id in self.mapper.boimmg_db_model_map.keys(): # if reactant.id in pseudo_components: # # if not component_parent: # child = self.mapper.get_boimmg_id_from_model_compound_id(reactant.id) # parent = self.__compounds_ontology.get_successors_by_ont_id_rel_type(child, "is_a") # component_parent = parent[0] # # coef = new_reaction.metabolites[reactant] # to_subtract[reactant] = coef # # new_reaction.subtract_metabolites(to_subtract) # # components = [] # for subtracted in to_subtract: # if isComponent: # boimmg_id = self.mapper.get_boimmg_id_from_model_compound_id(subtracted.id) # components.append(boimmg_id) # # else: # boimmg_id = self.mapper.get_boimmg_id_from_model_compound_id(subtracted.id) # new_components = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type(boimmg_id, # "component_of") # components.extend(new_components) # # if isComponent: # self.add_boimmg_metabolites_to_reaction(self.generic_fatty_acid, -1, new_reaction, reactant.compartment) # # else: # # self.add_boimmg_metabolites_to_reaction(component_parent,-1,new_reaction,reactant.compartment) # # return new_reaction, components # # else: # products = list(new_reaction.products) # # to_subtract = {} # # while products: # product = products.pop() # # if product.id in self.mapper.boimmg_db_model_map.keys(): # if product.id in pseudo_components: # # if not component_parent: # # child = self.mapper.get_boimmg_id_from_model_compound_id(product.id) # parent = self.__compounds_ontology.get_successors_by_ont_id_rel_type(child, "is_a") # # component_parent = parent[0] # # coef = new_reaction.metabolites[product] # to_subtract[product] = coef # # if isComponent: # self.add_boimmg_metabolites_to_reaction(self.generic_fatty_acid, 1, new_reaction, product.compartment) # # else: # # self.add_boimmg_metabolites_to_reaction(component_parent, 1, reaction, new_reaction.compartment) # # new_reaction.subtract_metabolites(to_subtract) # # components = [] # for subtracted in to_subtract: # if isComponent: # boimmg_id = self.mapper.get_boimmg_id_from_model_compound_id(subtracted.id) # components.append(boimmg_id) # # else: # boimmg_id = self.mapper.get_boimmg_id_from_model_compound_id(subtracted.id) # new_components = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type(boimmg_id, # "component_of") # components.extend(new_components) # # # return new_reaction, components # def __get_children_in_model(self,product): # # children_in_model = {} # # parent_boimmg_id = self.virtual_model_mapper.get_boimmg_id_from_model_compound_id(product.id) # # if parent_boimmg_id: # children = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type(parent_boimmg_id,"is_a") # # for mapped_compound in self.virtual_model_mapper.boimmg_db_model_map: # eventual_child = self.virtual_model_mapper.boimmg_db_model_map[mapped_compound] # # if eventual_child in children: # # children_in_model[eventual_child] = self.virtual_model_mapper.boimmg_db_model_map[mapped_compound] # # return children_in_model # def check_if_decomposition_reaction(self,reaction:Reaction): # # reactants = reaction.reactants # products = reaction.products # # inReactants = self.__check_component_in_reaction_side(reactants) # # inProducts = self.__check_component_in_reaction_side(products) # # if inReactants or inProducts: # return True,inReactants # # else: # return False, inReactants # def __check_component_in_reaction_side(self,metabolites): # for metabolite in metabolites: # # boimmg_id = self.virtual_model_mapper.get_boimmg_id_from_model_compound_id(metabolite.id) # # if boimmg_id: # if boimmg_id == self.generic_fatty_acid or boimmg_id == self.__generic_acps or \ # boimmg_id == self.__generic_acyl_coa: # return True # # else: # return False def __set_components(self): self.fatty_acids = self.__compounds_ontology.get_leaves_from_ont_id( 527) self.generic_fatty_acid = 527 # self.__acyl_coas = self.__compounds_ontology.get_leaves_from_ont_id(43) # self.__generic_acyl_coa = 43 # # self.__acyl_acps = self.__compounds_ontology.get_leaves_from_ont_id(704832) # self.__generic_acps = 704832 # self.__components = self.fatty_acids + self.__acyl_acps + self.__acyl_coas # self.__components = self.fatty_acids # def solve_components_reactions(self,same_components=False,components_reactions = {}, components = []): # # if not components_reactions and not components: # components_reactions,components = self.find_components_reactions_and_generalize() # # new_reactions = [components_reactions[reaction][0] for reaction in components_reactions.keys()] # # self.__add_new_reactions_to_virtual_model(new_reactions) # # self.__solve_components_reactions(components_reactions,components,same_components) def __solve_components_reactions(self, components_reactions, components, same_components): for reaction in components_reactions: self.__correct_component_reaction(components_reactions[reaction], components, same_components) # def __correct_component_reaction(self,reaction_features,components,same_components): # # new_reaction = reaction_features[0] # isReactant = reaction_features[2] # deleted = reaction_features[3] # # reactants = new_reaction.reactants # products = new_reaction.products # # # r_groups_reactants,r_groups_products = self.get_r_groups_from_reaction_compounds(reactants,products) # # if isReactant: # # boimmg_compound = self.find_boimmg_compound(products) # # if boimmg_compound: # # self.granulate(boimmg_compound, components, same_components) # # else: # boimmg_compound = self.find_boimmg_compound(reactants) # # if boimmg_compound: # self.granulate(boimmg_compound, components, same_components,decomposition=True) def find_boimmg_compound(self, compounds): """ It finds only one boimmg compound within a list of model compounds :param compounds: :return: """ for compound in compounds: boimmg_id = self.mapper.get_boimmg_id_from_model_compound_id( compound.id) if boimmg_id: return boimmg_id return None # def get_r_groups_from_reaction_compounds(self,reactants,products): # # r_groups_reactants = 0 # r_groups_products = 0 # # for reactant in reactants: # r_groups_reactants += self.get_r_groups_from_compound(reactant) # # for product in products: # r_groups_products += self.get_r_groups_from_compound(product) # # return r_groups_reactants,r_groups_products # def get_r_groups_from_compound(self,model_compound): # # boimmg_id = self.virtual_model_mapper.get_boimmg_id_from_model_compound_id(model_compound.id) # if boimmg_id: # node = self.__compounds_ontology.get_node_by_ont_id(boimmg_id) # smiles = node.smiles # # if smiles: # return smiles.count("*") # # return 0 # return 0 def filter_targets_to_replace(self, targets: List[int], parent: int) -> List[int]: """ Filter the predicted precursors by side chains. :param List[int] targets: :param int parent: :return List[int]: filtered list """ res = [] for target in targets: components = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( target, "component_of") node = self.__compounds_ontology.get_node_by_ont_id(target) child_smiles = node.smiles parent_node = self.__compounds_ontology.get_node_by_ont_id(parent) parent_smiles = parent_node.smiles molecules = chemo_utilities.get_side_chains( parent_smiles, child_smiles) if molecules: new_molecules = [] new_molecules_n = 0 for molecule in molecules: if molecule not in new_molecules: new_molecules_n += 1 new_molecules.append(molecule) if new_molecules_n == len(components): res.append(target) return res
def test_database_access(self): accessor = CompoundsDBAccessor() accessor.get_successors_by_ont_id_rel_type(3, "is_a")
class RedundantCaseSolver(RepresentationProblemSolver): 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) @property def model(self): return self.__model @model.setter def model(self, value): self.__model = value @property def mapper(self): return self.__mapper @mapper.setter def mapper(self, value): self.__mapper = value def write_in_progress_bar(self, message, value): with open(PROGRESS_BAR, "w") as file: file.write(message + ":" + str(value)) def __define_instance_variables(self): """ Define instance variables :return: """ self.__universal_model = Model("universal_model") self.__swapped = [] 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.__compoundsIdConverter = CompoundsIDConverter() self.__compounds_revisor = CompoundsRevisor(self.model, self.__universal_model) biocyc.set_organism("meta") self.mapper = ModelMapper(self.model, self.__compoundsAnnotationConfigs, self.__compoundsIdConverter) self.__compounds_revisor.set_model_mapper(self.mapper) self.granulator = Granulator(self.model, self.mapper, self.__database_format, self.__compoundsIdConverter, self.__compoundsAnnotationConfigs) def __add_hydrogen_to_virtual_model(self): """ This method set searches for the hydrogen in each compartment of the model. The hydrogens are used to balance reactions. """ compartments = self.__model.compartments metabolites_in_model = self.__model.metabolites res = [] i = 0 while i < len(metabolites_in_model): metabolite = metabolites_in_model[i] if metabolite.formula == "H" and metabolite.compartment in compartments: res.append(metabolite) i += 1 self.__virtual_model.add_metabolites(res) def swap_and_gap_fill(self, target_ontology_id): pass def generalize_model(self, target_ontology_id): pass def gap_fill_model_by_target(self, target_ontology_id: int, components_ont_ids: list): pass def write_reports(self, file_path): metabolites_report_material = self.granulator.metabolite_report_material reactions_report_material = self.granulator.reaction_report_material with open(file_path, "w") as f: f.write("--Metabolites--\n") f.write("metabolite in model,replacer metabolite\n") for metabolite in metabolites_report_material: f.write(metabolite + ",") f.write(metabolites_report_material[metabolite] + "\n") f.write("--Reactions--\n") f.write("reaction in model,replacer reaction\n") for reaction in reactions_report_material: f.write(reaction + ",") f.write(reactions_report_material[reaction] + "\n") def swap_from_generic(self, targets: list, components: list, same_components=False, progress_bar_processes_left=1): """ Swap compounds from a generic target and components. The algorithm acts as follows: 1st: Starts for identifying the reactions present in the requested biosynthetic pathway; 2nd: Creates a virtual model; 3rd: Calls the granulator to granulate the biosynthetic pathway; :param list<str> targets: list of lipid targets :param list<str> components: list of components :param bool same_components: boolean for same or mix of components :param int progress_bar_processes_left: :return: """ targets_generic_ontology_id, components_ont_ids = \ self.transform_targets_and_components_into_boimmg_ids(targets,components) self.__virtual_model = Model("virtual_model") self.__add_hydrogen_to_virtual_model() self.__virtual_model_mapper = ModelMapper( self.__virtual_model, self.__compoundsAnnotationConfigs, self.__compoundsIdConverter) self.__virtual_compounds_revisor = CompoundsRevisor( self.__virtual_model, self.__universal_model, self.__compoundsAnnotationConfigs) self.__virtual_compounds_revisor.set_model_mapper( self.__virtual_model_mapper) self.granulator.set_virtual_model(self.__virtual_model, self.__virtual_model_mapper, self.__virtual_compounds_revisor) for target_generic_ontology_id in targets_generic_ontology_id: biosynthesis_reactions = self.granulator.identify_biosynthesis_pathway( target_generic_ontology_id) self.__biosynthesis_reactions = deepcopy(biosynthesis_reactions) self.__add_new_reactions_to_virtual_model( self.__biosynthesis_reactions) self.__model.remove_reactions(biosynthesis_reactions) self.granulator.granulate(target_generic_ontology_id, components_ont_ids, same_components, progress_bar_processes_left) self.generateISAreactions() def __subtract_reactions_in_list(self, reactions, reactions_to_subtract): res = [] for reaction in reactions: if reaction.id not in reactions_to_subtract: res.append(reaction) return res # def solve_components_reactions(self,same_components=False): # # self.__virtual_model = Model("virtual_model") # self.__universal_model = Model("universal_model") # # self.__virtual_model_mapper = ModelMapper(self.__virtual_model, self.__compoundsAnnotationConfigs, # self.__compoundsIdConverter) # # self.__virtual_compounds_revisor = CompoundsRevisor(self.__virtual_model, self.__universal_model, # self.__compoundsAnnotationConfigs) # # self.__virtual_compounds_revisor.set_model_mapper(self.__virtual_model_mapper) # # granulator = Granulator(self.model, self.mapper, self.__database_format, self.__modelseedCompoundsDb, # self.__compoundsIdConverter, self.__compoundsAnnotationConfigs) # # granulator.set_virtual_model(self.__virtual_model, self.__virtual_model_mapper, # self.__virtual_compounds_revisor) # # granulator.solve_components_reactions(same_components) def __add_new_reactions_to_virtual_model(self, new_reactions): self.__virtual_model_mapper.add_new_reactions_to_model(new_reactions) self.__virtual_model.add_reactions(new_reactions) def __add_new_reactions_to_model(self, new_reactions): self.mapper.add_new_reactions_to_model(new_reactions) self.model.add_reactions(new_reactions) def generateISAreactions(self): parents_and_children = self.get_parent_and_children_in_model() objective_reactants = [ reactant.id for reactant in self.objective.reactants ] reactions = [] for parent in parents_and_children: if parent in objective_reactants: for child in parents_and_children[parent]: name = "ISA_reaction_" + child id = "ISA_reaction_" + child newISAreaction = Reaction(id=id, name=name) child_cobra_container = self.model.metabolites.get_by_id( child) parent_cobra_container = self.model.metabolites.get_by_id( parent) stoichiometry = { child_cobra_container: -1, parent_cobra_container: 1 } newISAreaction.add_metabolites(stoichiometry) reactions.append(newISAreaction) self.model.add_reactions(reactions) def get_parent_and_children_in_model(self): res = {} for model_compound_id in self.mapper.boimmg_db_model_map.keys(): boimmg_id = self.mapper.boimmg_db_model_map[model_compound_id] node = self.__compounds_ontology.get_node_by_ont_id(boimmg_id) if not node.generic: parents = self.__compounds_ontology.get_successors_by_ont_id_rel_type( boimmg_id, "is_a") if parents: parent = parents[0] if parent in self.mapper.boimmg_db_model_map_reverse.keys( ): parents_in_model = self.mapper.boimmg_db_model_map_reverse[ parent] if len(parents_in_model) == 1: parent_in_model = parents_in_model[0] if parent_in_model in res: res[parent_in_model].append(model_compound_id) else: res[parent_in_model] = [model_compound_id] return res def transform_targets_and_components_into_boimmg_ids( self, targets, components): """ Conversion of components and lipid targets into BOIMMG's format :param targets: :param components: :return: """ targets_res = [] components_res = [] accessor = CompoundsDBAccessor() boimmg_prefix = self.__compoundsAnnotationConfigs[ "BOIMMG_ID_CONSTRUCTION"] for target in targets: new_target = self._transform_database_ids_into_boimmg_ids( target, accessor, boimmg_prefix) if not new_target: exit(2) targets_res.append(new_target) for component in components: new_component = self._transform_database_ids_into_boimmg_ids( component, accessor, boimmg_prefix) if not new_component: exit(2) components_res.append(new_component) return targets_res, components_res def _transform_database_ids_into_boimmg_ids(self, target: str, accessor: CompoundsDBAccessor, boimmg_prefix: str): """ Convert target lipid identifier into BOIMMG's format :param str target: :param CompoundsDBAccessor accessor: :param str 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
def test_precursors(self): compounds_ontology = CompoundsDBAccessor() all_precursors = compounds_ontology.get_all_predecessors_by_ont_id_rel_type( 322790, "precursor_of") print(all_precursors)
class MetaboliteSwapper: def __init__(self, model, metabolite_in_model, new_metabolite, type, modelSeedCompoundsDb, model_database="ModelSEED", compoundsIdConverter=None, universal_model=None, not_to_change_compounds=[]): """ Class constructor :param Model model: COBRApy model :param int metabolite_in_model: ontology id of the metabolite to be replaced :param int new_metabolite: ontology id of the metabolite that will replace :param int type: type of change (0, 1, 2 or 3) :param ModelSeedDB modelSeedCompoundsDb: Model SEED compounds database :param string model_database: database format of metabolites and reactions :param (optional) CompoundsIDConverter compoundsIdConverter: compound id converter :param (optional) Model universal_model: an universal model :param (optional) list not_to_change_compounds: list with compound that are not supposed to be changed """ if not universal_model: self.__universal_model = universal_model else: self.__universal_model = Model("universal_reactions") if not compoundsIdConverter: self.__compoundsIdConverter = CompoundsIDConverter() else: self.__compoundsIdConverter = compoundsIdConverter self.__model_database = model_database self.__compounds_db = modelSeedCompoundsDb self.__type = type self.__metabolite_in_model = metabolite_in_model self.__new_metabolite = new_metabolite self.__model = model self.__metabolites_not_to_change = not_to_change_compounds self.define_instance_variables() @property def model(self): return self.__model @model.setter def model(self, value): self.__model = value @property def mapper(self): return self.__mapper @mapper.setter def mapper(self, value): self.__mapper = value @property def changed_reactions(self): return self._changed_reactions @changed_reactions.setter def changed_reactions(self, value): self._changed_reactions = value def define_instance_variables(self): """ Define instance variables :return: """ self.__compoundsAnnotationConfigs = file_utilities.read_conf_file( COMPOUNDS_ANNOTATION_CONFIGS_PATH) self.__reactionsAnnotationConfigs = file_utilities.read_conf_file( REACTIONS_ANNOTATION_CONFIGS_PATH) self.__compounds_ontology = CompoundsDBAccessor() self.__home_path__ = ROOT_DIR self.__configs = file_utilities.read_conf_file(TOOL_CONFIG_PATH) self.changed_reactions = [] self.__reactionsChanger = ReactionsChanger( self.model, self.__type, self.__model_database, self.__universal_model, compounds_converter=self.__compoundsIdConverter) def set_type(self, new_type): """ Method to change the type of swap. :param int new_type: new type of swap :return: """ self.__type = new_type self.__reactionsChanger.set_type(new_type) def set_new_compound(self, new_compound): """ Method to set the new compound that will replace the other in the model. :param int new_compound: ontology identifier of the new compound. :return: """ self.__new_metabolite = new_compound def set_compound_in_model(self, compound_in_model): """ Method to set the compound to be replaced. :param int compound_in_model: ontology identifier of the compound in the model. :return: """ self.__metabolite_in_model = compound_in_model def get_universal_model(self): """ Get the instance variable __universal_model. :return: Model __universal_model: return the universal model. """ return self.__universal_model def swap_metabolites(self) -> list: """ Algorithm to swap metabolites: 1º Set the game changer: dictionary with the metabolites' intermediates, conjugated acid or/and base. - {Metabolite in model : metabolite replacer} 2º Swap all the metabolite's intermediates, conjugated acid or/and base and the metabolite itself. 3º Swap the reactions associated to the replaced metabolite using the ReactionSwapper class. :return list : changed reactions """ compounds_with_reactions_to_change = [] game_changer = self.__get_game_changer() game_changer_in_model = {} for compound in game_changer.keys(): compound_container = self.__compounds_ontology.get_node_by_ont_id( compound) in_model_compound_inchikey = compound_container.inchikey modelseed_id = compound_container.model_seed_id in_model_aliases = {} if modelseed_id: in_model_aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID( modelseed_id) metabolitesInModel = self.mapper.check_metabolites_in_model( in_model_compound_inchikey, in_model_aliases, boimmg_container=compound_container) if metabolitesInModel: for metabolite in metabolitesInModel: game_changer_in_model[metabolite] = game_changer[compound] for metabolite in game_changer_in_model.keys(): inModel = game_changer_in_model[metabolite][0] if not inModel: new_compound_ontology_id = game_changer_in_model[metabolite][1] if self.__model_database == "ModelSEED": self.__swap_modelseed_compound(metabolite, new_compound_ontology_id) elif self.__model_database == "BiGG": self.__swap_bigg_metabolite(metabolite, new_compound_ontology_id) elif self.__model_database == "KEGG": self.__swap_kegg_metabolite(metabolite, new_compound_ontology_id) compounds_with_reactions_to_change.append(metabolite) else: mets = game_changer_in_model[metabolite][1] for met in mets: if metabolite.compartment == met.compartment: self.change_reaction_by_swapping_existing_metabolites( metabolite, met) compounds_with_reactions_to_change.append(met) changed_reactions = self.__reactionsChanger.swap_reactions_by_compounds( compounds_with_reactions_to_change) return changed_reactions def __swap_conjugates(self, model_metabolite=None, new_metabolite=None): """ Method to swap the conjugated base and acid of the compounds being swapped. If the model_metabolite and the new_metabolite are provided, the method will replace directly the model_metabolite for the new_metabolite. :param (optional) Metabolite model_metabolite: metabolite in the model to be replaced :param (optional) Metabolite new_metabolite: metabolite to replace. :return: """ conjugates_game_changer = self.__get_game_changer_conjugates() if not new_metabolite and not model_metabolite: compounds_with_reactions_to_change = [] game_changer_in_model = {} for compound in conjugates_game_changer.keys(): compound_container = self.__compounds_ontology.get_node_by_ont_id( compound) in_model_compound_inchikey = compound_container.inchikey in_model_aliases = compound_container.aliases metabolitesInModel = self.mapper.check_metabolites_in_model( in_model_compound_inchikey, in_model_aliases) if metabolitesInModel: for metabolite_to_be_changed in metabolitesInModel: game_changer_in_model[ metabolite_to_be_changed] = conjugates_game_changer[ compound] for metabolite_to_be_changed in game_changer_in_model.keys(): inModel = game_changer_in_model[metabolite_to_be_changed][0] if not inModel: new_compound_ontology_id = game_changer_in_model[ metabolite_to_be_changed][1] if self.__model_database == "ModelSEED": self.__swap_modelseed_compound( metabolite_to_be_changed, new_compound_ontology_id) elif self.__model_database == "BiGG": self.__swap_bigg_metabolite(metabolite_to_be_changed, new_compound_ontology_id) elif self.__model_database == "KEGG": self.__swap_kegg_metabolite(metabolite_to_be_changed, new_compound_ontology_id) compounds_with_reactions_to_change.append( metabolite_to_be_changed) self.__reactionsChanger.swap_reactions_by_compounds( compounds_with_reactions_to_change) else: reactions_to_change = [] for compound in conjugates_game_changer.keys(): conjugates = conjugates_game_changer[compound][1] for conjugate in conjugates: if conjugate.compartment == new_metabolite.compartment: compound_container = self.__compounds_ontology.get_node_by_ont_id( compound) in_model_compound_inchikey = compound_container.inchikey in_model_aliases = compound_container.aliases metabolitesInModel = self.mapper.check_metabolites_in_model( in_model_compound_inchikey, in_model_aliases, compound_container) for metabolite_to_be_changed in metabolitesInModel: if metabolite_to_be_changed.compartment == new_metabolite.compartment: reactions_to_change = self.change_reaction_by_swapping_existing_metabolites( metabolite_to_be_changed, conjugate) else: db_type = self.__compoundsAnnotationConfigs.get( self.__model_database) db_id = conjugate.annotation.get(db_type) if type(db_id) == str: modelseed_id = self.__compoundsIdConverter.convert_db_id_to_model_seed_by_db_id( db_id) else: modelseed_id = self.__compoundsIdConverter.convert_db_id_to_model_seed_by_db_id( db_id[0]) cont = self.__compounds_db.get_compound_by_id( modelseed_id[0]) new_compound = self.generate_new_metabolites(cont) compound_ont_container = self.__compounds_ontology.get_node_by_ont_id( compound) compound_to_be_changed = \ self.mapper.check_metabolites_in_model(compound_ont_container.inchikey, compound_ont_container.aliases, compound_ont_container) if compound_to_be_changed: reactions_to_change = self.change_reaction_by_swapping_existing_metabolites( compound_to_be_changed[0], new_compound[0]) if reactions_to_change: self.__reactionsChanger.swap_reactions(reactions_to_change) def swap_only_metabolites_and_conjugates(self, model_metabolite=None, new_metabolite=None): """ Method to swap only the metabolites and their conjugated acid and/or base. This method does not change the metabolite intermediates/precursors. :param (optional) Model.Metabolite model_metabolite: metabolite in the model to be replaced :param (optional) Model.Metabolite new_metabolite: metabolite to replace. :return: """ compounds_with_reactions_to_change = [] if not model_metabolite: self.__swap_conjugates() ontology_container = self.__compounds_ontology.get_node_by_ont_id( self.__metabolite_in_model) inchikey = ontology_container.inchikey aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID( ontology_container.model_seed_id) model_metabolites = self.mapper.check_metabolites_in_model( inchikey, aliases) replacer_metabolites_in_model = \ self.__check_if_compound_exists_in_model_by_ontology_id(self.__new_metabolite) if not replacer_metabolites_in_model: if self.__model_database == "ModelSEED": for model_metabolite in model_metabolites: self.__swap_modelseed_compound(model_metabolite, self.__new_metabolite) elif self.__model_database == "BiGG": for model_metabolite in model_metabolites: self.__swap_bigg_metabolite(model_metabolite, self.__new_metabolite) elif self.__model_database == "KEGG": for model_metabolite in model_metabolites: self.__swap_kegg_metabolite(model_metabolite, self.__new_metabolite) compounds_with_reactions_to_change.append(model_metabolite) self.__reactionsChanger.swap_reactions_by_compounds( compounds_with_reactions_to_change) else: for model_metabolite in model_metabolites: for replacer_metabolite in replacer_metabolites_in_model: if model_metabolite.compartment == replacer_metabolite.compartment: reactions_to_change = self.change_reaction_by_swapping_existing_metabolites( model_metabolite, replacer_metabolite) self.__reactionsChanger.swap_reactions( reactions_to_change) elif new_metabolite: self.__swap_conjugates(model_metabolite, new_metabolite) reactions_to_change = self.change_reaction_by_swapping_existing_metabolites( model_metabolite, new_metabolite) changed_reactions = self.__reactionsChanger.swap_reactions( reactions_to_change) self.changed_reactions.extend(changed_reactions) def change_reaction_by_swapping_existing_metabolites( self, model_metabolite, new_metabolite): """ Method to change a given metabolite and the respective reactions. :param Model.Metabolite model_metabolite: metabolite in the model to be replaced :param Model.Metabolite new_metabolite: metabolite to replace. :return: list<Reaction> reactions_to_change: list with the reactions to be changed (format, id, annotation, etc...) """ reactions_to_change = [] if model_metabolite.id != new_metabolite.id: reactions = model_metabolite.reactions for reaction in reactions: met_to_add = {} met_to_subtract = {} stoichiometry = reaction.metabolites coef = stoichiometry.get(model_metabolite) met_to_add[new_metabolite] = coef met_to_subtract[model_metabolite] = coef reaction.subtract_metabolites(met_to_subtract) reaction.add_metabolites(met_to_add) reactions_to_change.append(reaction) return reactions_to_change def __swap_bigg_metabolite(self, model_metabolite, new_compound_ontology_id): """ Method to swap a metabolite in the BiGG database format. This method tries to find the BiGG format of the new compound. If it does not find, it will change into the Model SEED format. :param Model.Metabolite model_metabolite: metabolite to be replaced. :param int new_compound_ontology_id: ontology identifier of the metabolite that will replace the other :return: """ model_metabolite.annotation = {} compound_container = self.__compounds_ontology.get_node_by_ont_id( new_compound_ontology_id) model_seed_id = compound_container.model_seed_id if model_seed_id: bigg_ids = None aliases = self.__compoundsIdConverter.get_modelSeedIdToDb().get( model_seed_id) if "BiGG" in aliases: bigg_ids = self.__compoundsIdConverter.convert_modelSeedId_into_other_dbID( model_seed_id, "BiGG") elif "BiGG1" in aliases: bigg_ids = self.__compoundsIdConverter.convert_modelSeedId_into_other_dbID( model_seed_id, "BiGG1") if bigg_ids: bigg_metabolite = None bigg_id = None found = False i = 0 while not found and i < len(bigg_ids): try: bigg_id = bigg_ids[i] bigg_metabolite = bigg.get_bigg_metabolite(bigg_id) found = True except: i += 1 if bigg_metabolite: old_inchikey = "" if "inchi_key" in model_metabolite.annotation.keys(): old_inchikey = model_metabolite.annotation["inchi_key"] old_aliases = AnnotationUtils.get_annotation_from_cobra_annotation( model_metabolite) old_id = model_metabolite.id new_aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID( compound_container.model_seed_id) annotation = AnnotationUtils.get_compound_annotation_format_by_aliases( new_aliases) model_metabolite.annotation = annotation new_inchikey = "" if not compound_container.generic: new_inchikey = compound_container.inchikey model_metabolite.annotation[ "inchi_key"] = compound_container.inchikey model_metabolite.annotation[ "smiles"] = compound_container.smiles model_metabolite.formula = bigg_metabolite.get( "formulae")[0] charges = bigg_metabolite.get("charges") if charges: model_metabolite.charge = charges[0] compartment = model_metabolite.compartment if compartment is None: model_metabolite.compartment = "c" model_metabolite.name = bigg_metabolite.get("name") self.__check_if_id_is_used_in_model_and_delete_it( bigg_id + "_" + model_metabolite.compartment) model_metabolite.id = bigg_id + "_" + model_metabolite.compartment self.mapper.update_maps(old_inchikey, new_inchikey, old_id, model_metabolite.id, new_compound_ontology_id, old_aliases, new_aliases) else: self.__change_boimmg_format_metabolite( model_metabolite, compound_container) else: self.__change_boimmg_format_metabolite(model_metabolite, compound_container) else: self.__change_boimmg_format_metabolite(model_metabolite, compound_container) def __swap_kegg_metabolite(self, model_metabolite, new_compound_ontology_id): """ Method to swap a metabolite in the KEGG database format. This method tries to find the KEGG format of the new compound. If it does not find, it will change into the Model SEED format. :param Model.Metabolite model_metabolite: metabolite to be replaced. :param int new_compound_ontology_id: ontology identifier of the metabolite that will replace the other :return: """ old_inchikey = "" if "inchi_key" in model_metabolite.annotation.keys(): old_inchikey = model_metabolite.annotation["inchi_key"] old_aliases = AnnotationUtils.get_annotation_from_cobra_annotation( model_metabolite) old_id = model_metabolite.id model_metabolite.annotation = {} compound_container = self.__compounds_ontology.get_node_by_ont_id( new_compound_ontology_id) model_seed_id = compound_container.model_seed_id new_aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID( model_seed_id) if model_seed_id in self.__compoundsIdConverter.get_modelSeedIdToDb( ).keys(): if "KEGG" in self.__compoundsIdConverter.get_modelSeedIdToDb().get( model_seed_id): kegg_id = self.__compoundsIdConverter.convert_modelSeedId_into_other_dbID( model_seed_id, "KEGG")[0] kegg_metabolite = KeggCompound(kegg_id) annotation = AnnotationUtils.get_compound_annotation_format_by_aliases( new_aliases) model_metabolite.annotation = annotation new_inchikey = "" if not compound_container.generic: model_metabolite.annotation[ "inchi_key"] = compound_container.inchikey new_inchikey = compound_container.inchikey model_metabolite.annotation[ "smiles"] = compound_container.smiles model_metabolite.formula = kegg_metabolite.get_formula() model_metabolite.name = kegg_metabolite.get_name() model_metabolite.charge = 0 compartment = model_metabolite.compartment self.__check_if_id_is_used_in_model_and_delete_it(kegg_id + "_" + compartment) model_metabolite.id = kegg_id + "_" + compartment self.mapper.update_maps(old_inchikey, new_inchikey, old_id, model_metabolite.id, compound_container.id, old_aliases, new_aliases) else: self.__change_boimmg_format_metabolite(model_metabolite, compound_container) else: self.__change_boimmg_format_metabolite(model_metabolite, compound_container) def __change_boimmg_format_metabolite(self, model_metabolite: Metabolite, compound_container): """ This method changes the id of the metabolite arbitrarily. The format of the metabolite is set for the ontology format. It is worth noting that the :param compound_container can be either a ModelSeedCompound or an OntologyCompound :param Model.Metabolite model_metabolite: metabolite to be replaced. :param CompoundContainer compound_container: compound that will replace the other. :return: """ old_inchikey = "" if "inchi_key" in model_metabolite.annotation.keys(): old_inchikey = model_metabolite.annotation["inchi_key"] old_aliases = AnnotationUtils.get_annotation_from_cobra_annotation( model_metabolite) old_id = model_metabolite.id aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID( compound_container.model_seed_id) annotation = {} if aliases: annotation = AnnotationUtils.get_compound_annotation_format_by_aliases( aliases) annotation["boimmg.compound"] = self.__compoundsAnnotationConfigs["BOIMMG_ID_CONSTRUCTION"]+\ str(compound_container.id) new_aliases = {"BOIMMG": [annotation["boimmg.compound"]]} model_metabolite.annotation = annotation new_inchikey = "" if not compound_container.generic: model_metabolite.annotation[ "inchi_key"] = compound_container.inchikey new_inchikey = compound_container.inchikey model_metabolite.annotation["smiles"] = compound_container.smiles model_metabolite.formula = compound_container.formula model_metabolite.charge = compound_container.charge model_metabolite.name = compound_container.name compartment = model_metabolite.compartment id = self.__compoundsAnnotationConfigs["BOIMMG_ID_CONSTRUCTION"] + str( compound_container.id) new_metabolite_id = id + "_" + compartment self.__check_if_id_is_used_in_model_and_delete_it(new_metabolite_id) model_metabolite.id = new_metabolite_id self.mapper.update_maps(old_inchikey, new_inchikey, old_id, model_metabolite.id, compound_container.id, old_aliases, new_aliases) def __swap_modelseed_compound(self, model_metabolite: Metabolite, new_compound_ontology_id: int): """ Method to swap a metabolite in the Model SEED database format. This method tries to find the Model SEED format of the new compound. If it does not find, it will change into an arbitrary id with the Model SEED or the Ontology format. :param Model.Metabolite model_metabolite: metabolite to be replaced. :param int new_compound_ontology_id: ontology identifier of the metabolite that will replace the other :return: """ old_inchikey = "" if "inchi_key" in model_metabolite.annotation.keys(): old_inchikey = model_metabolite.annotation["inchi_key"] old_aliases = AnnotationUtils.get_annotation_from_cobra_annotation( model_metabolite) old_id = model_metabolite.id model_metabolite.annotation = {} compound_container = self.__compounds_ontology.get_node_by_ont_id( new_compound_ontology_id) new_aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID( compound_container.model_seed_id) annotation = AnnotationUtils.get_compound_annotation_format_by_aliases( new_aliases) model_metabolite.annotation = annotation new_inchikey = "" if not compound_container.generic: model_metabolite.annotation[ "inchi_key"] = compound_container.inchikey new_inchikey = compound_container.inchikey model_metabolite.annotation["smiles"] = compound_container.smiles model_metabolite.formula = compound_container.formula model_metabolite.charge = compound_container.charge compartment = model_metabolite.compartment db_id = compound_container.model_seed_id model_metabolite.name = compound_container.name if db_id: self.__check_if_id_is_used_in_model_and_delete_it( compound_container.model_seed_id + "_" + compartment) model_metabolite.id = compound_container.model_seed_id + "_" + compartment self.mapper.update_maps(old_inchikey, new_inchikey, old_id, model_metabolite.id, new_compound_ontology_id, old_aliases, new_aliases) else: self.__change_boimmg_format_metabolite(model_metabolite, compound_container) def __check_if_id_is_used_in_model_and_delete_it(self, id: int): """ This method checks whether a compound ID is used in the model and if so, it is removed :param id: compound identifier :return: """ inModel = self.model.metabolites.has_id(id) if inModel: metabolite = self.model.metabolites.get_by_id(id) self.model.remove_metabolites([metabolite]) def __get_game_changer_conjugates(self): """ This method searches for the conjugates of a given compound in model and assigns their conjugated acid or base; :return dict {ontology id : (metabolite already in model ? (boolean), COBRApy metabolite or ontology id)} """ conjugated_acid_in_model = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( self.__metabolite_in_model, "conjugated_acid_of") conjugated_base_in_model = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( self.__metabolite_in_model, "conjugated_base_of") game_changer = {} if conjugated_base_in_model: conjugated_base_to_change = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( self.__new_metabolite, "conjugated_base_of") game_changer.update( self.__add_conjugate_to_game_changer( "base", conjugated_base_in_model, conjugated_base_to_change)) if conjugated_acid_in_model: conjugated_acid_to_change = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( self.__new_metabolite, "conjugated_acid_of") game_changer.update( self.__add_conjugate_to_game_changer( "acid", conjugated_acid_in_model, conjugated_acid_to_change)) return game_changer def __get_game_changer(self): """ This method set the game changer. The game changer will be a dictionary with all of the necessary information to swap the compounds. The game changer will have a given compound intermediates, conjugated acid or/and base and the respective metabolites to replace them. :return dict: {ontology id : (metabolite already in model ? (boolean), COBRApy metabolite or ontology id)} """ intermediates_in_model = self.__compounds_ontology.get_all_predecessors_by_ont_id_rel_type( self.__metabolite_in_model, "precursor_of") conjugated_acid_in_model = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( self.__metabolite_in_model, "conjugated_acid_of") conjugated_base_in_model = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( self.__metabolite_in_model, "conjugated_base_of") intermediates_to_change = self.__compounds_ontology.get_all_predecessors_by_ont_id_rel_type( self.__new_metabolite, "precursor_of") # values -----> (met in model?, if true: cobraMetabolite else: ontId) game_changer = self.__add_to_game_changer(self.__metabolite_in_model, self.__new_metabolite) game_changer.update( self.__get_intermediates_game_changer(intermediates_in_model, intermediates_to_change)) if conjugated_acid_in_model: conjugated_acid_to_change = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( self.__new_metabolite, "conjugated_acid_of") game_changer.update( self.__add_conjugate_to_game_changer( "acid", conjugated_acid_in_model, conjugated_acid_to_change)) intermediates_in_model = self.__compounds_ontology.get_all_predecessors_by_ont_id_rel_type( conjugated_acid_in_model[0], "precursor_of") intermediates_to_change = self.__compounds_ontology.get_all_predecessors_by_ont_id_rel_type( conjugated_acid_to_change[0], "precursor_of") game_changer.update( self.__get_intermediates_game_changer(intermediates_in_model, intermediates_to_change)) if conjugated_base_in_model: conjugated_base_to_change = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( self.__new_metabolite, "conjugated_base_of") game_changer.update( self.__add_conjugate_to_game_changer( "base", conjugated_base_in_model, conjugated_base_to_change)) intermediates_in_model = self.__compounds_ontology.get_all_predecessors_by_ont_id_rel_type( conjugated_base_in_model[0], "precursor_of") intermediates_to_change = self.__compounds_ontology.get_all_predecessors_by_ont_id_rel_type( conjugated_base_to_change[0], "precursor_of") game_changer.update( self.__get_intermediates_game_changer(intermediates_in_model, intermediates_to_change)) return game_changer def __add_conjugate_to_game_changer(self, type: str, conjugated_in_model: list, new_conjugated: list) -> dict: """ This method add a conjugated acid or base to the game changer :param string type: "acid" or "base" :param list conjugated_in_model: ontology id of the conjugate to be replaced :param list new_conjugated: ontology id of the conjugate that will replace :return dict: {ontology id : (metabolite already in model ? (boolean), COBRApy metabolite or ontology id)} """ game_changer = {} if type == "base": metabolite_added = self.__add_to_game_changer( conjugated_in_model[0], new_conjugated[0]) game_changer.update(metabolite_added) elif type == "acid": metabolite_added = self.__add_to_game_changer( conjugated_in_model[0], new_conjugated[0]) game_changer.update(metabolite_added) return game_changer def __add_to_game_changer(self, met_in_model, new_met): """ This method add metabolites to the game changer :param int met_in_model: ontology id of the metabolite to be replaced :param int new_met: ontology id of the metabolite to be replaced :return dict: {ontology id : (metabolite already in model ? (boolean), COBRApy metabolite or ontology id)} """ game_changer = {} metabolite_container = self.__compounds_ontology.get_node_by_ont_id( new_met) inchikey = metabolite_container.inchikey aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID( metabolite_container.model_seed_id) metabolites_check_in_model = self.mapper.check_metabolites_in_model( inchikey, aliases) if met_in_model not in self.__metabolites_not_to_change: if metabolites_check_in_model: game_changer[met_in_model] = (True, []) for metabolite in metabolites_check_in_model: game_changer[met_in_model][1].append( metabolite ) # (met in model?, if true: [cobraMetabolite] else: ontId) else: game_changer[met_in_model] = (False, new_met) return game_changer else: if not metabolites_check_in_model: if metabolite_container.model_seed_id: ms_container = self.__compounds_db.get_compound_by_id( metabolite_container.model_seed_id) metabolites = self.generate_new_metabolites(ms_container) else: metabolites = self.generate_new_boimmg_metabolites( metabolite_container) self.model.add_metabolites(metabolites) return game_changer def _check_if_compound_is_generic(self, compound_id): """ This method check if some compound is generic or not :param int compound_id: ontology id of the metabolite :return boolean: is generic or not """ compound_container = self.__compounds_ontology.get_node_by_ont_id( compound_id) return compound_container.generic def __get_intermediates_game_changer(self, intermediates_in_model, intermediates_to_change): """ This method finds the correspondent substitute of each intermediate in the model :param list intermediates_in_model: list of ontology ids of the intermediates of the metabolite to be changed :param list intermediates_to_change: list of ontology ids of the intermediates of the metabolite that will replace :return dict: {ontology id : (metabolite already in model? (boolean), COBRApy metabolite or ontology id) } """ game_changer = {} if self.__type == 1: intermediates = self.__set_intermediates_in_game_changer_type1( intermediates_in_model, intermediates_to_change) game_changer.update(intermediates) elif self.__type == 2: intermediates = self.__set_intermediates_in_game_changer_type2( intermediates_in_model, intermediates_to_change) game_changer.update(intermediates) return game_changer def __set_intermediates_in_game_changer_type1(self, intermediates_in_model, intermediates_to_change): """ This method finds the correspondent substitute of each intermediate in the model for the type 1 game change :param list intermediates_in_model: list of ontology ids of the intermediates of the metabolite to be changed :param list intermediates_to_change: list of ontology ids of the intermediates of the metabolite that will replace :return dict: {ontology id : (metabolite already in model? (boolean), COBRApy metabolite or ontology id) } """ game_changer = {} for met in intermediates_in_model: parent_met_in_model = self.__compounds_ontology.get_successors_by_ont_id_rel_type( met, "is_a") i = 0 found = False while not found and i < len(intermediates_to_change): parent2 = self.__compounds_ontology.get_successors_by_ont_id_rel_type( intermediates_to_change[i], "is_a") if parent_met_in_model[0] == parent2[0]: found = True metabolite_added = self.__add_to_game_changer( met, intermediates_to_change[i]) game_changer.update(metabolite_added) i += 1 return game_changer def __set_intermediates_in_game_changer_type2(self, intermediates_in_model, intermediates_to_change): """ This method finds the correspondent substitute of each intermediate in the model for the type 2 game change :param list intermediates_in_model: list of ontology ids of the intermediates of the metabolite to be changed :param list intermediates_to_change: list of ontology ids of the intermediates of the metabolite that will replace :return dict: {ontology id : (metabolite already in model? (boolean), COBRApy metabolite or ontology id) } """ game_changer = {} isGenericInModel = self._check_if_compound_is_generic( intermediates_in_model[0]) self.__reactionsChanger.set_type2_is_generic_in_model(isGenericInModel) if isGenericInModel: for met in intermediates_in_model: i = 0 found = False while not found and i < len(intermediates_to_change): parent_met_to_change = self.__compounds_ontology.get_successors_by_ont_id_rel_type( intermediates_to_change[i], "is_a") if met in parent_met_to_change: game_changer.update( self.__add_to_game_changer( met, intermediates_to_change[i])) found = True i += 1 else: for met in intermediates_in_model: i = 0 found = False while not found and i < len(intermediates_to_change): children = self.__compounds_ontology.get_predecessors_by_ont_id_rel_type( intermediates_to_change[i], "is_a") if met in children: game_changer.update( self.__add_to_game_changer( met, intermediates_to_change[i])) found = True i += 1 return game_changer def __get_metabolite_container_by_id(self, id): """ This method searches for a given metabolite in the Model :param string id: id in the Model :return Model.metabolite: if the metabolite is found returns the metabolite, otherwise returns None """ for met in self.model.metabolites: if met.id == id: return met return None def change_reaction_format(self, reaction): """ This method changes a given reaction format. :param Model.Reaction reaction: reaction to be changed :return: """ self.__reactionsChanger.swap_reactions([reaction]) def __check_if_compound_exists_in_model_by_ontology_id(self, ontology_id): """ Method to check whether a compound exists in the model using BOIMMG ID :param int ontology_id: boimmg id :return list<Compound>: list of compounds in model with this ID (list of the same compound in different compartments) """ container = self.__compounds_ontology.get_node_by_ont_id(ontology_id) inchikey = container.inchikey aliases = {} if container.model_seed_id: aliases = self.__compoundsIdConverter.get_all_aliases_by_modelSeedID( container.model_seed_id) aliases.update(container.aliases) return self.mapper.check_metabolites_in_model(inchikey, aliases, container) def generate_new_metabolites(self, compound_container: ModelSeedCompound): """ This method will generate a new set of compounds (same metabolite in different compartments) :param ModelSeedCompound compound_container: internal wrappers of the ModelSEED compounds :return list<Metabolite>: list of newly generated compounds """ model_metabolites = \ model_utilities.generate_model_compounds_by_database_format(self.model, compound_container.getDbId(), self.__compoundsIdConverter, self.__compounds_db, self.__model_database) self.model.add_metabolites(model_metabolites) self.mapper.add_new_metabolites_to_maps(model_metabolites) return model_metabolites def generate_new_boimmg_metabolites(self, metabolite_container: CompoundNode): """ This method will generate a new set of compounds (same metabolite in different compartments) :param CompoundNode metabolite_container: wrapper of BOIMMG compound :return list<Metabolite>: list of newly generated compounds """ metabolites = model_utilities.generate_boimmg_metabolites( self.model, metabolite_container, self.__model_database, self.__compoundsIdConverter, self.__compoundsAnnotationConfigs) self.model.add_metabolites(metabolites) self.mapper.add_new_metabolites_to_maps(metabolites) return metabolites def setType2_isGenericInModel(self, isGeneric): self.__reactionsChanger.set_type2_is_generic_in_model(isGeneric) def set_model_mapper(self, mapper): self.mapper = mapper
class ModelMapper: def __init__(self, model, compoundsAnnotationConfigs, compoundsIdConverter): self.model = model self.__compoundsAnnotationConfigs = compoundsAnnotationConfigs self.__compoundsIdConverter = compoundsIdConverter self.__compounds_ontology = CompoundsDBAccessor() self.mapped = False self.boimmg_db_model_map = {} self.boimmg_db_model_map_reverse = {} self.compounds_aliases_indexation = {} self.compound_inchikey_indexation = {} self.__compounds_aliases_indexation_reverse = {} @property def model(self): return self.__model @model.setter def model(self, value): self.__model = value @property def boimmg_db_model_map(self): return self.__boimmg_db_model_map @boimmg_db_model_map.setter def boimmg_db_model_map(self, value): if isinstance(value, dict): self.__boimmg_db_model_map = value else: raise ValueError("introduce a dictionary") @property def boimmg_db_model_map_reverse(self): return self.__boimmg_db_model_map_reverse @boimmg_db_model_map_reverse.setter def boimmg_db_model_map_reverse(self, value): if isinstance(value, dict): self.__boimmg_db_model_map_reverse = value else: raise ValueError("introduce a dictionary") @property def compounds_aliases_indexation(self): return self.__compounds_aliases_indexation @compounds_aliases_indexation.setter def compounds_aliases_indexation(self, value): if isinstance(value, dict): self.__compounds_aliases_indexation = value else: raise ValueError("introduce a dictionary") @property def compounds_aliases_indexation_reverse(self): return self.__compounds_aliases_indexation_reverse @compounds_aliases_indexation_reverse.setter def compounds_aliases_indexation_reverse(self, value): if isinstance(value, dict): self.__compounds_aliases_indexation_reverse = value else: raise ValueError("introduce a dictionary") @property def compound_inchikey_indexation(self): return self.__compound_inchikey_indexation @compound_inchikey_indexation.setter def compound_inchikey_indexation(self, value): if isinstance(value, dict): self.__compound_inchikey_indexation = value else: raise ValueError("introduce a dictionary") @property def mapped(self): return self._mapped @mapped.setter def mapped(self, value: bool): self._mapped = value def printProgressBar(self, iteration, total, prefix='', suffix='', decimals=1, length=100, fill='|', printEnd="\r"): """ Call in a loop to create terminal progress bar @params: iteration - Required : current iteration (Int) total - Required : total iterations (Int) prefix - Optional : prefix string (Str) suffix - Optional : suffix string (Str) decimals - Optional : positive number of decimals in percent complete (Int) length - Optional : character length of bar (Int) fill - Optional : bar fill character (Str) printEnd - Optional : end character (e.g. "\r", "\r\n") (Str) """ percent = ("{0:." + str(decimals) + "f}").format( 100 * (iteration / float(total))) filledLength = int(length * iteration // total) bar = fill * filledLength + '-' * (length - filledLength) print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end="", flush=True) # Print New Line on Complete if iteration == total: print() def map_model(self, database): if database in self.__compoundsAnnotationConfigs.keys(): database_annotation_key = self.__compoundsAnnotationConfigs[ database] else: raise ValueError("introduce a valid database name") j = 0 model_metabolites = list(self.model.metabolites) for compound in self.model.metabolites: self.printProgressBar(j, len(model_metabolites)) j += 1 compound_annotation = compound.annotation boimmg_compound_found = False annotation_keys = [ "seed.compound", database_annotation_key, "boimmg.compound", "inchi_key" ] for key in annotation_keys: if key in compound_annotation.keys(): if isinstance(compound_annotation[key], str): annotation_values = [compound_annotation[key]] else: annotation_values = compound_annotation[key] for annotation_value in annotation_values: if not boimmg_compound_found: if "cpd" in annotation_value: model_seed_id = [annotation_value] else: model_seed_id = self.__compoundsIdConverter.convert_db_id_to_model_seed_by_db_id( annotation_value) if model_seed_id: found = False i = 0 while not found and i < len(model_seed_id): node = self.__compounds_ontology.get_node_id_from_model_seed_id( model_seed_id[i]) i += 1 if node: found = True boimmg_compound_found = True self.boimmg_db_model_map[ compound.id] = node if node in self.boimmg_db_model_map_reverse.keys( ): self.boimmg_db_model_map_reverse[ node].append(compound.id) else: self.boimmg_db_model_map_reverse[ node] = [compound.id] if key not in self.compounds_aliases_indexation: self.compounds_aliases_indexation[key] = {} if annotation_value not in self.compounds_aliases_indexation[ key]: self.compounds_aliases_indexation[key][ annotation_value] = [] if compound.id not in self.compounds_aliases_indexation_reverse: self.compounds_aliases_indexation_reverse[ compound.id] = {} if key not in self.compounds_aliases_indexation_reverse[ compound.id]: self.compounds_aliases_indexation_reverse[ compound.id] = { key: [] } if annotation_value not in self.compounds_aliases_indexation_reverse[ compound.id][key]: self.compounds_aliases_indexation_reverse[ compound.id][key].append(annotation_value) if compound.id not in self.compounds_aliases_indexation_reverse[ compound.id][key]: self.compounds_aliases_indexation[key][ annotation_value].append(compound.id) if not boimmg_compound_found: if key == "boimmg.compound": construction_sub_string = self.__compoundsAnnotationConfigs[ "BOIMMG_ID_CONSTRUCTION"] value = compound_annotation[key] boimmg_id = int( value.replace(construction_sub_string, "")) if boimmg_id not in self.boimmg_db_model_map_reverse.keys( ): self.boimmg_db_model_map_reverse[ boimmg_id] = [] self.boimmg_db_model_map_reverse[boimmg_id].append( compound.id) if boimmg_id not in self.boimmg_db_model_map.keys( ): self.boimmg_db_model_map_reverse[ compound.id] = [] self.boimmg_db_model_map_reverse[ compound.id].append(compound.id) elif key == "inchi_key": value = compound_annotation[key][:-1] if value not in self.compound_inchikey_indexation: self.compound_inchikey_indexation[value] = [ compound.id ] else: self.compound_inchikey_indexation[ value].append(compound.id) self.mapped = True def create_map_dump(self, destination): out_file = open(destination + "boimmg_db_model_map.json", "w") json.dump(self.boimmg_db_model_map, out_file) out_file.close() out_file = open(destination + "boimmg_db_model_map_reverse.json", "w") json.dump(self.boimmg_db_model_map_reverse, out_file) out_file.close() out_file = open(destination + "compounds_aliases_indexation.json", "w") json.dump(self.compounds_aliases_indexation, out_file) out_file.close() out_file = open( destination + "compounds_aliases_indexation_reverse.json", "w") json.dump(self.compounds_aliases_indexation_reverse, out_file) out_file.close() out_file = open(destination + "compound_inchikey_indexation.json", "w") json.dump(self.compound_inchikey_indexation, out_file) out_file.close() def upload_maps(self, folder): in_file = open(folder + "boimmg_db_model_map.json", "r") self.boimmg_db_model_map = json.load(in_file) in_file.close() in_file = open(folder + "boimmg_db_model_map_reverse.json", "r") temp = json.load(in_file) in_file.close() self.boimmg_db_model_map_reverse = {int(k): v for k, v in temp.items()} in_file = open(folder + "compounds_aliases_indexation.json", "r") self.compounds_aliases_indexation = json.load(in_file) in_file.close() in_file = open(folder + "compounds_aliases_indexation_reverse.json", "r") self.compounds_aliases_indexation_reverse = json.load(in_file) in_file.close() in_file = open(folder + "compound_inchikey_indexation.json", "r") self.compound_inchikey_indexation = json.load(in_file) in_file.close() self.mapped = True def add_new_reactions_to_model(self, new_reactions): for reaction in new_reactions: self.add_new_metabolites_to_maps(reaction.metabolites) def __add_metabolites_to_boimmg_indexation(self, key, annotation_value, metabolite): if key == self.__compoundsAnnotationConfigs.get("ModelSEED"): model_seed_id = [annotation_value] else: model_seed_id = self.__compoundsIdConverter.convert_db_id_to_model_seed_by_db_id( annotation_value) if model_seed_id: found = False i = 0 while not found and i < len(model_seed_id): node = self.__compounds_ontology.get_node_id_from_model_seed_id( model_seed_id[i]) i += 1 if node: # found = True self.boimmg_db_model_map[metabolite.id] = node if node in self.boimmg_db_model_map_reverse.keys(): self.boimmg_db_model_map_reverse[node].append( metabolite.id) else: self.boimmg_db_model_map_reverse[node] = [ metabolite.id ] return True return False def __add_metabolites_to_aliases_indexation(self, annotation_pair, annotation_value, metabolite): if annotation_pair not in self.compounds_aliases_indexation: self.compounds_aliases_indexation[annotation_pair] = {} if annotation_value not in self.compounds_aliases_indexation[ annotation_pair]: self.compounds_aliases_indexation[annotation_pair][ annotation_value] = [] if metabolite.id not in self.compounds_aliases_indexation_reverse: self.compounds_aliases_indexation_reverse[metabolite.id] = {} if annotation_pair not in self.compounds_aliases_indexation_reverse[ metabolite.id]: self.compounds_aliases_indexation_reverse[metabolite.id] = { annotation_pair: [] } if annotation_value not in self.compounds_aliases_indexation_reverse[ metabolite.id][annotation_pair]: self.compounds_aliases_indexation_reverse[ metabolite.id][annotation_pair].append(annotation_value) if metabolite not in self.compounds_aliases_indexation[ annotation_pair][annotation_value]: self.compounds_aliases_indexation[annotation_pair][ annotation_value].append(metabolite.id) def add_new_metabolites_to_maps(self, new_metabolites): for metabolite in new_metabolites: compound_annotation = metabolite.annotation boimmg_compound_found = False for key in compound_annotation.keys(): if key in self.__compoundsAnnotationConfigs.keys(): annotation_pair = self.__compoundsAnnotationConfigs[key] if isinstance(compound_annotation[key], str): annotation_values = [compound_annotation[key]] else: annotation_values = compound_annotation[key] for annotation_value in annotation_values: if not boimmg_compound_found: boimmg_compound_found = self.__add_metabolites_to_boimmg_indexation( key, annotation_value, metabolite) self.__add_metabolites_to_aliases_indexation( annotation_pair, annotation_value, metabolite) if not boimmg_compound_found: if key == "boimmg.compound": construction_sub_string = self.__compoundsAnnotationConfigs[ "BOIMMG_ID_CONSTRUCTION"] value = compound_annotation[key] boimmg_id = int( value.replace(construction_sub_string, "")) self.boimmg_db_model_map[metabolite.id] = boimmg_id if boimmg_id not in self.boimmg_db_model_map_reverse.keys( ): self.boimmg_db_model_map_reverse[boimmg_id] = [ metabolite.id ] else: self.boimmg_db_model_map_reverse[ boimmg_id].append(metabolite.id) elif key == "inchi_key": value = compound_annotation[key][:-1] if value not in self.compound_inchikey_indexation: self.compound_inchikey_indexation[value] = [ metabolite.id ] else: self.compound_inchikey_indexation[ value].append(metabolite.id) def update_maps(self, old_inchikey, new_inchikey, old_id, new_id, new_ontology_id, old_aliases, new_aliases): compound_container = self.model.metabolites.get_by_id(new_id) if old_id in self.boimmg_db_model_map: del self.boimmg_db_model_map[old_id] self.boimmg_db_model_map[new_id] = new_ontology_id for key, value in self.boimmg_db_model_map_reverse.items(): if old_id in value: del self.boimmg_db_model_map_reverse[key] break if new_ontology_id not in self.boimmg_db_model_map_reverse: self.boimmg_db_model_map_reverse[new_ontology_id] = [ compound_container.id ] elif compound_container.id not in self.boimmg_db_model_map_reverse[ new_ontology_id]: self.boimmg_db_model_map_reverse[new_ontology_id].append( compound_container.id) if old_inchikey: if old_inchikey[:-1] in self.compound_inchikey_indexation: del self.compound_inchikey_indexation[old_inchikey[:-1]] if new_inchikey: if new_inchikey[:-1] in self.compound_inchikey_indexation: self.compound_inchikey_indexation[new_inchikey[:-1]].append( compound_container.id) else: self.compound_inchikey_indexation[new_inchikey[:-1]] = [ compound_container.id ] self.__update_aliases_indexation(old_id, new_aliases, compound_container) def __update_aliases_indexation(self, old_id, new_aliases, compound_container): if old_id in self.compounds_aliases_indexation_reverse: old_aliases = self.compounds_aliases_indexation_reverse[old_id] for db in self.compounds_aliases_indexation: if db in old_aliases: for alias in old_aliases[db]: if alias in self.compounds_aliases_indexation[db]: del self.compounds_aliases_indexation[db][alias] del self.compounds_aliases_indexation_reverse[old_id] for key in new_aliases: if key in self.__compoundsAnnotationConfigs.keys() and \ key in self.compounds_aliases_indexation: for alias in new_aliases[key]: if alias in self.compounds_aliases_indexation[key]: self.compounds_aliases_indexation[key][alias].append( compound_container.id) else: self.compounds_aliases_indexation[key][alias] = [ compound_container.id ] def check_metabolites_in_model(self, inchikey: str, aliases: dict, boimmg_container=None, boimmg_id=None) -> list: """ This method checks whether a given metabolite with the :param inchikey and the :param aliases. If a BOIMMG node is available the search starts with it. :param str inchikey: InchiKey of the metabolite to be searched. :param dict aliases: databases links of the metabolite to be searched. :param CompoundNode boimmg_container: BOIMMG node :return list: metabolites in model """ if not boimmg_container and not boimmg_id: if inchikey: inchikey_without_protonation = inchikey[:-1] if inchikey_without_protonation in self.compound_inchikey_indexation.keys( ): compound_ids = self.compound_inchikey_indexation[ inchikey_without_protonation] compounds_in_model = [ self.model.metabolites.get_by_id(compound_id) for compound_id in compound_ids ] return compounds_in_model for key in aliases: new_key = None if key in self.__compoundsAnnotationConfigs: new_key = self.__compoundsAnnotationConfigs[key] if key in self.compounds_aliases_indexation: for alias in aliases[key]: if alias in self.compounds_aliases_indexation.get(key): compound_ids = self.compounds_aliases_indexation[ key].get(alias) compounds_in_model = [ self.model.metabolites.get_by_id(compound_id) for compound_id in compound_ids ] return compounds_in_model elif new_key and new_key in self.compounds_aliases_indexation: for alias in aliases[key]: if alias in self.compounds_aliases_indexation.get( new_key): compound_ids = self.compounds_aliases_indexation[ new_key].get(alias) compounds_in_model = [ self.model.metabolites.get_by_id(compound_id) for compound_id in compound_ids ] return compounds_in_model elif boimmg_container: ont_id = boimmg_container.id res = [] if ont_id in self.__boimmg_db_model_map_reverse.keys(): for model_id in self.__boimmg_db_model_map_reverse[ont_id]: res.append(self.model.metabolites.get_by_id(model_id)) return res else: res = [] if boimmg_id in self.__boimmg_db_model_map_reverse.keys(): for model_id in self.__boimmg_db_model_map_reverse[boimmg_id]: res.append(self.model.metabolites.get_by_id(model_id)) return res return [] def check_if_boimmg_metabolite_in_model(self, boimmg_id, aliases={}): if boimmg_id in self.boimmg_db_model_map_reverse.keys(): return self.boimmg_db_model_map_reverse[boimmg_id] elif aliases: for db in aliases: db_aliases = aliases[db] for alias in db_aliases: if db in self.compounds_aliases_indexation.keys(): if alias in self.compounds_aliases_indexation[db]: compounds = self.compounds_aliases_indexation[db][ alias] return compounds else: return None return None def get_boimmg_id_from_model_compound_id(self, model_id): if model_id in self.boimmg_db_model_map.keys(): return self.boimmg_db_model_map[model_id] return None