Пример #1
0
    def loadEntry(self,
                  index,
                  label,
                  solvent,
                  molecule=None,
                  reference=None,
                  referenceType='',
                  shortDesc='',
                  longDesc='',
                  ):
        spc = molecule
        if molecule is not None:
            try:
                spc = Species().fromSMILES(molecule)
            except:
                logging.debug("Solvent '{0}' does not have a valid SMILES '{1}'" .format(label, molecule))
                try:
                    spc = Species().fromAdjacencyList(molecule)
                except:
                    logging.error("Can't understand '{0}' in solute library '{1}'".format(molecule, self.name))
                    raise
            spc.generateResonanceIsomers()

        self.entries[label] = Entry(
            index = index,
            label = label,
            item = spc,
            data = solvent,
            reference = reference,
            referenceType = referenceType,
            shortDesc = shortDesc,
            longDesc = longDesc.strip(),
        )
Пример #2
0
def getRMGSpeciesFromSMILES(smilesList, speciesList, names=False):
    """
    Args:
        smilesList: list of SMIlES for species of interest
        speciesList: a list of RMG species objects
        names: set to `True` if species names are desired to be returned instead of objects

    Returns: A dict containing the smiles as keys and RMG species objects as their values
    If the species is not found, the value will be returned as None
    """
    # Not strictly necesssary, but its likely that people will forget to put the brackets around the bath gasses
    bathGases={"Ar": "[Ar]", "He": "[He]", "Ne": "[Ne]"}
    mapping = {}
    for smiles in smilesList:
        if smiles in bathGases:
            spec = Species().fromSMILES(bathGases[smiles])
        else:
            spec=Species().fromSMILES(smiles)
        spec.generateResonanceIsomers()

        for rmgSpecies in speciesList:
            if spec.isIsomorphic(rmgSpecies):
                if smiles in mapping:
                    raise KeyError("The SMILES {0} has appeared twice in the species list!".format(smiles))
                mapping[smiles] = rmgSpecies
                break
        else: 
            mapping[smiles] = None

    return mapping
Пример #3
0
 def testOldThermoGeneration(self):
     """
     Test that the old ThermoDatabase generates relatively accurate thermo data.
     """
     
     for smiles, symm, H298, S298, Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500 in self.testCases:
         Cplist = [Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500]
         species = Species(molecule=[Molecule(SMILES=smiles)])
         species.generateResonanceIsomers()
         thermoData = self.oldDatabase.getThermoData(Species(molecule=[species.molecule[0]]))
         molecule = species.molecule[0]
         for mol in species.molecule[1:]:
             thermoData0 = self.oldDatabase.getAllThermoData(Species(molecule=[mol]))[0][0]
             for data in self.oldDatabase.getAllThermoData(Species(molecule=[mol]))[1:]:
                 if data.getEnthalpy(298) < thermoData0.getEnthalpy(298):
                     thermoData0 = data
             if thermoData0.getEnthalpy(298) < thermoData.getEnthalpy(298):
                 thermoData = thermoData0
                 molecule = mol
         
         self.assertEqual(molecule.calculateSymmetryNumber(), symm)
         self.assertTrue(1 - thermoData.getEnthalpy(298) / 4184 / H298 < 0.01)
         self.assertTrue(1 - thermoData.getEntropy(298) / 4.184 / S298 < 0.01)
         for T, Cp in zip(self.Tlist, Cplist):
             self.assertTrue(1 - thermoData.getHeatCapacity(T) / 4.184 / Cp < 0.1)
Пример #4
0
 def testNewThermoGeneration(self):
     """
     Test that the new ThermoDatabase generates appropriate thermo data.
     """
     
     for smiles, symm, H298, S298, Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500 in self.testCases:
         Cplist = [Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500]
         species = Species(molecule=[Molecule(SMILES=smiles)])
         species.generateResonanceIsomers()
         species.molecule[0]
         thermoData = self.database.getThermoDataFromGroups(Species(molecule=[species.molecule[0]]))[0]
         molecule = species.molecule[0]
         for mol in species.molecule[1:]:
             thermoData0 = self.database.getAllThermoData(Species(molecule=[mol]))[0][0]
             for data in self.database.getAllThermoData(Species(molecule=[mol]))[1:]:
                 if data.getEnthalpy(298) < thermoData0.getEnthalpy(298):
                     thermoData0 = data
             if thermoData0.getEnthalpy(298) < thermoData.getEnthalpy(298):
                 thermoData = thermoData0
                 molecule = mol
         
         self.assertEqual(molecule.calculateSymmetryNumber(), symm)
         self.assertAlmostEqual(H298, thermoData.getEnthalpy(298) / 4184, places=1)
         self.assertAlmostEqual(S298, thermoData.getEntropy(298) / 4.184, places=1)
         for T, Cp in zip(self.Tlist, Cplist):
             self.assertAlmostEqual(Cp, thermoData.getHeatCapacity(T) / 4.184, places=1)
Пример #5
0
    def test_singlet_vs_closed_shell(self):
        adjlist_singlet = """
1 C u0 p0 c0 {2,D} {3,S} {4,S}
2 C u0 p0 c0 {1,D} {3,S} {5,S}
3 C u0 p1 c0 {1,S} {2,S}
4 H u0 p0 c0 {1,S}
5 H u0 p0 c0 {2,S}
        """

        adjlist_closed_shell = """
1 C u0 p0 c0 {2,D} {3,S} {4,S}
2 C u0 p0 c0 {1,D} {3,D}
3 C u0 p0 c0 {1,S} {2,D} {5,S}
4 H u0 p0 c0 {1,S}
5 H u0 p0 c0 {3,S}
        """

        singlet = Species(molecule=[Molecule().fromAdjacencyList(adjlist_singlet)])
        singlet.generateResonanceIsomers()
        closed_shell = Species(molecule=[Molecule().fromAdjacencyList(adjlist_closed_shell)])
        closed_shell.generateResonanceIsomers()

        singlet_aug_inchi = singlet.getAugmentedInChI()
        closed_shell_aug_inchi = closed_shell.getAugmentedInChI()
        self.assertTrue(singlet_aug_inchi != closed_shell_aug_inchi)
Пример #6
0
 def testResonaceIsomersRepresented(self):
     "Test that both resonance forms of 1-penten-3-yl are printed by __repr__"
     spec = Species().fromSMILES('C=C[CH]CC')
     spec.generateResonanceIsomers()
     exec('spec2 = {0!r}'.format(spec))
     self.assertEqual(len(spec.molecule), len(spec2.molecule))
     for i, j in zip(spec.molecule, spec2.molecule):
         self.assertTrue(i.isIsomorphic(j))
Пример #7
0
    def compare(self, adjlist, aug_inchi):
        spc = Species(molecule=[Molecule().fromAdjacencyList(adjlist)])
        spc.generateResonanceIsomers()

        ignore_prefix = r"(InChI=1+)(S*)/"

        exp = re.split(ignore_prefix, aug_inchi)[-1]
        comp = re.split(ignore_prefix, spc.getAugmentedInChI())[-1]
        self.assertEquals(exp, comp)
Пример #8
0
 def testTotalSymmetryNumber14Dimethylbenzene(self):
     """
     Test the Species.getSymmetryNumber() (total symmetry) on Cc1ccc(C)cc1
     """
     molecule = Molecule().fromSMILES("Cc1ccc(C)cc1")
     species = Species(molecule=[molecule])
     species.generateResonanceIsomers()
     symmetryNumber = species.getSymmetryNumber()
     self.assertEqual(symmetryNumber, 36)
Пример #9
0
 def testTotalSymmetryNumberToluene(self):
     """
     Test the Species.getSymmetryNumber() (total symmetry) on c1ccccc1C
     """
     molecule = Molecule().fromSMILES("c1ccccc1C")
     species = Species(molecule=[molecule])
     species.generateResonanceIsomers()
     symmetryNumber = species.getSymmetryNumber()
     self.assertEqual(symmetryNumber, 3)
Пример #10
0
def filterReactions(reactants, products, reactionList):
    """
    Remove any reactions from the given `reactionList` whose reactants do
    not involve all the given `reactants` or whose products do not involve 
    all the given `products`. This method checks both forward and reverse
    directions, and only filters out reactions that don't match either.
    """
    
    # Convert from molecules to species and generate resonance isomers.
    reactant_species = []
    for mol in reactants:
        s = Species(molecule=[mol])
        s.generateResonanceIsomers()
        reactant_species.append(s)
    reactants = reactant_species
    product_species = []
    for mol in products:
        s = Species(molecule=[mol])
        s.generateResonanceIsomers()
        product_species.append(s)
    products = product_species
    
    reactions = reactionList[:]
    
    for reaction in reactionList:
        # Forward direction
        reactants0 = [r for r in reaction.reactants]
        for reactant in reactants:
            for reactant0 in reactants0:
                if reactant.isIsomorphic(reactant0):
                    reactants0.remove(reactant0)
                    break
        products0 = [p for p in reaction.products]
        for product in products:
            for product0 in products0:
                if product.isIsomorphic(product0):
                    products0.remove(product0)
                    break
        forward = not (len(reactants0) != 0 or len(products0) != 0)
        # Reverse direction
        reactants0 = [r for r in reaction.products]
        for reactant in reactants:
            for reactant0 in reactants0:
                if reactant.isIsomorphic(reactant0):
                    reactants0.remove(reactant0)
                    break
        products0 = [p for p in reaction.reactants]
        for product in products:
            for product0 in products0:
                if product.isIsomorphic(product0):
                    products0.remove(product0)
                    break
        reverse = not (len(reactants0) != 0 or len(products0) != 0)
        if not forward and not reverse:
            reactions.remove(reaction)
    return reactions
Пример #11
0
    def test_CCCO_triplet(self):

        adjlist = """
        multiplicity 3
1 C u0 p0 c0 {2,D} {5,S} {6,S}
2 C u0 p0 c0 {1,D} {3,S} {7,S}
3 C u1 p0 c0 {2,S} {4,S} {8,S}
4 O u1 p2 c0 {3,S}
5 H u0 p0 c0 {1,S}
6 H u0 p0 c0 {1,S}
7 H u0 p0 c0 {2,S}
8 H u0 p0 c0 {3,S}
        """
        mol = Molecule().fromAdjacencyList(adjlist)
        
        spc = Species(molecule=[mol])
        spc.generateResonanceIsomers()
        aug_inchi = spc.getAugmentedInChI()

        self.assertEqual(Species(molecule=[Molecule().fromAugmentedInChI(aug_inchi)]).isIsomorphic(spc), True)
Пример #12
0
    def compare(self, inchi, u_indices=[], p_indices = []):        
        u_layer = U_LAYER_PREFIX + U_LAYER_SEPARATOR.join(map(str, u_indices)) if u_indices else None
        p_layer = P_LAYER_PREFIX + P_LAYER_SEPARATOR.join(map(str, p_indices)) if p_indices else None

        aug_inchi = compose_aug_inchi(inchi, u_layer, p_layer)

        mol = fromAugmentedInChI(Molecule(), aug_inchi)
        ConsistencyChecker.check_multiplicity(mol.getRadicalCount(), mol.multiplicity)

        for at in mol.atoms:
            ConsistencyChecker.check_partial_charge(at)
        
        spc = Species(molecule=[mol])
        spc.generateResonanceIsomers()

        ignore_prefix = r"(InChI=1+)(S*)/"
        aug_inchi_expected = re.split(ignore_prefix, aug_inchi)[-1]
        aug_inchi_computed = re.split(ignore_prefix, spc.getAugmentedInChI())[-1]
        self.assertEquals(aug_inchi_expected, aug_inchi_computed)

        return mol
Пример #13
0
 def testSymmetryNumberGeneration(self):
     """
     Test we generate symmetry numbers correctly.
     
     This uses the new thermo database to generate the H298, used 
     to select the stablest resonance isomer.
     """
     for smiles, symm, H298, S298, Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500 in self.testCases:
         species = Species(molecule=[Molecule(SMILES=smiles)])
         species.generateResonanceIsomers()
         thermoData = self.database.getThermoDataFromGroups(Species(molecule=[species.molecule[0]]))
         # pick the molecule with lowest H298
         molecule = species.molecule[0]
         for mol in species.molecule[1:]:
             thermoData0 = self.database.getAllThermoData(Species(molecule=[mol]))[0][0]
             for data in self.database.getAllThermoData(Species(molecule=[mol]))[1:]:
                 if data.getEnthalpy(298) < thermoData0.getEnthalpy(298):
                     thermoData0 = data
             if thermoData0.getEnthalpy(298) < thermoData.getEnthalpy(298):
                 thermoData = thermoData0
                 molecule = mol
         self.assertEqual(molecule.calculateSymmetryNumber(), symm, msg="Symmetry number error for {0}".format(smiles))
Пример #14
0
    def loadEntry(
        self,
        index,
        label,
        solvent,
        molecule=None,
        reference=None,
        referenceType='',
        shortDesc='',
        longDesc='',
    ):
        spc = molecule
        if molecule is not None:
            try:
                spc = Species().fromSMILES(molecule)
            except:
                logging.debug(
                    "Solvent '{0}' does not have a valid SMILES '{1}'".format(
                        label, molecule))
                try:
                    spc = Species().fromAdjacencyList(molecule)
                except:
                    logging.error(
                        "Can't understand '{0}' in solute library '{1}'".
                        format(molecule, self.name))
                    raise
            spc.generateResonanceIsomers()

        self.entries[label] = Entry(
            index=index,
            label=label,
            item=spc,
            data=solvent,
            reference=reference,
            referenceType=referenceType,
            shortDesc=shortDesc,
            longDesc=longDesc.strip(),
        )
Пример #15
0
def getReactionForEntry(entry, database):
    """
    Return a Reaction object for a given entry that uses Species instead of
    Molecules (so that we can compute the reaction thermo).
    """
    reaction = Reaction(reactants=[], products=[])
    for molecule in entry.item.reactants:
        molecule.makeHydrogensExplicit()
        reactant = Species(molecule=[molecule], label=molecule.toSMILES())
        reactant.generateResonanceIsomers()
        reactant.thermo = generateThermoData(reactant, database)
        reaction.reactants.append(reactant)
    for molecule in entry.item.products:
        molecule.makeHydrogensExplicit()
        product = Species(molecule=[molecule], label=molecule.toSMILES())
        product.generateResonanceIsomers()
        product.thermo = generateThermoData(product, database)
        reaction.products.append(product)
    
    reaction.kinetics = entry.data
    reaction.degeneracy = entry.item.degeneracy
    
    return reaction
Пример #16
0
 def testSymmetryNumberGeneration(self):
     """
     Test we generate symmetry numbers correctly.
     
     This uses the new thermo database to generate the H298, used 
     to select the stablest resonance isomer.
     """
     for smiles, symm, H298, S298, Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500 in self.testCases:
         molecule=Molecule(SMILES=smiles)
         species = Species(molecule=molecule)
         species.generateResonanceIsomers()
         thermoData = self.database.getThermoDataFromGroups(Species(molecule=[species.molecule[0]]))
         # pick the molecule with lowest H298
         molecule = species.molecule[0]
         for mol in species.molecule[1:]:
             thermoData0 = self.database.getAllThermoData(Species(molecule=[mol]))[0][0]
             for data in self.database.getAllThermoData(Species(molecule=[mol]))[1:]:
                 if data.getEnthalpy(298) < thermoData0.getEnthalpy(298):
                     thermoData0 = data
             if thermoData0.getEnthalpy(298) < thermoData.getEnthalpy(298):
                 thermoData = thermoData0
                 molecule = mol
         self.assertEqual(molecule.calculateSymmetryNumber(), symm, msg="Symmetry number error for {0}".format(smiles))
Пример #17
0
 def testOldThermoGeneration(self):
     """
     Test that the old ThermoDatabase generates relatively accurate thermo data.
     """
     for smiles, symm, H298, S298, Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500 in self.testCases:
         Cplist = [Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500]
         species = Species(molecule=[Molecule(SMILES=smiles)])
         species.generateResonanceIsomers()
         thermoData = self.oldDatabase.getThermoData(Species(molecule=[species.molecule[0]]))
         molecule = species.molecule[0]
         for mol in species.molecule[1:]:
             thermoData0 = self.oldDatabase.getAllThermoData(Species(molecule=[mol]))[0][0]
             for data in self.oldDatabase.getAllThermoData(Species(molecule=[mol]))[1:]:
                 if data.getEnthalpy(298) < thermoData0.getEnthalpy(298):
                     thermoData0 = data
             if thermoData0.getEnthalpy(298) < thermoData.getEnthalpy(298):
                 thermoData = thermoData0
                 molecule = mol
         
         self.assertAlmostEqual(H298, thermoData.getEnthalpy(298) / 4184, places=1, msg="H298 error for {0}".format(smiles))
         self.assertAlmostEqual(S298, thermoData.getEntropy(298) / 4.184, places=1, msg="S298 error for {0}".format(smiles))
         for T, Cp in zip(self.Tlist, Cplist):
             self.assertAlmostEqual(Cp, thermoData.getHeatCapacity(T) / 4.184, places=1, msg="Cp{1} error for {0}".format(smiles, T))
Пример #18
0
def convertToSpeciesObjects(reaction):
    """
    modifies a reaction holding Molecule objects to a reaction holding
    Species objects, with generated resonance isomers.
    """
    # if already species' objects, return none
    if isinstance(reaction.reactants[0], Species):
        return None
    # obtain species with all resonance isomers
    for i, mol in enumerate(reaction.reactants):
        spec = Species(molecule=[mol])
        spec.generateResonanceIsomers(keepIsomorphic=True)
        reaction.reactants[i] = spec
    for i, mol in enumerate(reaction.products):
        spec = Species(molecule=[mol])
        spec.generateResonanceIsomers(keepIsomorphic=True)
        reaction.products[i] = spec

    # convert reaction.pairs object to species
    newPairs = []
    for reactant, product in reaction.pairs:
        newPair = []
        for reactant0 in reaction.reactants:
            if reactant0.isIsomorphic(reactant):
                newPair.append(reactant0)
                break
        for product0 in reaction.products:
            if product0.isIsomorphic(product):
                newPair.append(product0)
                break
        newPairs.append(newPair)
    reaction.pairs = newPairs

    try:
        convertToSpeciesObjects(reaction.reverse)
    except AttributeError:
        pass
Пример #19
0
    def testNewThermoGeneration(self):
        """
        Test that the new ThermoDatabase generates appropriate thermo data.
        """

        for smiles, symm, H298, S298, Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500 in self.testCases:
            Cplist = [Cp300, Cp400, Cp500, Cp600, Cp800, Cp1000, Cp1500]
            species = Species(molecule=[Molecule(SMILES=smiles)])
            species.generateResonanceIsomers()
            species.molecule[0]
            thermoData = self.database.getThermoDataFromGroups(
                Species(molecule=[species.molecule[0]]))
            molecule = species.molecule[0]
            for mol in species.molecule[1:]:
                thermoData0 = self.database.getAllThermoData(
                    Species(molecule=[mol]))[0][0]
                for data in self.database.getAllThermoData(
                        Species(molecule=[mol]))[1:]:
                    if data.getEnthalpy(298) < thermoData0.getEnthalpy(298):
                        thermoData0 = data
                if thermoData0.getEnthalpy(298) < thermoData.getEnthalpy(298):
                    thermoData = thermoData0
                    molecule = mol
            self.assertAlmostEqual(H298,
                                   thermoData.getEnthalpy(298) / 4184,
                                   places=1,
                                   msg="H298 error for {0}".format(smiles))
            self.assertAlmostEqual(S298,
                                   thermoData.getEntropy(298) / 4.184,
                                   places=1,
                                   msg="S298 error for {0}".format(smiles))
            for T, Cp in zip(self.Tlist, Cplist):
                self.assertAlmostEqual(Cp,
                                       thermoData.getHeatCapacity(T) / 4.184,
                                       places=1,
                                       msg="Cp{1} error for {0}".format(
                                           smiles, T))
Пример #20
0
    def getForwardReactionForFamilyEntry(self, entry, family, groups,
                                         rxnFamily):
        """
        For a given `entry` for a reaction of the given reaction `family` (the
        string label of the family), return the reaction with transition state
        distances for the "forward" direction as defined by the reaction
        family. For families that are their own reverse, the direction the
        kinetics is given in will be preserved. If the entry contains
        functional groups for the reactants, assume that it is given in the
        forward direction and do nothing. Returns the reaction in the direction
        consistent with the reaction family template, and the matching template.
        """
        def matchSpeciesToMolecules(species, molecules):
            if len(species) == len(molecules) == 1:
                return species[0].isIsomorphic(molecules[0])
            elif len(species) == len(molecules) == 2:
                if species[0].isIsomorphic(
                        molecules[0]) and species[1].isIsomorphic(
                            molecules[1]):
                    return True
                elif species[0].isIsomorphic(
                        molecules[1]) and species[1].isIsomorphic(
                            molecules[0]):
                    return True
            return False

        reaction = None
        template = None

        # Get the indicated reaction family
        if groups is None:
            raise ValueError(
                'Invalid value "{0}" for family parameter.'.format(family))

        if all([(isinstance(reactant, Group)
                 or isinstance(reactant, LogicNode))
                for reactant in entry.item.reactants]):
            # The entry is a rate rule, containing functional groups only
            # By convention, these are always given in the forward direction and
            # have kinetics defined on a per-site basis
            reaction = Reaction(
                reactants=entry.item.reactants[:],
                products=[],
                kinetics=entry.data,
                degeneracy=1,
            )
            template = [
                groups.entries[label] for label in entry.label.split(';')
            ]

        elif (all([
                isinstance(reactant, (RMGMolecule, RMGSpecies))
                for reactant in entry.item.reactants
        ]) and all([
                isinstance(product, (RMGMolecule, RMGSpecies))
                for product in entry.item.products
        ])):
            # The entry is a real reaction, containing molecules
            # These could be defined for either the forward or reverse direction
            # and could have a reaction-path degeneracy

            reaction = Reaction(reactants=[], products=[])
            for molecule in entry.item.reactants:
                if isinstance(molecule, RMGMolecule):
                    reactant = RMGSpecies(molecule=[molecule])
                else:
                    reactant = molecule
                reactant.generateResonanceIsomers()
                reaction.reactants.append(reactant)
            for molecule in entry.item.products:
                if isinstance(molecule, RMGMolecule):
                    product = RMGSpecies(molecule=[molecule])
                else:
                    product = molecule
                product.generateResonanceIsomers()
                reaction.products.append(product)

            # Generate all possible reactions involving the reactant species
            generatedReactions = self.generateReactionsFromFamilies(
                [reactant.molecule[0] for reactant in reaction.reactants], [],
                only_families=[family],
                families=rxnFamily)

            # Remove from that set any reactions that don't produce the desired
            # reactants and products
            forward = []
            reverse = []
            for rxn in generatedReactions:
                if matchSpeciesToMolecules(
                        reaction.reactants,
                        rxn.reactants) and matchSpeciesToMolecules(
                            reaction.products, rxn.products):
                    forward.append(rxn)
                if matchSpeciesToMolecules(
                        reaction.reactants,
                        rxn.products) and matchSpeciesToMolecules(
                            reaction.products, rxn.reactants):
                    reverse.append(rxn)

            # We should now know whether the reaction is given in the forward or
            # reverse direction
            if len(forward) == 1 and len(reverse) == 0:
                # The reaction is in the forward direction, so use as-is
                reaction = forward[0]
                template = reaction.template
                # Don't forget to overwrite the estimated distances from the
                # database with the distances for this entry
                reaction.distances = entry.data
            elif len(reverse) == 1 and len(forward) == 0:
                # The reaction is in the reverse direction
                # The reaction is in the forward direction, so use as-is
                reaction = forward[0]
                template = reaction.template
                # The distances to the H atom are reversed
                reaction.distances = entry.data
                reaction.distances['d12'] = entry.data['d23']
                reaction.distances['d23'] = entry.data['d12']
            elif len(reverse) > 0 and len(forward) > 0:
                print('FAIL: Multiple reactions found for {0!r}.'.format(
                    entry.label))
            elif len(reverse) == 0 and len(forward) == 0:
                print('FAIL: No reactions found for "%s".' % (entry.label))
            else:
                print('FAIL: Unable to estimate distances for {0!r}.'.format(
                    entry.label))

        assert reaction is not None
        assert template is not None
        return reaction, template
Пример #21
0
    def getForwardReactionForFamilyEntry(self, entry, family, thermoDatabase):
        """
        For a given `entry` for a reaction of the given reaction `family` (the
        string label of the family), return the reaction with kinetics and
        degeneracy for the "forward" direction as defined by the reaction 
        family. For families that are their own reverse, the direction the
        kinetics is given in will be preserved. If the entry contains 
        functional groups for the reactants, assume that it is given in the 
        forward direction and do nothing. Returns the reaction in the direction
        consistent with the reaction family template, and the matching template.
        Note that the returned reaction will have its kinetics and degeneracy
        set appropriately.
        
        In order to reverse the reactions that are given in the reverse of the
        direction the family is defined, we need to compute the thermodynamics
        of the reactants and products. For this reason you must also pass
        the `thermoDatabase` to use to generate the thermo data.
        """
        def generateThermoData(species, thermoDatabase):
            thermoData = [thermoDatabase.getThermoData(species)]
            thermoData.sort(key=lambda x: x.getEnthalpy(298))
            return thermoData[0]

        def matchSpeciesToMolecules(species, molecules):
            if len(species) == len(molecules) == 1:
                return species[0].isIsomorphic(molecules[0])
            elif len(species) == len(molecules) == 2:
                if species[0].isIsomorphic(
                        molecules[0]) and species[1].isIsomorphic(
                            molecules[1]):
                    return True
                elif species[0].isIsomorphic(
                        molecules[1]) and species[1].isIsomorphic(
                            molecules[0]):
                    return True
            return False

        reaction = None
        template = None

        # Get the indicated reaction family
        try:
            groups = self.families[family].groups
        except KeyError:
            raise ValueError(
                'Invalid value "{0}" for family parameter.'.format(family))

        if all([(isinstance(reactant, Group)
                 or isinstance(reactant, LogicNode))
                for reactant in entry.item.reactants]):
            # The entry is a rate rule, containing functional groups only
            # By convention, these are always given in the forward direction and
            # have kinetics defined on a per-site basis
            reaction = Reaction(
                reactants=entry.item.reactants[:],
                products=[],
                kinetics=entry.data,
                degeneracy=1,
            )
            template = [
                groups.entries[label] for label in entry.label.split(';')
            ]

        elif (all([
                isinstance(reactant, Molecule)
                for reactant in entry.item.reactants
        ]) and all(
            [isinstance(product, Molecule)
             for product in entry.item.products])):
            # The entry is a real reaction, containing molecules
            # These could be defined for either the forward or reverse direction
            # and could have a reaction-path degeneracy

            reaction = Reaction(reactants=[], products=[])
            for molecule in entry.item.reactants:
                reactant = Species(molecule=[molecule])
                reactant.generateResonanceIsomers()
                reactant.thermo = generateThermoData(reactant, thermoDatabase)
                reaction.reactants.append(reactant)
            for molecule in entry.item.products:
                product = Species(molecule=[molecule])
                product.generateResonanceIsomers()
                product.thermo = generateThermoData(product, thermoDatabase)
                reaction.products.append(product)

            # Generate all possible reactions involving the reactant species
            generatedReactions = self.generateReactionsFromFamilies(
                [reactant.molecule for reactant in reaction.reactants], [],
                only_families=[family])

            # Remove from that set any reactions that don't produce the desired reactants and products
            forward = []
            reverse = []
            for rxn in generatedReactions:
                if matchSpeciesToMolecules(
                        reaction.reactants,
                        rxn.reactants) and matchSpeciesToMolecules(
                            reaction.products, rxn.products):
                    forward.append(rxn)
                if matchSpeciesToMolecules(
                        reaction.reactants,
                        rxn.products) and matchSpeciesToMolecules(
                            reaction.products, rxn.reactants):
                    reverse.append(rxn)

            # We should now know whether the reaction is given in the forward or
            # reverse direction
            if len(forward) == 1 and len(reverse) == 0:
                # The reaction is in the forward direction, so use as-is
                reaction = forward[0]
                template = reaction.template
                # Don't forget to overwrite the estimated kinetics from the database with the kinetics for this entry
                reaction.kinetics = entry.data
            elif len(reverse) == 1 and len(forward) == 0:
                # The reaction is in the reverse direction
                # First fit Arrhenius kinetics in that direction
                Tdata = 1000.0 / numpy.arange(0.5, 3.301, 0.1, numpy.float64)
                kdata = numpy.zeros_like(Tdata)
                for i in range(Tdata.shape[0]):
                    kdata[i] = entry.data.getRateCoefficient(
                        Tdata[i]) / reaction.getEquilibriumConstant(Tdata[i])
                kunits = 'm^3/(mol*s)' if len(
                    reverse[0].reactants) == 2 else 's^-1'
                kinetics = Arrhenius().fitToData(Tdata, kdata, kunits, T0=1.0)
                kinetics.Tmin = entry.data.Tmin
                kinetics.Tmax = entry.data.Tmax
                kinetics.Pmin = entry.data.Pmin
                kinetics.Pmax = entry.data.Pmax
                # Now flip the direction
                reaction = reverse[0]
                reaction.kinetics = kinetics
                template = reaction.template
            elif len(reverse) > 0 and len(forward) > 0:
                print 'FAIL: Multiple reactions found for {0!r}.'.format(
                    entry.label)
            elif len(reverse) == 0 and len(forward) == 0:
                print 'FAIL: No reactions found for "%s".' % (entry.label)
            else:
                print 'FAIL: Unable to estimate kinetics for {0!r}.'.format(
                    entry.label)

        assert reaction is not None
        assert template is not None
        return reaction, template
Пример #22
0
                break
        return rmg_mol
    else:
        return Molecule().fromSMILES(mol_string)


rxnString = os.getcwd().split('/')[-2]
r1 = fixLonePairMolecule(rxnString.split('_')[0].split('+')[0])
r2 = fixLonePairMolecule(rxnString.split('_')[0].split('+')[1])
p1 = fixLonePairMolecule(rxnString.split('_')[1])  #.split('+')[0])
#p2 = fixLonePairMolecule(rxnString.split('_')[1].split('+')[1])
rSpecies1 = Species(molecule=[r1])
rSpecies2 = Species(molecule=[r2])
pSpecies1 = Species(molecule=[p1])
#pSpecies2 = Species(molecule=[p2])
rSpecies1.generateResonanceIsomers()
rSpecies2.generateResonanceIsomers()
pSpecies1.generateResonanceIsomers()
#pSpecies2.generateResonanceIsomers()

testReaction = Reaction(reactants=[rSpecies1, rSpecies2],
                        products=[pSpecies1],
                        reversible=True)
reactionList = []
for moleculeA in rSpecies1.molecule:
    for moleculeB in rSpecies2.molecule:
        tempList = database.kinetics.generateReactionsFromFamilies(
            [moleculeA, moleculeB], [], only_families=['Silylene_Insertion'])
        for rxn0 in tempList:
            reactionList.append(rxn0)
Пример #23
0
    def getForwardReactionForFamilyEntry(self, entry, family, thermoDatabase):
        """
        For a given `entry` for a reaction of the given reaction `family` (the
        string label of the family), return the reaction with kinetics and
        degeneracy for the "forward" direction as defined by the reaction 
        family. For families that are their own reverse, the direction the
        kinetics is given in will be preserved. If the entry contains 
        functional groups for the reactants, assume that it is given in the 
        forward direction and do nothing. Returns the reaction in the direction
        consistent with the reaction family template, and the matching template.
        Note that the returned reaction will have its kinetics and degeneracy
        set appropriately.
        
        In order to reverse the reactions that are given in the reverse of the
        direction the family is defined, we need to compute the thermodynamics
        of the reactants and products. For this reason you must also pass
        the `thermoDatabase` to use to generate the thermo data.
        """

        def generateThermoData(species, thermoDatabase):
            thermoData = [thermoDatabase.getThermoData(species)]
            thermoData.sort(key=lambda x: x.getEnthalpy(298))
            return thermoData[0]
        
        def matchSpeciesToMolecules(species, molecules):
            if len(species) == len(molecules) == 1:
                return species[0].isIsomorphic(molecules[0])
            elif len(species) == len(molecules) == 2:
                if species[0].isIsomorphic(molecules[0]) and species[1].isIsomorphic(molecules[1]):
                    return True
                elif species[0].isIsomorphic(molecules[1]) and species[1].isIsomorphic(molecules[0]):
                    return True
            return False

        reaction = None; template = None

        # Get the indicated reaction family
        try:
            groups = self.families[family].groups
        except KeyError:
            raise ValueError('Invalid value "{0}" for family parameter.'.format(family))

        if all([(isinstance(reactant, Group) or isinstance(reactant, LogicNode)) for reactant in entry.item.reactants]):
            # The entry is a rate rule, containing functional groups only
            # By convention, these are always given in the forward direction and
            # have kinetics defined on a per-site basis
            reaction = Reaction(
                reactants = entry.item.reactants[:],
                products = [],
                kinetics = entry.data,
                degeneracy = 1,
            )
            template = [groups.entries[label] for label in entry.label.split(';')]

        elif (all([isinstance(reactant, Molecule) for reactant in entry.item.reactants]) and
            all([isinstance(product, Molecule) for product in entry.item.products])):
            # The entry is a real reaction, containing molecules
            # These could be defined for either the forward or reverse direction
            # and could have a reaction-path degeneracy

            reaction = Reaction(reactants=[], products=[])
            for molecule in entry.item.reactants:
                reactant = Species(molecule=[molecule])
                reactant.generateResonanceIsomers()
                reactant.thermo = generateThermoData(reactant, thermoDatabase)
                reaction.reactants.append(reactant)
            for molecule in entry.item.products:
                product = Species(molecule=[molecule])
                product.generateResonanceIsomers()
                product.thermo = generateThermoData(product, thermoDatabase)
                reaction.products.append(product)

            # Generate all possible reactions involving the reactant species
            generatedReactions = self.generateReactionsFromFamilies([reactant.molecule for reactant in reaction.reactants], [], only_families=[family])

            # Remove from that set any reactions that don't produce the desired reactants and products
            forward = []; reverse = []
            for rxn in generatedReactions:
                if matchSpeciesToMolecules(reaction.reactants, rxn.reactants) and matchSpeciesToMolecules(reaction.products, rxn.products):
                    forward.append(rxn)
                if matchSpeciesToMolecules(reaction.reactants, rxn.products) and matchSpeciesToMolecules(reaction.products, rxn.reactants):
                    reverse.append(rxn)

            # We should now know whether the reaction is given in the forward or
            # reverse direction
            if len(forward) == 1 and len(reverse) == 0:
                # The reaction is in the forward direction, so use as-is
                reaction = forward[0]
                template = reaction.template
                # Don't forget to overwrite the estimated kinetics from the database with the kinetics for this entry
                reaction.kinetics = entry.data
            elif len(reverse) == 1 and len(forward) == 0:
                # The reaction is in the reverse direction
                # First fit Arrhenius kinetics in that direction
                Tdata = 1000.0 / numpy.arange(0.5, 3.301, 0.1, numpy.float64)
                kdata = numpy.zeros_like(Tdata)
                for i in range(Tdata.shape[0]):
                    kdata[i] = entry.data.getRateCoefficient(Tdata[i]) / reaction.getEquilibriumConstant(Tdata[i])
                kunits = 'm^3/(mol*s)' if len(reverse[0].reactants) == 2 else 's^-1'
                kinetics = Arrhenius().fitToData(Tdata, kdata, kunits, T0=1.0)
                kinetics.Tmin = entry.data.Tmin
                kinetics.Tmax = entry.data.Tmax
                kinetics.Pmin = entry.data.Pmin
                kinetics.Pmax = entry.data.Pmax
                # Now flip the direction
                reaction = reverse[0]
                reaction.kinetics = kinetics
                template = reaction.template
            elif len(reverse) > 0 and len(forward) > 0:
                print 'FAIL: Multiple reactions found for {0!r}.'.format(entry.label)
            elif len(reverse) == 0 and len(forward) == 0:
                print 'FAIL: No reactions found for "%s".' % (entry.label)
            else:
                print 'FAIL: Unable to estimate kinetics for {0!r}.'.format(entry.label)

        assert reaction is not None
        assert template is not None
        return reaction, template
Пример #24
0
rmgDatabase = RMGDatabase()
rmgDatabase.load(os.path.abspath(os.path.join(os.getenv('RMGpy'), '..', 'RMG-database', 'input')), kineticsFamilies='default')
print 'Finished loading RMG Database ...'

reactionTuple = rxnList[i-1]
rxnFamily, reactionLine = reactionTuple
rxnFormula, A, n, Ea = reactionLine.split()
reactants, products = rxnFormula.split('=')
if rxnFamily in ['H_Abstraction', 'Disproportionation']:
	reactant1, reactant2 = [moleculeDict[j] for j in reactants.split('+')]
	product1, product2 = [moleculeDict[j] for j in products.split('+')]
	rSpecies1 = Species(molecule=[reactant1])
	rSpecies2 = Species(molecule=[reactant2])
	pSpecies1 = Species(molecule=[product1])
	pSpecies2 = Species(molecule=[product2])
	rSpecies1.generateResonanceIsomers()
	rSpecies2.generateResonanceIsomers()
	pSpecies1.generateResonanceIsomers()
	pSpecies2.generateResonanceIsomers()
	testReaction = Reaction(reactants=[rSpecies1, rSpecies2], products=[pSpecies1, pSpecies2], reversible=True)
	reactionList = []
	for moleculeA in rSpecies1.molecule:
		for moleculeB in rSpecies2.molecule:
			tempList = rmgDatabase.kinetics.generateReactionsFromFamilies([moleculeA, moleculeB], [], only_families=[rxnFamily])
			for rxn0 in tempList:
				reactionList.append(rxn0)
elif rxnFamily in ['intra_H_migration']:
	reactant = moleculeDict[reactants]
	product = moleculeDict[products]
	rSpecies = Species(molecule=[reactant])
	pSpecies = Species(molecule=[product])
Пример #25
0
def filterReactions(reactants, products, reactionList):
    """
    Remove any reactions from the given `reactionList` whose reactants do
    not involve all the given `reactants` or whose products do not involve 
    all the given `products`. This method checks both forward and reverse
    directions, and only filters out reactions that don't match either.
    
    reactants and products can be either molecule or species objects
    """
    
    # Convert from molecules to species and generate resonance isomers.
    reactant_species = []
    for mol in reactants:
        if isinstance(mol,Species):
            s = mol
        else:
            s = Species(molecule=[mol])
        s.generateResonanceIsomers()
        reactant_species.append(s)
    reactants = reactant_species
    product_species = []
    for mol in products:
        if isinstance(mol,Species):
            s = mol
        else:
            s = Species(molecule=[mol])
        s.generateResonanceIsomers()
        product_species.append(s)
    products = product_species
    
    reactions = reactionList[:]
    
    for reaction in reactionList:
        # Forward direction
        reactants0 = [r for r in reaction.reactants]
        for reactant in reactants:
            for reactant0 in reactants0:
                if reactant.isIsomorphic(reactant0):
                    reactants0.remove(reactant0)
                    break
        products0 = [p for p in reaction.products]
        for product in products:
            for product0 in products0:
                if product.isIsomorphic(product0):
                    products0.remove(product0)
                    break
        forward = not (len(reactants0) != 0 or len(products0) != 0)
        # Reverse direction
        reactants0 = [r for r in reaction.products]
        for reactant in reactants:
            for reactant0 in reactants0:
                if reactant.isIsomorphic(reactant0):
                    reactants0.remove(reactant0)
                    break
        products0 = [p for p in reaction.reactants]
        for product in products:
            for product0 in products0:
                if product.isIsomorphic(product0):
                    products0.remove(product0)
                    break
        reverse = not (len(reactants0) != 0 or len(products0) != 0)
        if not forward and not reverse:
            reactions.remove(reaction)
    return reactions
Пример #26
0
 def testResonanceIsomersGenerated(self):
     "Test that 1-penten-3-yl makes 2-penten-1-yl resonance isomer"
     spec = Species().fromSMILES('C=C[CH]CC')
     spec.generateResonanceIsomers()
     self.assertEquals(len(spec.molecule), 2)
     self.assertEquals(spec.molecule[1].toSMILES(), "[CH2]C=CCC")
Пример #27
0
    def testaddReverseAttribute(self):
        """
        tests that the addReverseAttribute method gets the reverse degeneracy correct
        """
        from rmgpy.data.rmg import getDB
        from rmgpy.data.kinetics.family import TemplateReaction
        adjlist = [
            '''
        multiplicity 2
        1 H u0 p0 c0 {7,S}
        2 H u0 p0 c0 {4,S}
        3 C u1 p0 c0 {5,S} {7,S} {8,S}
        4 C u0 p0 c0 {2,S} {6,S} {7,D}
        5 H u0 p0 c0 {3,S}
        6 H u0 p0 c0 {4,S}
        7 C u0 p0 c0 {1,S} {3,S} {4,D}
        8 H u0 p0 c0 {3,S}
        ''', '''
        1 C u0 p0 c0 {2,S} {4,S} {5,S} {6,S}
        2 C u0 p0 c0 i13 {1,S} {3,D} {7,S}
        3 C u0 p0 c0 {2,D} {8,S} {9,S}
        4 H u0 p0 c0 {1,S}
        5 H u0 p0 c0 {1,S}
        6 H u0 p0 c0 {1,S}
        7 H u0 p0 c0 {2,S}
        8 H u0 p0 c0 {3,S}
        9 H u0 p0 c0 {3,S}
        ''', '''
        multiplicity 2
        1 H u0 p0 c0 {7,S}
        2 H u0 p0 c0 {4,S}
        3 C u1 p0 c0 {5,S} {7,S} {8,S}
        4 C u0 p0 c0 {2,S} {6,S} {7,D}
        5 H u0 p0 c0 {3,S}
        6 H u0 p0 c0 {4,S}
        7 C u0 p0 c0 i13 {1,S} {3,S} {4,D}
        8 H u0 p0 c0 {3,S}
        ''', '''
        1 C u0 p0 c0 {2,S} {4,S} {5,S} {6,S}
        2 C u0 p0 c0 {1,S} {3,D} {7,S}
        3 C u0 p0 c0 {2,D} {8,S} {9,S}
        4 H u0 p0 c0 {1,S}
        5 H u0 p0 c0 {1,S}
        6 H u0 p0 c0 {1,S}
        7 H u0 p0 c0 {2,S}
        8 H u0 p0 c0 {3,S}
        9 H u0 p0 c0 {3,S}
        '''
        ]
        family = getDB('kinetics').families['H_Abstraction']
        r1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[0])])
        r2 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[1])])
        p1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[2])])
        p2 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[3])])
        r1.generateResonanceIsomers(keepIsomorphic=True)
        p1.generateResonanceIsomers(keepIsomorphic=True)

        rxn = TemplateReaction(reactants=[r1, r2], products=[p1, p2])

        rxn.degeneracy = family.calculateDegeneracy(rxn)
        self.assertEqual(rxn.degeneracy, 6)

        family.addReverseAttribute(rxn)

        self.assertEqual(rxn.reverse.degeneracy, 6)
Пример #28
0
 def testResonanceIsomersGenerated(self):
     "Test that 1-penten-3-yl makes 2-penten-1-yl resonance isomer"
     spec = Species().fromSMILES('C=C[CH]CC')
     spec.generateResonanceIsomers()
     self.assertEquals(len(spec.molecule), 2)
     self.assertEquals(spec.molecule[1].toSMILES(), "[CH2]C=CCC")