Esempio n. 1
0
 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")]))
Esempio n. 2
0
    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()))
Esempio n. 3
0
 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()
Esempio n. 4
0
    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
Esempio n. 5
0
    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)
Esempio n. 6
0
    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)
Esempio n. 7
0
    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
Esempio n. 8
0
    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
Esempio n. 9
0
    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
Esempio n. 10
0
    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
Esempio n. 11
0
    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
Esempio n. 12
0
    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
Esempio n. 13
0
    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