def setUp(self): self.reaction = Reaction("CC+[O]O_[CH2]C+OO") self.reaction2 = Reaction(rmg_reaction=RMGReaction( reactants=[RMGMolecule(smiles="CC"), RMGMolecule(smiles="[O]O")], products=[RMGMolecule(smiles="[CH2]C"), RMGMolecule(smiles="OO")]))
def test_rmg_reaction(self): test_reaction = RMGReaction( reactants=[RMGMolecule(smiles="CC"), RMGMolecule(smiles="[O]O")], products=[RMGMolecule(smiles="[CH2]C"), RMGMolecule(smiles="OO")]) self.assertTrue( test_reaction.is_isomorphic(self.reaction.get_rmg_reaction())) self.assertTrue( test_reaction.is_isomorphic(self.reaction2.get_rmg_reaction()))
def setUp(self): self.reaction = Reaction("CC+[O]O_[CH2]C+OO") self.reaction2 = Reaction(rmg_reaction=RMGReaction( reactants=[RMGMolecule(smiles="CC"), RMGMolecule(smiles="[O]O")], products=[RMGMolecule(smiles="[CH2]C"), RMGMolecule(smiles="OO")])) self.ts = self.reaction.ts["forward"][0] self.ts2 = self.reaction.ts["forward"][0] self.ts.get_molecules() self.ts2.get_molecules()
def get_rmg_reaction(self): if self.rmg_reaction: return self.rmg_reaction r, p = self.label.split("_") reactants = [] products = [] for react in r.split("+"): reactants.append(RMGMolecule(SMILES=react)) for prod in p.split("+"): products.append(RMGMolecule(SMILES=prod)) self.rmg_reaction = RMGReaction(reactants=reactants, products=products) return self.rmg_reaction
def test_labeled_reaction(self): test_reaction = RMGReaction( reactants=[RMGMolecule(smiles="CC"), RMGMolecule(smiles="[O]O")], products=[RMGMolecule(smiles="[CH2]C"), RMGMolecule(smiles="OO")]) labeled_reaction, reaction_family = self.reaction.get_labeled_reaction( ) self.assertEquals(reaction_family.lower(), "h_abstraction") self.assertTrue(test_reaction.is_isomorphic(labeled_reaction)) merged = labeled_reaction.reactants[0].merge( labeled_reaction.reactants[1]) self.assertTrue(merged.get_labeled_atoms("*1")[0].is_carbon()) self.assertTrue(merged.get_labeled_atoms("*2")[0].is_hydrogen()) self.assertTrue(merged.get_labeled_atoms("*3")[0].is_oxygen) merged = labeled_reaction.products[0].merge( labeled_reaction.products[1]) self.assertTrue(merged.get_labeled_atoms("*3")[0].is_carbon()) self.assertTrue(merged.get_labeled_atoms("*2")[0].is_hydrogen()) self.assertTrue(merged.get_labeled_atoms("*1")[0].is_oxygen) labeled_reaction, reaction_family = self.reaction2.get_labeled_reaction( ) self.assertEquals(reaction_family.lower(), "h_abstraction") self.assertTrue(test_reaction.is_isomorphic(labeled_reaction)) merged = labeled_reaction.reactants[0].merge( labeled_reaction.reactants[1]) self.assertTrue(merged.get_labeled_atoms("*1")[0].is_carbon()) self.assertTrue(merged.get_labeled_atoms("*2")[0].is_hydrogen()) self.assertTrue(merged.get_labeled_atoms("*3")[0].is_oxygen) merged = labeled_reaction.products[0].merge( labeled_reaction.products[1]) self.assertTrue(merged.get_labeled_atoms("*3")[0].is_carbon()) self.assertTrue(merged.get_labeled_atoms("*2")[0].is_hydrogen()) self.assertTrue(merged.get_labeled_atoms("*1")[0].is_oxygen)
def test_labeled_reaction(self): test_reaction = RMGReaction( reactants=[RMGMolecule(SMILES="CC"), RMGMolecule(SMILES="[O]O")], products=[RMGMolecule(SMILES="[CH2]C"), RMGMolecule(SMILES="OO")]) labeled_reaction, reaction_family = self.reaction.get_labeled_reaction( ) self.assertEquals(reaction_family.lower(), "h_abstraction") self.assertTrue(test_reaction.isIsomorphic(labeled_reaction)) merged = labeled_reaction.reactants[0].merge( labeled_reaction.reactants[1]) self.assertTrue(merged.getLabeledAtom("*1").isCarbon()) self.assertTrue(merged.getLabeledAtom("*2").isHydrogen()) self.assertTrue(merged.getLabeledAtom("*3").isOxygen) merged = labeled_reaction.products[0].merge( labeled_reaction.products[1]) self.assertTrue(merged.getLabeledAtom("*3").isCarbon()) self.assertTrue(merged.getLabeledAtom("*2").isHydrogen()) self.assertTrue(merged.getLabeledAtom("*1").isOxygen) labeled_reaction, reaction_family = self.reaction2.get_labeled_reaction( ) self.assertEquals(reaction_family.lower(), "h_abstraction") self.assertTrue(test_reaction.isIsomorphic(labeled_reaction)) merged = labeled_reaction.reactants[0].merge( labeled_reaction.reactants[1]) self.assertTrue(merged.getLabeledAtom("*1").isCarbon()) self.assertTrue(merged.getLabeledAtom("*2").isHydrogen()) self.assertTrue(merged.getLabeledAtom("*3").isOxygen) merged = labeled_reaction.products[0].merge( labeled_reaction.products[1]) self.assertTrue(merged.getLabeledAtom("*3").isCarbon()) self.assertTrue(merged.getLabeledAtom("*2").isHydrogen()) self.assertTrue(merged.getLabeledAtom("*1").isOxygen)
def validate_irc(self, calc=None): """ A method to verify an IRC calc """ assert "irc" in calc.label, "The calculator provided is not an IRC calculator" reaction_label = calc.label.split("_irc")[0] logging.info("Validating IRC file...") irc_path = os.path.join(calc.scratch, calc.label + ".log") if not os.path.exists(irc_path): logging.info("It seems that the IRC claculation has not been run.") return False f = open(irc_path, "r") file_lines = f.readlines()[-5:] completed = False for file_line in file_lines: if "Normal termination" in file_line: logging.info("IRC successfully ran") completed = True if not completed: logging.info("IRC failed... could not be validated...") return False pth1 = list() steps = list() with open(irc_path) as outputFile: for line in outputFile: line = line.strip() if line.startswith('Point Number:'): if int(line.split()[2]) > 0: if int(line.split()[-1]) == 1: ptNum = int(line.split()[2]) pth1.append(ptNum) else: pass elif line.startswith('# OF STEPS ='): numStp = int(line.split()[-1]) steps.append(numStp) # This indexes the coordinate to be used from the parsing if steps == []: logging.error('No steps taken in the IRC calculation!') return False else: pth1End = sum(steps[:pth1[-1]]) # Compare the reactants and products ircParse = ccread(irc_path) # cf. # http://cclib.sourceforge.net/wiki/index.php/Using_cclib#Additional_information atomcoords = ircParse.atomcoords atomnos = ircParse.atomnos # Convert the IRC geometries into RMG molecules # We don't know which is reactant or product, so take the two at the end of the # paths and compare to the reactants and products mol1 = RMGMolecule() mol1.fromXYZ(atomnos, atomcoords[pth1End]) mol2 = RMGMolecule() mol2.fromXYZ(atomnos, atomcoords[-1]) testReaction = RMGReaction( reactants=mol1.split(), products=mol2.split(), ) r, p = reaction_label.split("_") reactants = [] products = [] for react in r.split("+"): react = RMGMolecule(SMILES=react) reactants.append(react) for prod in p.split("+"): prod = RMGMolecule(SMILES=prod) products.append(prod) possible_reactants = [] possible_products = [] for reactant in reactants: possible_reactants.append( reactant.generate_resonance_structures()) for product in products: possible_products.append( product.generate_resonance_structures()) possible_reactants = list(itertools.product(*possible_reactants)) possible_products = list(itertools.product(*possible_products)) for possible_reactant in possible_reactants: reactant_list = [] for react in possible_reactant: reactant_list.append(react.toSingleBonds()) for possible_product in possible_products: product_list = [] for prod in possible_product: product_list.append(prod.toSingleBonds()) targetReaction = RMGReaction(reactants=list(reactant_list), products=list(product_list)) if targetReaction.isIsomorphic(testReaction): logging.info("IRC calculation was successful!") return True logging.info("IRC calculation failed for {} :(".format(calc.label)) return False
def __init__(self, label=None, rmg_reaction=None, reaction_family="H_Abstraction", calculator=None): self.possible_families = [ # These families (and only these) will be loaded from both RMG and AutoTST databases "R_Addition_MultipleBond", "H_Abstraction", "intra_H_migration" ] self.load_databases() self.calculator = calculator if rmg_reaction: self.rmg_reaction, self.reaction_family = self.get_labeled_reaction( rmg_reaction=rmg_reaction) if label: try: reactants = [] products = [] r, p = label.split("_") for react in r.split("+"): reactants.append(RMGMolecule(SMILES=react)) for prod in p.split("+"): products.append(RMGMolecule(SMILES=prod)) test_reaction = RMGReaction(reactants=reactants, products=products) if self.rmg_reaction.isIsomorphic(test_reaction): self.label = label self.generate_reactants_and_products() else: logging.info( "Label provided doesn't match the RMGReaction, creating a new label" ) self.label = self.get_reaction_label(self.rmg_reaction) self.generate_reactants_and_products() except BaseException: logging.info( "Label provided doesn't match the RMGReaction, creating a new label" ) self.label = self.get_reaction_label(self.rmg_reaction) self.generate_reactants_and_products() else: self.label = self.get_reaction_label(self.rmg_reaction) self.generate_reactants_and_products() elif label: try: self.rmg_reaction, self.reaction_family = self.get_labeled_reaction( label=label) self.label = label self.generate_reactants_and_products(self.rmg_reaction) except BaseException: logging.info( "Label provided is not valid... setting everything to None" ) self.rmg_reaction = None self.label = None self.reaction_family = reaction_family else: self.rmg_reaction = None self.reaction_family = reaction_family self.label = label # a bit clumsy, but saves refactoring code for now. self.ts_database = self.ts_databases[reaction_family] self._ts = None self._distance_data = None
def get_labeled_reaction(self, label=None, rmg_reaction=None): """ A method that will return a labeled reaction given a reaction label or rmg_reaction """ assert ( label or rmg_reaction), "You must provide a reaction or a reaction label" label_reaction = None rmg_reaction_reaction = None if label: rmg_reactants = [] rmg_products = [] r, p = label.split("_") for react in r.split("+"): s = RMGMolecule(SMILES=react) rmg_reactants.append(s) for prod in p.split("+"): s = RMGMolecule(SMILES=prod) rmg_products.append(s) label_reaction = RMGReaction(reactants=rmg_reactants, products=rmg_products) if rmg_reaction: assert rmg_reaction.isIsomorphic(label_reaction) test_reaction = label_reaction else: test_reaction = label_reaction elif rmg_reaction: rmg_reactants = [] rmg_products = [] for react in rmg_reaction.reactants: if isinstance(react, RMGSpecies): rmg_reactants.append(react.molecule) elif isinstance(react, RMGMolecule): rmg_reactants.append([react]) for prod in rmg_reaction.products: if isinstance(prod, RMGSpecies): rmg_products.append(prod.molecule) elif isinstance(prod, RMGMolecule): rmg_products.append([prod]) test_reactants = [] test_products = [] if len(rmg_reactants) == 1: test_reactants = rmg_reactants elif len(rmg_reactants) == 2: l1, l2 = rmg_reactants for i in l1: for j in l2: test_reactants.append([i, j]) if len(rmg_products) == 1: test_reactants = rmg_products elif len(rmg_products) == 2: l1, l2 = rmg_products for i in l1: for j in l2: test_products.append([i, j]) for test_reactant in test_reactants: for test_products in test_products: test_reaction = RMGReaction(reactants=test_reactant, products=test_products) if rmg_reaction.isIsomorphic(test_reaction): break got_one = False for name, family in self.rmg_database.kinetics.families.items(): try: labeled_r, labeled_p = family.getLabeledReactantsAndProducts( test_reaction.reactants, test_reaction.products) if not (labeled_r and labeled_p): continue got_one = True except BaseException: logging.info("Couldn't match {} family...".format(family)) if got_one: break assert got_one, "Couldn't find a match" reaction_list = self.rmg_database.kinetics.generate_reactions_from_families( test_reaction.reactants, test_reaction.products, only_families=[name]) assert reaction_list, "Could not match a reaction to a reaction family..." for reaction in reaction_list: if reaction.isIsomorphic(test_reaction): reaction.reactants = labeled_r reaction.products = labeled_p break return reaction, name
def get_labeled_reaction(self): """ A method that will return a labeled reaction given a reaction label or rmg_reaction A label or an rmg_reaction needs to be provided in order for this method to work. If both are provided, we assert that the label matches the reaction. Variables: - label (str): the reaction label of interest - rmg_reaction (RMGReaction): the reaction of interest Returns: - reaction (RMGReaction): An RMGReaction with labeled reactants and products - name (str): The string corresponding to the reaction family matched to the reaction of interest """ if not (self.rmg_database or self.ts_databases): self.rmg_database, self.ts_databases = self.load_databases() assert (self.label or self.rmg_reaction ), "You must provide a reaction or a reaction label" match = False if self.label: rmg_reactants = [] rmg_products = [] r, p = self.label.split("_") for react in r.split("+"): s = RMGMolecule(SMILES=react) rmg_reactants.append(s) for prod in p.split("+"): s = RMGMolecule(SMILES=prod) rmg_products.append(s) test_reaction = RMGReaction(reactants=rmg_reactants, products=rmg_products) if self.rmg_reaction: assert self.rmg_reaction.isIsomorphic( test_reaction ), "The reaction label provided does not match the RMGReaction provided..." for name, family in list( self.rmg_database.kinetics.families.items()): if match: break try: labeled_r, labeled_p = family.getLabeledReactantsAndProducts( test_reaction.reactants, test_reaction.products) except ValueError: continue if not (labeled_r and labeled_p): continue if ((len(labeled_r) > 0) and (len(labeled_p) > 0)): logging.info("Matched reaction to {} family".format(name)) labeled_reactants = deepcopy(labeled_r) labeled_products = deepcopy(labeled_p) test_reaction.reactants = labeled_r[:] test_reaction.products = labeled_p[:] match = True final_family = family final_name = name break elif self.rmg_reaction: #RMGReaction but no label rmg_reactants = [] rmg_products = [] for react in self.rmg_reaction.reactants: if isinstance(react, RMGSpecies): rmg_reactants.append(react.molecule) elif isinstance(react, RMGMolecule): rmg_reactants.append([react]) for prod in self.rmg_reaction.products: if isinstance(prod, RMGSpecies): rmg_products.append(prod.molecule) elif isinstance(prod, RMGMolecule): rmg_products.append([prod]) test_reactants = [] test_products = [] if len(rmg_reactants) == 1: for l1 in rmg_reactants[0]: test_reactants.append([l1]) elif len(rmg_reactants) == 2: l1, l2 = rmg_reactants for i in l1: for j in l2: test_reactants.append([i, j]) if len(rmg_products) == 1: for l1 in rmg_products[0]: test_products.append([l1]) elif len(rmg_products) == 2: l1, l2 = rmg_products for i in l1: for j in l2: test_products.append([i, j]) reacts = test_reactants[:] prods = test_products[:] for name, family in list( self.rmg_database.kinetics.families.items()): logging.info("Trying to match {} to {}".format( self.rmg_reaction, family)) if match: continue test_reactants = reacts[:] test_products = prods[:] for test_reactant in test_reactants: for test_product in test_products: if match: continue test_reaction = RMGReaction(reactants=test_reactant, products=test_product) try: labeled_r, labeled_p = family.getLabeledReactantsAndProducts( test_reaction.reactants, test_reaction.products) if not (labeled_r and labeled_p): logging.info( "Unable to determine a reaction for the forward direction. Trying the reverse direction." ) raise ActionError except (ValueError, ActionError, IndexError): try: # Trying the reverse reaction if the forward reaction doesn't work # This is useful for R_Addition reactions labeled_r, labeled_p = family.getLabeledReactantsAndProducts( test_reaction.products, test_reaction.reactants) except (ValueError, ActionError, IndexError): continue if not (labeled_r and labeled_p): labeled_r, labeled_p = family.getLabeledReactantsAndProducts( test_reaction.products, test_reaction.reactants) continue if ((len(labeled_r) > 0) and (len(labeled_p) > 0)) and ( self.rmg_reaction.isIsomorphic(test_reaction)): logging.info( "Matched reaction to {} family".format(name)) labeled_reactants = deepcopy(labeled_r) labeled_products = deepcopy(labeled_p) test_reaction.reactants = labeled_r[:] test_reaction.products = labeled_p[:] logging.info("{}".format(labeled_r)) logging.info("{}".format(labeled_p)) match = True final_family = family print final_family final_name = name assert match, "Could not idetify labeled reactants and products" #try: reaction_list = final_family.generateReactions(test_reaction.reactants, test_reaction.products) #except KeyError: # reaction_list = None # logging.info("For some reason, RMG is having trouble generating reactions for {}".format(test_reaction)) assert reaction_list, "Could not match a reaction to a reaction family..." for reaction in reaction_list: if test_reaction.isIsomorphic(reaction): reaction.reactants = labeled_reactants reaction.products = labeled_products break self.rmg_reaction = reaction self.reaction_family = final_name return self.rmg_reaction, self.reaction_family
def validate_irc(self): """ A method to verify an IRC calc """ logging.info("Validating IRC file...") irc_path = os.path.join( self.directory, "ts", self.conformer.reaction_label, "irc", self.conformer.reaction_label + "_irc_" + self.conformer.direction + "_" + str(self.conformer.index) + ".log") complete, converged = self.verify_output_file(irc_path) if not complete: logging.info("It seems that the IRC claculation did not complete") return False if not converged: logging.info("The IRC calculation did not converge...") return False pth1 = list() steps = list() with open(irc_path) as outputFile: for line in outputFile: line = line.strip() if line.startswith('Point Number:'): if int(line.split()[2]) > 0: if int(line.split()[-1]) == 1: ptNum = int(line.split()[2]) pth1.append(ptNum) else: pass elif line.startswith('# OF STEPS ='): numStp = int(line.split()[-1]) steps.append(numStp) # This indexes the coordinate to be used from the parsing if steps == []: logging.error('No steps taken in the IRC calculation!') return False else: pth1End = sum(steps[:pth1[-1]]) # Compare the reactants and products ircParse = ccread(irc_path) atomcoords = ircParse.atomcoords atomnos = ircParse.atomnos mol1 = RMGMolecule() mol1.fromXYZ(atomnos, atomcoords[pth1End]) mol2 = RMGMolecule() mol2.fromXYZ(atomnos, atomcoords[-1]) testReaction = RMGReaction( reactants=mol1.split(), products=mol2.split(), ) r, p = self.conformer.reaction_label.split("_") reactants = [] products = [] for react in r.split("+"): react = RMGMolecule(SMILES=react) reactants.append(react) for prod in p.split("+"): prod = RMGMolecule(SMILES=prod) products.append(prod) possible_reactants = [] possible_products = [] for reactant in reactants: possible_reactants.append( reactant.generate_resonance_structures()) for product in products: possible_products.append( product.generate_resonance_structures()) possible_reactants = list(itertools.product(*possible_reactants)) possible_products = list(itertools.product(*possible_products)) for possible_reactant in possible_reactants: reactant_list = [] for react in possible_reactant: reactant_list.append(react.toSingleBonds()) for possible_product in possible_products: product_list = [] for prod in possible_product: product_list.append(prod.toSingleBonds()) targetReaction = RMGReaction(reactants=list(reactant_list), products=list(product_list)) if targetReaction.isIsomorphic(testReaction): logging.info("IRC calculation was successful!") return True logging.info("IRC calculation failed for {} :(".format(calc.label)) return False
def get_labeled_reaction(self, label=None, rmg_reaction=None): """ A method that will return a labeled reaction given a reaction label or rmg_reaction A label or an rmg_reaction needs to be provided in order for this method to work. If both are provided, we assert that the label matches the reaction. Variables: - label (str): the reaction label of interest - rmg_reaction (RMGReaction): the reaction of interest Returns: - reaction (RMGReaction): An RMGReaction with labeled reactants and products - name (str): The string corresponding to the reaction family matched to the reaction of interest """ assert ( label or rmg_reaction), "You must provide a reaction or a reaction label" label_reaction = None rmg_reaction_reaction = None test_reactions = [] match = False if label: rmg_reactants = [] rmg_products = [] r, p = label.split("_") for react in r.split("+"): s = RMGMolecule(SMILES=react) rmg_reactants.append(s) for prod in p.split("+"): s = RMGMolecule(SMILES=prod) rmg_products.append(s) test_reaction = RMGReaction( reactants=rmg_reactants, products=rmg_products) if rmg_reaction: assert rmg_reaction.isIsomorphic( test_reaction), "The reaction label provided does not match the RMGReaction provided..." for name, family in list(self.rmg_database.kinetics.families.items()): if match: break labeled_r, labeled_p = family.getLabeledReactantsAndProducts( test_reaction.reactants, test_reaction.products) if not (labeled_r and labeled_p): continue if ((len(labeled_r) > 0) and (len(labeled_p) > 0)): logging.info("Matched reaction to {} family".format(name)) labeled_reactants = deepcopy(labeled_r) labeled_products = deepcopy(labeled_p) test_reaction.reactants = labeled_r[:] test_reaction.products = labeled_p[:] match = True final_name = name break elif rmg_reaction: rmg_reactants = [] rmg_products = [] for react in rmg_reaction.reactants: if isinstance(react, RMGSpecies): rmg_reactants.append(react.molecule) elif isinstance(react, RMGMolecule): rmg_reactants.append([react]) for prod in rmg_reaction.products: if isinstance(prod, RMGSpecies): rmg_products.append(prod.molecule) elif isinstance(prod, RMGMolecule): rmg_products.append([prod]) test_reactants = [] test_products = [] if len(rmg_reactants) == 1: test_reactants = rmg_reactants elif len(rmg_reactants) == 2: l1, l2 = rmg_reactants for i in l1: for j in l2: test_reactants.append([i, j]) if len(rmg_products) == 1: test_reactants = rmg_products elif len(rmg_products) == 2: l1, l2 = rmg_products for i in l1: for j in l2: test_products.append([i, j]) for name, family in list(self.rmg_database.kinetics.families.items()): if match: break for test_reactant in test_reactants: for test_products in test_products: if match: continue test_reaction = RMGReaction( reactants=test_reactant, products=test_products) labeled_r, labeled_p = family.getLabeledReactantsAndProducts( test_reaction.reactants, test_reaction.products) if not (labeled_r and labeled_p): continue if ((len(labeled_r) > 0) and (len(labeled_p) > 0)): logging.info( "Matched reaction to {} family".format(name)) labeled_reactants = deepcopy(labeled_r) labeled_products = deepcopy(labeled_p) test_reaction.reactants = labeled_r[:] test_reaction.products = labeled_p[:] logging.info("\n{}".format(labeled_r)) logging.info("\n{}".format(labeled_p)) match = True final_name = name break assert match, "Could not idetify labeled reactants and products" reaction_list = self.rmg_database.kinetics.generate_reactions_from_families( test_reaction.reactants, test_reaction.products, only_families=[final_name]) assert reaction_list, "Could not match a reaction to a reaction family..." for reaction in reaction_list: if test_reaction.isIsomorphic(reaction): reaction.reactants = labeled_reactants reaction.products = labeled_products break return reaction, name
def get_labeled_reaction(self): """ A method that will return a labeled reaction given a reaction label or rmg_reaction A label or an rmg_reaction needs to be provided in order for this method to work. If both are provided, we assert that the label matches the reaction. Variables: - label (str): the reaction label of interest - rmg_reaction (RMGReaction): the reaction of interest Returns: - reaction (RMGReaction): An RMGReaction with labeled reactants and products - name (str): The string corresponding to the reaction family matched to the reaction of interest """ if not (self.rmg_database or self.ts_databases): self.rmg_database, self.ts_databases = self.load_databases() assert (self.label or self.rmg_reaction ), "You must provide a reaction or a reaction label" match = False # We have not found a labeled reaction that matches the one provided. if self.label: # A reaction label was provided # Generating lists of lists. Main list is the reactans or products # Secondary list is composed of the resonance structures for that species r, p = self.label.split("_") rmg_reactants = [ RMGMolecule(smiles=smile).generate_resonance_structures() for smile in r.split("+") ] rmg_products = [ RMGMolecule(smiles=smile).generate_resonance_structures() for smile in p.split("+") ] combos_to_try = list( itertools.product(list(itertools.product(*rmg_reactants)), list(itertools.product(*rmg_products)))) # looping though each reaction family and each combination of reactants and products for name, family in list( self.rmg_database.kinetics.families.items()): logging.info("Trying to match reacction to {}".format(family)) for rmg_reactants, rmg_products in combos_to_try: # Making a test reaction test_reaction = RMGReaction(reactants=list(rmg_reactants), products=list(rmg_products)) try: # Trying to label the reaction labeled_r, labeled_p = family.get_labeled_reactants_and_products( test_reaction.reactants, test_reaction.products) except: # Failed to match a reaction to the family logging.error( "Couldn't match {} to {}, trying different combination..." .format(test_reaction, name)) continue if not (labeled_r and labeled_p): # Catching an error where it matched the reaction but the reactants and products we not return... # A weird bug in RMG that I can explain continue if ((len(labeled_r) > 0) and (len(labeled_p) > 0)): # We found a match. if match: # We found a match already, but we were able to label the reaction again... # This would happen if different combinations of resonance structures match up logging.warning( "This reaction has been already labeled... \ it seems that resonance structures \for reactants and products exist." ) logging.warning("Skipping this duplicate for now") continue logging.info( "Matched reaction to {} family".format(name)) # Copying labed reactions and saving them for later labeled_reactants = deepcopy(labeled_r) labeled_products = deepcopy(labeled_p) match_reaction = RMGReaction( reactants=deepcopy(labeled_r), products=deepcopy(labeled_p)) # Setting it true that we matche the reaction and remembering the # RMG reaction family and family name match = True final_family = family final_name = name elif self.rmg_reaction: #RMGReaction but no label rmg_reactants = [] rmg_products = [] for react in self.rmg_reaction.reactants: if isinstance(react, RMGSpecies): rmg_reactants.append(react.molecule) elif isinstance(react, RMGMolecule): rmg_reactants.append(react.generate_resonance_structures()) for prod in self.rmg_reaction.products: if isinstance(prod, RMGSpecies): rmg_products.append(prod.molecule) elif isinstance(prod, RMGMolecule): rmg_products.append(prod.generate_resonance_structures()) combos_to_try = list( itertools.product(list(itertools.product(*rmg_reactants)), list(itertools.product(*rmg_products)))) for name, family in list( self.rmg_database.kinetics.families.items()): logging.info("Trying to match reaction to {}".format(name)) for rmg_reactants, rmg_products in combos_to_try: # Making a test reaction test_reaction = RMGReaction(reactants=list(rmg_reactants), products=list(rmg_products)) try: # Trying to label the reaction labeled_r, labeled_p = family.get_labeled_reactants_and_products( test_reaction.reactants, test_reaction.products) if not (labeled_r and labeled_p): logging.error( "Unable to determine a reaction for the forward direction. Trying the reverse direction." ) raise ActionError except: try: # Trying the reverse reaction if the forward reaction doesn't work # This is useful for R_Addition reactions labeled_r, labeled_p = family.get_labeled_reactants_and_products( test_reaction.products, test_reaction.reactants) except: logging.error( "Couldn't match {} to {}, trying different combination..." .format(test_reaction, name)) continue if not (labeled_r and labeled_p): # Catching an error where it matched the reaction but the reactants and products we not return... # A weird bug in RMG that I can explain continue if ((len(labeled_r) > 0) and (len(labeled_p) > 0)): # We found a match. if match: # We found a match already, but we were able to label the reaction again... # This would happen if different combinations of resonance structures match up logging.warning( "This reaction has been already labeled... \ it seems that resonance structures \for reactants and products exist." ) logging.warning("Skipping this duplicate for now") continue logging.info( "Matched reaction to {} family".format(name)) # Copying labed reactions and saving them for later labeled_reactants = deepcopy(labeled_r) labeled_products = deepcopy(labeled_p) match_reaction = RMGReaction( reactants=deepcopy(labeled_r), products=deepcopy(labeled_p)) # Setting it true that we matche the reaction and remembering the # RMG reaction family and family name match = True final_family = family final_name = name assert match, "Could not idetify labeled reactants and products" reaction_list = final_family.generate_reactions( match_reaction.reactants, match_reaction.products) assert reaction_list, "Could not match a reaction to a reaction family..." for reaction in reaction_list: if match_reaction.is_isomorphic(reaction): reaction.reactants = labeled_reactants reaction.products = labeled_products break self.rmg_reaction = reaction self.reaction_family = final_name return self.rmg_reaction, self.reaction_family