Example #1
0
    def __init__(self, smiles=None, rmg_molecule=None, index=0):

        self.energy = None
        self.index = index

        if (smiles or rmg_molecule):
            if smiles and rmg_molecule:
                assert rmg_molecule.isIsomorphic(
                    RMGMolecule(SMILES=smiles)
                ), "SMILES string did not match RMG Molecule object"
                self.smiles = smiles
                self.rmg_molecule = rmg_molecule

            elif rmg_molecule:
                self.rmg_molecule = rmg_molecule
                self.smiles = rmg_molecule.toSMILES()

            else:
                self.smiles = smiles
                self.rmg_molecule = RMGMolecule(SMILES=smiles)

            self.rmg_molecule.updateMultiplicity()
            self.get_mols()
            self.get_geometries()

        else:
            self.smiles = None
            self.rmg_molecule = None
            self.rdkit_molecule = None
            self.ase_molecule = None
            self.bonds = []
            self.angles = []
            self.torsions = []
            self.cistrans = []
            self.chiral_centers = []
Example #2
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")]))
Example #3
0
        def check_isomorphic(conformer):
            """
            Compares whatever is in the log file 'f' 
            to the SMILES of the passed in 'conformer'
            """
            starting_molecule = RMGMolecule(smiles=conformer.smiles)
            starting_molecule = starting_molecule.to_single_bonds()

            atoms = self.read_log(
                os.path.join(scratch_dir, f)
            )

            test_molecule = RMGMolecule()
            test_molecule.from_xyz(
                atoms.arrays["numbers"],
                atoms.arrays["positions"]
            )
            if not starting_molecule.is_isomorphic(test_molecule):
                logging.info(
                    "Output geometry of {} is not isomorphic with input geometry".format(calc.label))
                return False
            else:
                logging.info(
                "{} was successful and was validated!".format(calc.label))
                return True
Example #4
0
    def get_complexes(self, rmg_reaction=None):
        """
        A method to create a forward and reverse TS complexes used to initialize transition state geometries
        """

        if not rmg_reaction:
            rmg_reaction = self.rmg_reaction

        reactant_complex = RMGMolecule()
        for react in rmg_reaction.reactants:
            if isinstance(react, RMGMolecule):
                reactant_complex = reactant_complex.merge(react)
            elif isinstance(react, RMGSpecies):
                reactant_complex = reactant_complex.merge(react.molecule[0])

        product_complex = RMGMolecule()
        for prod in rmg_reaction.products:
            if isinstance(prod, RMGMolecule):
                product_complex = product_complex.merge(prod)
            elif isinstance(prod, RMGSpecies):
                product_complex = product_complex.merge(prod.molecule[0])

        reactant_complex.updateMultiplicity()
        product_complex.updateMultiplicity()

        self.complexes = {
            "forward": reactant_complex,
            "reverse": product_complex
        }

        return self.complexes
Example #5
0
    def __init__(
            self,
            smiles=None,
            reaction_label=None,
            direction='forward',
            rmg_molecule=None,
            reaction_family="H_Abstraction",
            distance_data=None,
            index=0):
        self.energy = None
        #####################################################
        #####################################################
        assert reaction_label, "A reaction label needs to be provided in addition to a smiles or rmg_molecule"
        assert direction in ["forward",
                             "reverse"], "Please provide a valid direction"
        self.reaction_label = reaction_label
        self.direction = direction.lower()
        self._rdkit_molecule = None
        self._ase_molecule = None
        self.reaction_family = reaction_family
        self.distance_data = distance_data
        self.index = index

        if (smiles or rmg_molecule):
            if smiles and rmg_molecule:
                assert rmg_molecule.isIsomorphic(RMGMolecule(
                    SMILES=smiles)), "SMILES string did not match RMG Molecule object"
                self.smiles = smiles
                self.rmg_molecule = rmg_molecule

            elif rmg_molecule:
                self.rmg_molecule = rmg_molecule
                self.smiles = rmg_molecule.toSMILES()

            else:
                self.smiles = smiles
                self.rmg_molecule = RMGMolecule(SMILES=smiles)

            self.rmg_molecule.updateMultiplicity()
            self.get_mols()
            self.get_geometries()
            self._symmetry_number = None

        else:
            self.smiles = None
            self.rmg_molecule = None
            self.rdkit_molecule = None
            self._pseudo_geometry = None
            self.ase_molecule = None
            self.bonds = []
            self.angles = []
            self.torsions = []
            self.cistrans = []
            self.chiral_centers = []
            self._symmetry_number = None
Example #6
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()))
Example #7
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()
Example #8
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
Example #9
0
    def __init__(self,
                 smiles=None,
                 reaction_label=None,
                 rmg_molecule=None,
                 reaction_family="H_Abstraction",
                 distance_data=None):
        self.energy = None
        #####################################################
        #####################################################
        assert reaction_label, "A reaction label needs to be provided in addition to a smiles or rmg_molecule"
        self.reaction_label = reaction_label
        self._rdkit_molecule = None
        self._ase_molecule = None
        self.reaction_family = reaction_family
        self.distance_data = distance_data

        if (smiles or rmg_molecule):
            if smiles and rmg_molecule:
                assert rmg_molecule.isIsomorphic(
                    RMGMolecule(SMILES=smiles)
                ), "SMILES string did not match RMG Molecule object"
                self.smiles = smiles
                self.rmg_molecule = rmg_molecule

            elif rmg_molecule:
                self.rmg_molecule = rmg_molecule
                self.smiles = rmg_molecule.toSMILES()

            else:
                self.smiles = smiles
                self.rmg_molecule = RMGMolecule(SMILES=smiles)

            self.rmg_molecule.updateMultiplicity()
            self.get_mols()
            self.get_geometries()

        else:
            self.smiles = None
            self.rmg_molecule = None
            self.rdkit_molecule = None
            self._pseudo_geometry = None
            self.ase_molecule = None
            self.bonds = []
            self.angles = []
            self.torsions = []
            self.cistrans = []
            self.chiral_centers = []
Example #10
0
    def get_rmg_complexes(self):
        """
        A method to create a forward and reverse TS complexes used to initialize transition state geometries

        Variables:
        - rmg_reaction (RMGReaction): The RMGReaction of interest

        Returns:
        - complexes (dict): a dictionary containing RMGMolecules of the forward and reverse reaction complexes
        """

        if self.rmg_reaction is None:
            self.get_labeled_reaction()

        reactant_complex = RMGMolecule()
        for react in self.rmg_reaction.reactants:
            if isinstance(react, RMGMolecule):
                reactant_complex = reactant_complex.merge(react)
            elif isinstance(react, RMGSpecies):
                for mol in react.molecule:
                    if len(mol.getLabeledAtoms()) > 0:
                        reactant_complex = reactant_complex.merge(mol)

        product_complex = RMGMolecule()
        for prod in self.rmg_reaction.products:
            if isinstance(prod, RMGMolecule):
                product_complex = product_complex.merge(prod)
            elif isinstance(prod, RMGSpecies):
                for mol in prod.molecule:
                    if len(mol.getLabeledAtoms()) > 0:
                        product_complex = product_complex.merge(mol)

        reactant_complex.updateMultiplicity()
        product_complex.updateMultiplicity()

        if len(reactant_complex.getLabeledAtoms()) == 0 or len(
                product_complex.getLabeledAtoms()) == 0:
            logging.warning(
                "REACTING ATOMS LABELES NOT PROVIDED. Please call `Reaction.get_labeled_reaction` to generate labeled complexes"
            )

        self.complexes = {
            "forward": reactant_complex,
            "reverse": product_complex
        }

        return self.complexes
Example #11
0
    def get_molecules(self):
        if not self.rmg_molecule:
            self.rmg_molecule = RMGMolecule(SMILES=self.smiles)
        self.rdkit_molecule = self.get_rdkit_mol()
        self.ase_molecule = self.get_ase_mol()
        self.get_geometries()

        return self.rdkit_molecule, self.ase_molecule
Example #12
0
 def test_molecule(self):
     """
     Test that a Molecule contains the `id` attribute.
     """
     rmg_mol = RMGMolecule(smiles='C')
     mol = Molecule(smiles='C')
     self.assertIsInstance(mol, RMGMolecule)
     self.assertTrue(hasattr(mol, 'id'))
     self.assertFalse(hasattr(rmg_mol, 'id'))
Example #13
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)
Example #14
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)
Example #15
0
    def get_complexes(self, rmg_reaction=None):
        """
        A method to create a forward and reverse TS complexes used to initialize transition state geometries

        Variables:
        - rmg_reaction (RMGReaction): The RMGReaction of interest

        Returns:
        - complexes (dict): a dictionary containing RMGMolecules of the forward and reverse reaction complexes
        """

        if not rmg_reaction:
            rmg_reaction = self.rmg_reaction

        reactant_complex = RMGMolecule()
        for react in rmg_reaction.reactants:
            if isinstance(react, RMGMolecule):
                reactant_complex = reactant_complex.merge(react)
            elif isinstance(react, RMGSpecies):
                for mol in react.molecule:
                    if len(mol.getLabeledAtoms()) > 0:
                        reactant_complex = reactant_complex.merge(mol)
        product_complex = RMGMolecule()
        for prod in rmg_reaction.products:
            if isinstance(prod, RMGMolecule):
                product_complex = product_complex.merge(prod)
            elif isinstance(prod, RMGSpecies):
                for mol in prod.molecule:
                    if len(mol.getLabeledAtoms()) > 0:
                        product_complex = product_complex.merge(mol)

        reactant_complex.updateMultiplicity()
        product_complex.updateMultiplicity()

        self.complexes = {
            "forward": reactant_complex,
            "reverse": product_complex}

        return self.complexes
Example #16
0
    def calculate_symmetry_number(self):

        numbers = self.ase_molecule.numbers
        positions = self.ase_molecule.positions

        mol = RMGMolecule()
        mol.from_xyz(numbers, positions)
        try:
            species = RMGSpecies(molecule=[mol])
            self._symmetry_number = species.get_symmetry_number()
        except ValueError:
            self._symmetry_number = mol.get_symmetry_number()

        return self._symmetry_number
Example #17
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
Example #18
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
Example #19
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
Example #20
0
    def __init__(self, smiles=[], rmg_species=None):

        assert isinstance(smiles, list)

        self._conformers = None

        if ((len(smiles) != 0) and rmg_species):
            # Provide both a list of smiles and an rmg_species
            assert isinstance(rmg_species,
                              (rmgpy.molecule.Molecule, rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                rmg_species.generate_resonance_structures()

            else:
                rmg_species.generate_resonance_structures()

            smiles_list = []
            for rmg_mol in rmg_species.molecule:
                smiles_list.append(rmg_mol.toSMILES())

            for s in smiles_list:
                if s in smiles:
                    continue
                if not (s in smiles):
                    smiles.append(s)

            assert len(smiles) == len(
                smiles_list
            ), "The list of smiles presented does not match the possible species provided"

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif (rmg_species and (len(smiles) == 0)):
            # RMG species provided, but not smiles

            assert isinstance(rmg_species,
                              (rmgpy.molecule.Molecule, rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                rmg_species.generate_resonance_structures()

            else:
                rmg_species.generate_resonance_structures()

            smiles = []
            for rmg_mol in rmg_species.molecule:
                smiles.append(rmg_mol.toSMILES())

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif ((not rmg_species) and (len(smiles) != 0)):
            # smiles provided but not species

            species_list = []
            for smile in smiles:
                molecule = RMGMolecule(SMILES=smile)
                s = RMGSpecies(molecule=[molecule])
                s.generate_resonance_structures()
                species_list.append(s)

            for s1 in species_list:
                for s2 in species_list:
                    assert s1.isIsomorphic(
                        s2), "SMILESs provided describe different species"

            self.smiles = smiles
            self.rmg_species = species_list[0]

        else:
            self.smiles = []
            self.rmg_species = rmg_species
Example #21
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
Example #22
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
Example #23
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
Example #24
0
    def __init__(self, smiles=[], rmg_species=None):
        """
        A class that holds information for Species object
        """

        assert isinstance(smiles, list)

        self._conformers = None

        if ((len(smiles) != 0) and rmg_species):
            # Provide both a list of smiles and an rmg_species
            assert isinstance(
                rmg_species,
                (rmgpy.molecule.Molecule,
                 rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            else:
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            smiles_list = []
            for rmg_mol in rmg_species.molecule:
                smiles_list.append(rmg_mol.toSMILES())

            for s in smiles_list:
                if s in smiles:
                    continue
                if not(s in smiles):
                    smiles.append(s)

            assert len(smiles) == len(
                smiles_list), "The list of smiles presented does not match the possible species provided"

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif (rmg_species and (len(smiles) == 0)):
            # RMG species provided, but not smiles

            assert isinstance(
                rmg_species,
                (rmgpy.molecule.Molecule,
                 rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            else:
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            smiles = []
            for rmg_mol in rmg_species.molecule:
                smiles.append(rmg_mol.toSMILES())

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif ((not rmg_species) and (len(smiles) != 0)):
            # smiles provided but not species

            species_list = []
            for smile in smiles:
                molecule = RMGMolecule(SMILES=smile)
                species_list.append(molecule.generate_resonance_structures())

            if len(smiles) != 1:
                got_one = False
                for s1 in species_list:
                    for s2 in species_list:
                        for m1 in s1:
                            for m2 in s2:
                                if m1.isIsomorphic(m2):
                                    got_one = True
                assert got_one, "SMILESs provided describe different species"

            smiles_list = []
            for mol in species_list[0]:
                smiles_list.append(mol.toSMILES())

            self.smiles = smiles_list
            self.rmg_species = species_list[0]

        else:
            self.smiles = []
            self.rmg_species = rmg_species
Example #25
0
def update_dictionary_entries(old_entries, need_to_add):
    """
    Expects dictionary of species entries and
    unique list of species (as SMILES) that need to be added

    Creates new entries for the species that need to be added
    Returns old and new entries
    """
    list(set(need_to_add))
    for j, species in enumerate(need_to_add):

        molecule = RMGMolecule(SMILES=species)
        adjlist = molecule.toAdjacencyList()

        multiplicity = None
        if re.search('(?<=multiplicity ).*', adjlist):
            multiplicity = int(
                re.search('(?<=multiplicity ).*', adjlist).group(0))
            adjlist = re.sub(r'multiplicity .*',
                             'multiplicity [{}]'.format(multiplicity), adjlist)

        group = rmgpy.molecule.group.Group()
        group.fromAdjacencyList(adjlist)

        atom_counts = {}
        rel_label = ''
        for atom in ['C', 'H', 'O']:
            count = species.count(atom)
            if count > 0:
                rel_label = rel_label + atom + str(count)

        assert rel_label != ''
        """
        3 Scenerios:
        No old -> no need for ID number: max_ID = -1
        Only one old -> needs to have ID of 1: max_ID = 0
        Multiple old -> needs to have a unique ID: max_ID > 0
        """

        new_ID = None
        max_ID = -1
        duplicate = False
        for old_label in old_entries:
            old_entry = old_entries[old_label]

            if group.isIsomorphic(old_entry.item):
                duplicate = True
                print '{} found to be duplicate'.format(old_entry)
                continue

            if rel_label not in old_label:
                continue

            if rel_label == old_label and max_ID == -1:
                # Atleast one with same label
                max_ID = 0

            if old_label.find('-') > 0:
                old_label, ID_str = old_label.split('-')
                ID = int(ID_str)

                if old_label == rel_label and ID > max_ID:
                    # Multiple exisitng labels
                    max_ID = ID

        if max_ID > -1:
            # Existing label
            new_ID = max_ID + 1
            rel_label = rel_label + '-' + str(new_ID)

        if not duplicate:
            entry = Entry()
            entry.label = rel_label
            entry.item = group
            assert rel_label not in old_entries.keys()
            old_entries[rel_label] = entry

    entry_labels = [old_entries[key].label for key in old_entries]
    assert len(entry_labels) == len(list(
        set(entry_labels))), 'Non-unique labels in dictionary'

    return old_entries
Example #26
0
    def calculate_conformer(self, conformer, calculator):

        if isinstance(calculator, Gaussian):
            calc = calculator.get_conformer_calc(conformer=conformer,
                                                 convergence='Tight')

        else:
            calc = calculator.get_conformer_calc(conformer=conformer)

        scratch = calculator.scratch

        scratch_dir = os.path.join(calculator.scratch, "species",
                                   conformer.smiles, "conformers")

        f = calc.label + ".log"

        if not os.path.exists(os.path.join(scratch_dir, f)):
            logging.info("Submitting conformer calculation for {}".format(
                calc.label))
            label = self.submit_conformer(conformer, calc, "general")
            while not self.check_complete(label):
                time.sleep(15)

        else:
            logging.info(
                "It appears that we already have a complete log file for {}".
                format(calc.label))

            complete, converged = calculator.verify_output_file(
                os.path.join(scratch_dir, f))
            if not complete:
                logging.info(
                    "It seems that the file never completed for {} completed, running it again"
                    .format(calc.label))
                label = self.submit_conformer(conformer, calc, "general")
                while not self.check_complete(label):
                    time.sleep(15)

        complete, converged = calculator.verify_output_file(
            os.path.join(scratch_dir, f))

        if (complete and converged):
            logging.info("{} was successful and was validated!".format(
                calc.label))
            atoms = self.read_log(os.path.join(scratch_dir, f))

            starting_molecule = RMGMolecule(SMILES=conformer.smiles)
            starting_molecule = starting_molecule.toSingleBonds()

            test_molecule = RMGMolecule()
            test_molecule.fromXYZ(atoms.arrays["numbers"],
                                  atoms.arrays["positions"])

            if not starting_molecule.isIsomorphic(test_molecule):
                logging.info(
                    "Output geometry of {} is not isomorphic with input geometry"
                    .format(calc.label))
                result = False
            else:
                logging.info("{} was successful and was validated!".format(
                    calc.label))
                result = True

        if not complete:
            logging.info("It appears that {} was killed prematurely".format(
                calc.label))
            result = False

        elif not converged:
            logging.info("{} did not converge".format(calc.label))
            result = False
            if isinstance(calculator, Gaussian):
                if not calc.convergence.lower() in [
                        "tight", "verytight", "loose"
                ]:
                    logging.info("{} failed QM optimization".format(
                        calc.label))
                else:
                    logging.info(
                        "Resubmitting {} with default convergence criteria".
                        format(calc.label))
                    atoms = self.read_log(os.path.join(scratch_dir, f))
                    conformer.ase_molecule = atoms
                    conformer.update_coords_from("ase")
                    calc = calculator.get_conformer_calc(conformer,
                                                         convergence="")
                    logging.info(
                        "Removing the old log file that didn't converge, restarting from last geometry"
                    )
                    os.remove(os.path.join(scratch_dir, f))

                    label = self.submit_conformer(conformer, calc, "general")
                    while not self.check_complete(label):
                        time.sleep(15)

                    scratch_dir = os.path.join(calculator.scratch, "species",
                                               conformer.smiles, "conformers")
                    f = calc.label + ".log"
                    if not os.path.exists(os.path.join(scratch_dir, f)):
                        logging.info(
                            "It seems that {} was never run...".format(
                                calc.label))
                        result = False

                    complete, converged = calculator.verify_output_file(
                        os.path.join(scratch_dir, f))

                    if not complete:
                        logging.info(
                            "It appears that {} was killed prematurely".format(
                                calc.label))
                        result = False

                    elif not converged:
                        logging.info("{} failed second QM optimization".format(
                            calc.label))
                        result = False

                    else:
                        atoms = self.read_log(os.path.join(scratch_dir, f))

                        starting_molecule = RMGMolecule(
                            SMILES=conformer.smiles)
                        starting_molecule = starting_molecule.toSingleBonds()

                        test_molecule = RMGMolecule()
                        test_molecule.fromXYZ(atoms.arrays["numbers"],
                                              atoms.arrays["positions"])

                        if not starting_molecule.isIsomorphic(test_molecule):
                            logging.info(
                                "Output geometry of {} is not isomorphic with input geometry"
                                .format(calc.label))
                            result = False
                        else:
                            logging.info(
                                "{} was successful and was validated!".format(
                                    calc.label))
                            result = True

        if not result:
            fail_dir = os.path.join(scratch_dir, "failures")
            try:
                os.makedirs(os.path.join(scratch_dir, "failures"))
            except OSError:
                logging.info("{} already exists...".format(fail_dir))
            move(os.path.join(scratch_dir, f),
                 os.path.join(scratch_dir, "failures", f))
            return False

        return True
Example #27
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