def testGenerateIsotopomers(self): """ Test that the generation of isotopomers with N isotopes works. """ from rmgpy.thermo.nasa import NASAPolynomial, NASA spc = Species().fromSMILES('CC') polynomial = NASAPolynomial(coeffs=[1.,1.,1.,1.,1.,1.,1.], Tmin=(200,'K'),Tmax=(1600,'K'),E0=(1.,'kJ/mol'), comment='made up thermo') spc.thermo = NASA(polynomials=[polynomial],Tmin=(200,'K'), Tmax=(1600,'K'),E0=(1.,'kJ/mol'), comment='made up thermo') spcs = generate_isotopomers(spc, 0) self.assertEquals(len(spcs), 0) spcs = generate_isotopomers(spc) self.assertEquals(len(spcs), 1) spcs = generate_isotopomers(spc, 2) self.assertEquals(len(spcs), 2) spcs = generate_isotopomers(spc, 3) self.assertEquals(len(spcs), 2)
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(), )
def funcSubmitGet(): """ Test if we can retrieve thermo of species after submitting some of them. """ load() spcs = [ Species().fromSMILES('C'),\ Species().fromSMILES('CC'), \ Species().fromSMILES('CCC') ] for spc in spcs: submit(spc) absent = Species().fromSMILES('[CH3]') data = absent.getThermoData() if not data: return False present = Species().fromSMILES('CC') data = present.getThermoData() if not data: return False random.shuffle(spcs) for spc in spcs: data = spc.getThermoData() if not data: return False return True
def testRemoveIsotopeForSpecies(self): """ Test that remove isotope algorithm works with Species. """ eth = Species().fromAdjacencyList( """ 1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S} 2 C u0 p0 c0 {1,S} {6,S} {7,S} {8,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 H u0 p0 c0 {2,S} 7 H u0 p0 c0 {2,S} 8 H u0 p0 c0 {2,S} """ ) ethi = Species().fromAdjacencyList( """ 1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S} 2 C u0 p0 c0 i13 {1,S} {6,S} {7,S} {8,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} 5 H u0 p0 c0 {1,S} 6 H u0 p0 c0 {2,S} 7 H u0 p0 c0 {2,S} 8 H u0 p0 c0 {2,S} """ ) stripped = remove_isotope(ethi) self.assertTrue(eth.isIsomorphic(stripped))
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
def testGetResonanceHybrid(self): """ Tests that getResonanceHybrid returns an isomorphic structure which has intermediate bond orders. This check is for C=C[CH]CC which has another resonance structure, [CH2]C=CC. When these structures are merged, the bond structure should be, C~C~CC, where '~' is a hybrid bond of order 1.5. """ spec = Species().fromSMILES('C=C[CH]CC') hybridMol = spec.getResonanceHybrid() self.assertTrue(hybridMol.toSingleBonds().isIsomorphic(spec.molecule[0].toSingleBonds())) # a rough check for intermediate bond orders expected_orders = [1,1.5] bonds = [] # ensure all bond orders are expected for atom in hybridMol.atoms: for atom2 in atom.bonds: bond = hybridMol.getBond(atom,atom2) self.assertTrue(any([bond.isOrder(otherOrder) for otherOrder in expected_orders]), 'Unexpected bond order {}'.format(bond.getOrderNum())) bonds.append(bond) # ensure all expected orders are present for expected_order in expected_orders: self.assertTrue(any([bond.isOrder(expected_order) for bond in bonds]),'No bond of order {} found'.format(expected_order))
def testCantera(self): """ Test that a Cantera Species object is created correctly. """ from rmgpy.thermo import NASA, NASAPolynomial import cantera as ct rmgSpecies = Species(label="Ar", thermo=NASA(polynomials=[NASAPolynomial(coeffs=[2.5,0,0,0,0,-745.375,4.37967], Tmin=(200,'K'), Tmax=(1000,'K')), NASAPolynomial(coeffs=[2.5,0,0,0,0,-745.375,4.37967], Tmin=(1000,'K'), Tmax=(6000,'K'))], Tmin=(200,'K'), Tmax=(6000,'K'), comment=""" Thermo library: primaryThermoLibrary """), molecule=[Molecule(SMILES="[Ar]")], transportData=TransportData(shapeIndex=0, epsilon=(1134.93,'J/mol'), sigma=(3.33,'angstrom'), dipoleMoment=(2,'De'), polarizability=(1,'angstrom^3'), rotrelaxcollnum=15.0, comment="""GRI-Mech""")) rmg_ctSpecies = rmgSpecies.toCantera(useChemkinIdentifier = True) ctSpecies = ct.Species.fromCti("""species(name=u'Ar', atoms='Ar:1', thermo=(NASA([200.00, 1000.00], [ 2.50000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, -7.45375000E+02, 4.37967000E+00]), NASA([1000.00, 6000.00], [ 2.50000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, -7.45375000E+02, 4.37967000E+00])), transport=gas_transport(geom='atom', diam=3.33, well_depth=136.501, dipole=2.0, polar=1.0, rot_relax=15.0))""") self.assertEqual(type(rmg_ctSpecies),type(ctSpecies)) self.assertEqual(rmg_ctSpecies.name, ctSpecies.name) self.assertEqual(rmg_ctSpecies.composition, ctSpecies.composition) self.assertEqual(rmg_ctSpecies.size, ctSpecies.size) self.assertEqual(type(rmg_ctSpecies.thermo), type(ctSpecies.thermo)) self.assertEqual(type(rmg_ctSpecies.transport), type(ctSpecies.transport))
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)
def retrieveSaturatedSpeciesFromList(self,species): """ Given a radical `species`, this function retrieves the saturated species objects from a list of species objects and returns the saturated species object along with a boolean that indicates if the species is not part of the model (True->not in the model, False->in the model) """ molecule = species.molecule[0] assert molecule.isRadical(), "Method only valid for radicals." saturatedStruct = molecule.copy(deep=True) saturatedStruct.saturate_radicals() for otherSpecies in self.speciesList: if otherSpecies.isIsomorphic(saturatedStruct): return otherSpecies, False #couldn't find saturated species in the model, try libraries newSpc = Species(molecule=[saturatedStruct]) thermo = self.database.thermo.getThermoDataFromLibraries(newSpc) if thermo is not None: newSpc.thermo = thermo self.speciesList.append(newSpc) return newSpc, True else: raise Exception('Could not retrieve saturated species form of {0} from the species list'.format(species))
def testTotalSymmetryNumberbute_di_yl(self): """ Test the Species.getSymmetryNumber() (total symmetry) on [CH2][CH]C=C """ species = Species().fromSMILES('[CH2][CH]C=C') symmetryNumber = species.getSymmetryNumber() self.assertEqual(symmetryNumber, 2)
def testAxisSymmetryNumberAllyl(self): """ Test the Molecule.calculateAxisSymmetryNumber() on [CH2]C=C """ spc = Species(molecule=[Molecule().fromSMILES('[CH2]C=C')]) molecule = spc.getResonanceHybrid() self.assertEqual(calculateAxisSymmetryNumber(molecule), 1)
def loadEntry(self, index, label, solvent, molecule=None, reference=None, referenceType='', shortDesc='', longDesc='', ): if molecule is not None: if not isinstance(molecule, list): molecule = [molecule] spc_list = [] for mol in molecule: spc0 = Species(label=label) spc0.set_structure(mol) spc_list.append(spc0) else: spc_list = None self.entries[label] = Entry( index=index, label=label, item=spc_list, data=solvent, reference=reference, referenceType=referenceType, shortDesc=shortDesc, longDesc=longDesc.strip(), )
def test_calculate_degeneracy_for_non_reactive_molecule(self): """ tests that the calculateDegeneracy method gets the degeneracy correct for unreactive molecules and that __generateReactions work correctly with the react_non_reactive flag set to `True`. """ from rmgpy.data.rmg import getDB from rmgpy.data.kinetics.family import TemplateReaction adjlist = [''' multiplicity 2 1 H u1 p0 c0''', ''' multiplicity 2 1 O u1 p1 c+1 {2,D} 2 N u0 p2 c-1 {1,D}''', ''' 1 O u0 p1 c+1 {2,D} {3,S} 2 N u0 p2 c-1 {1,D} 3 H u0 p0 c0 {1,S}'''] family = getDB('kinetics').families['R_Recombination'] r1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[0])]) r2 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[1])]) # r2 is not the representative structure of # NO, but it is the correct structure participating in this reaction p1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[2])]) r2.generate_resonance_structures(keep_isomorphic=True) rxn = TemplateReaction(reactants=[r1, r2], products=[p1]) rxn.degeneracy = family.calculateDegeneracy(rxn) self.assertEqual(rxn.degeneracy, 1)
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)
def toRMGSpecies(self): """ Convert to :class:`rmgpy.species.Species` object and return the object. """ adjlist = self.toAdjlist() spc = Species().fromAdjacencyList(adjlist) spc.label = '' return spc
def testGetTransportData(self): """ Test that transport data can be retrieved correctly via the getTransportData method. """ spc = Species(label="Ar", molecule=[Molecule(SMILES="[Ar]")], transportData=TransportData(shapeIndex=0, epsilon=(1134.93,'J/mol'), sigma=(3.33,'angstrom'), dipoleMoment=(2,'De'), polarizability=(1,'angstrom^3'), rotrelaxcollnum=15.0, comment="""GRI-Mech""")) self.assertTrue(spc.getTransportData() is spc.transportData)
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.generate_resonance_structures() 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(j.isIsomorphic(i), msg='i is not isomorphic with j, where i is {} and j is {}'.format(i.toSMILES(), j.toSMILES()))
def testTotalSymmetryNumberChlorobenzene(self): """ Test the Species.getSymmetryNumber() (total symmetry) on c1ccccc1Cl """ molecule = Molecule().fromSMILES('c1ccccc1Cl') species = Species(molecule=[molecule]) symmetryNumber = species.getSymmetryNumber() self.assertEqual(symmetryNumber, 2)
def testTotalSymmetryNumber14Dimethylbenzene(self): """ Test the Species.getSymmetryNumber() (total symmetry) on Cc1ccc(C)cc1 """ molecule = Molecule().fromSMILES('Cc1ccc(C)cc1') species = Species(molecule=[molecule]) symmetryNumber = species.getSymmetryNumber() self.assertEqual(symmetryNumber, 36)
def testTotalSymmetryNumberSpecialCyclic(self): """ Test the Species.getSymmetryNumber() (total symmetry) from issue # 332 """ molecule = Molecule().fromSMILES('C1(C(C(C(C(C1C2CCC2)C3CCC3)C4CCC4)C5CCC5)C6CCC6)C7CCC7') species = Species(molecule=[molecule]) symmetryNumber = species.getSymmetryNumber() self.assertEqual(symmetryNumber, 12)
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))
def testTotalSymmetryNumberAllyl(self): """ Test the Species.getSymmetryNumber() (total symmetry) on Allyl, [CH2]C=C """ molecule = Molecule().fromSMILES('[CH2]C=C') species = Species(molecule=[molecule]) symmetryNumber = species.getSymmetryNumber() self.assertEqual(symmetryNumber, 2)
def testTotalSymmetryNumberPentenyl(self): """ Test the Species.getSymmetryNumer() for C[CH]C=CC and ensures that it is differet than the molecule object """ spc = Species(molecule=[Molecule().fromSMILES('C[CH]C=CC')]) symmetryNumber = spc.getSymmetryNumber() self.assertEqual(symmetryNumber, 18, 'the symmetry number for C[CH]C=CC is 18, but RMG returned {}'.format(symmetryNumber))
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)
def testTotalSymmetryNumberPhenoxyKecle(self): """ Test the Species.getSymmetryNumber() (total symmetry) on c1ccccc1[O] using kecle structure """ molecule = Molecule().fromSMILES('c1ccccc1[O]') species = Species(molecule=[molecule]) symmetryNumber = species.getSymmetryNumber() self.assertEqual(symmetryNumber, 2)
def testTotalSymmetryNumber12Dimethylbenzene(self): """ Test the Species.getSymmetryNumber() (total symmetry) on Cc1ccccc1C """ molecule = Molecule().fromSMILES("Cc1ccccc1C") species = Species(molecule=[molecule]) species.generateResonanceIsomers() symmetryNumber = species.getSymmetryNumber() self.assertEqual(symmetryNumber, 18)
def testDrawNonStandardBonds(self): spec = Species().fromSMILES('[CH2]C=C[CH2]') hybrid = spec.getResonanceHybrid() try: from cairocffi import PDFSurface except ImportError: from cairo import PDFSurface surface, cr, (xoff, yoff, width, height) = self.drawer.draw(hybrid, format='pdf') self.assertIsInstance(surface, PDFSurface)
def testSpeciesSymmetryNumberIsNotMoleculeSymmetryNumber(self): """ Tests that the species symmetry number can be different from the molecule symmetry number This molecule's resonance isomer hybrid should return more symmetry than the base molecule object. """ molecule = Molecule().fromSMILES('C[CH]C=CC') species = Species(molecule=[molecule]) self.assertEqual(molecule.getSymmetryNumber() * 2, species.getSymmetryNumber())
def testAtomSymmetryNumberAllyl(self): """ Test the Molecule.calculateAtomSymmetryNumber() on [CH2]C=C """ spc = Species(molecule=[Molecule().fromSMILES('[CH2]C=C')]) molecule = spc.getResonanceHybrid() symmetryNumber = 1 for atom in molecule.atoms: if not molecule.isAtomInCycle(atom): symmetryNumber *= calculateAtomSymmetryNumber(molecule, atom) self.assertEqual(symmetryNumber, 2)
def testBondSymmetryNumberAllyl(self): """ Test the Molecule.calculateBondSymmetryNumber() on [CH2]C=C """ spc = Species(molecule=[Molecule().fromSMILES('[CH2]C=C')]) molecule = spc.getResonanceHybrid() symmetryNumber = 1 for atom1 in molecule.atoms: for atom2 in atom1.bonds: if molecule.atoms.index(atom1) < molecule.atoms.index(atom2): symmetryNumber *= calculateBondSymmetryNumber(molecule, atom1, atom2) self.assertEqual(symmetryNumber, 1)
def testSoluteDataGenerationAmide(self): "Test that we can obtain solute parameters via group additivity for an amide" molecule = Molecule().fromAdjacencyList(""" 1 N u0 p1 {2,S} {3,S} {4,S} 2 H u0 {1,S} 3 C u0 {1,S} {6,S} {7,S} {8,S} 4 C u0 {1,S} {5,D} {9,S} 5 O u0 p2 {4,D} 6 H u0 {3,S} 7 H u0 {3,S} 8 H u0 {3,S} 9 H u0 {4,S} """) species = Species(molecule=[molecule]) soluteData = self.database.getSoluteDataFromGroups(species) self.assertTrue(soluteData is not None)
def testSoluteLibrary(self): "Test we can obtain solute parameters from a library" species = Species(molecule=[ Molecule(SMILES='COC=O') ]) #methyl formate - we know this is in the solute library libraryData = self.database.getSoluteDataFromLibrary( species, self.database.libraries['solute']) self.assertEqual(len(libraryData), 3) soluteData = self.database.getSoluteData(species) self.assertTrue(isinstance(soluteData, SoluteData)) S = soluteData.S self.assertEqual(S, 0.68) self.assertTrue(soluteData.V is not None)
def test_rmg_reaction_to_str(self): """Test the rmg_reaction_to_str() method and the reaction label generated""" spc1 = Species().fromSMILES(str('CON=O')) spc1.label = str('CONO') spc2 = Species().fromSMILES(str('C[N+](=O)[O-]')) spc2.label = str('CNO2') rmg_reaction = Reaction(reactants=[spc1], products=[spc2]) rxn = ARCReaction(rmg_reaction=rmg_reaction) rxn_str = rxn.rmg_reaction_to_str() self.assertEqual(rxn_str, 'CON=O <=> [O-][N+](=O)C') self.assertEqual(rxn.label, 'CONO <=> CNO2')
def test_joback_on_benzene_bonds(self): """Test Joback doesn't crash on Cb desription of benzene""" species = Species().from_adjacency_list(""" 1 C u0 p0 {2,B} {6,B} {7,S} 2 C u0 p0 {1,B} {3,B} {8,S} 3 C u0 p0 {2,B} {4,B} {9,S} 4 C u0 p0 {3,B} {5,B} {10,S} 5 C u0 p0 {4,B} {6,B} {11,S} 6 C u0 p0 {1,B} {5,B} {12,S} 7 H u0 p0 {1,S} 8 H u0 p0 {2,S} 9 H u0 p0 {3,S} 10 H u0 p0 {4,S} 11 H u0 p0 {5,S} 12 H u0 p0 {6,S} """) transport_data, blank, blank2 = self.database.get_transport_properties_via_group_estimates(species) self.assertIsNotNone(transport_data)
def setUpClass(cls): """ A method that is run before all unit tests in this class. """ cls.maxDiff = None # Method 1: RMG Species object (here by SMILES) cls.spc1_rmg = Species(molecule=[Molecule().fromSMILES(str('C=C[O]'))]) # delocalized radical + amine cls.spc1_rmg.label = str('vinoxy') cls.spc1 = ARCSpecies(rmg_species=cls.spc1_rmg) # Method 2: ARCSpecies object by XYZ (also give SMILES for thermo BAC) oh_xyz = str("""O 0.00000000 0.00000000 -0.12002167 H 0.00000000 0.00000000 0.85098324""") cls.spc2 = ARCSpecies(label=str('OH'), xyz=oh_xyz, smiles=str('[OH]'), multiplicity=2, charge=0) # Method 3: ARCSpecies object by SMILES cls.spc3 = ARCSpecies(label=str('methylamine'), smiles=str('CN'), multiplicity=1, charge=0) # Method 4: ARCSpecies object by RMG Molecule object mol4 = Molecule().fromSMILES(str('C=CC')) cls.spc4 = ARCSpecies(label=str('propene'), mol=mol4, multiplicity=1, charge=0) # Method 5: ARCSpecies by AdjacencyList (to generate AdjLists, see https://rmg.mit.edu/molecule_search) n2h4_adj = str("""1 N u0 p1 c0 {2,S} {3,S} {4,S} 2 N u0 p1 c0 {1,S} {5,S} {6,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} 5 H u0 p0 c0 {2,S} 6 H u0 p0 c0 {2,S}""") cls.spc5 = ARCSpecies(label=str('N2H4'), adjlist=n2h4_adj, multiplicity=1, charge=0) n3_xyz = str("""N -1.1997440839 -0.1610052059 0.0274738287 H -1.4016624407 -0.6229695533 -0.8487034080 H -0.0000018759 1.2861082773 0.5926077870 N 0.0000008520 0.5651072858 -0.1124621525 H -1.1294692206 -0.8709078271 0.7537518889 N 1.1997613019 -0.1609980472 0.0274604887 H 1.1294795781 -0.8708998550 0.7537444446 H 1.4015274689 -0.6230592706 -0.8487058662""") cls.spc6 = ARCSpecies(label=str('N3'), xyz=n3_xyz, multiplicity=1, charge=0, smiles=str('NNN')) xyz1 = os.path.join(arc_path, 'arc', 'testing', 'xyz', 'AIBN.gjf') cls.spc7 = ARCSpecies(label='AIBN', smiles=str('N#CC(C)(C)N=NC(C)(C)C#N'), xyz=xyz1)
def testJoback(self): #values calculate from joback's estimations self.testCases = [ ['acetone', 'CC(=O)C', Length(5.36421, 'angstroms'), Energy(3.20446, 'kJ/mol'), "Epsilon & sigma estimated with Tc=500.53 K, Pc=47.11 bar (from Joback method)"], ['cyclopenta-1,2-diene', 'C1=C=CCC1', None, None, None], # not sure what to expect, we just want to make sure it doesn't crash ['benzene', 'c1ccccc1', None, None, None], ] for name, smiles, sigma, epsilon, comment in self.testCases: molecule=Molecule(SMILES=smiles) species = Species(molecule=[molecule]) transportData, blank, blank2 = self.transportdb.getTransportPropertiesViaGroupEstimates(species) # check Joback worked. # If we don't know what to expect, don't check (just make sure we didn't crash) if comment: self.assertTrue(transportData.comment == comment) if sigma: self.assertAlmostEqual(transportData.sigma.value_si * 1e10, sigma.value_si * 1e10, 4) if epsilon: self.assertAlmostEqual(transportData.epsilon.value_si, epsilon.value_si, 1)
def test_specifying_absolute_file_paths(self): """Test specifying absolute file paths of statmech files""" h2o2_input = """#!/usr/bin/env python # -*- coding: utf-8 -*- bonds = {{'H-O': 2, 'O-O': 1}} externalSymmetry = 2 spinMultiplicity = 1 opticalIsomers = 1 energy = {{'b3lyp/6-311+g(3df,2p)': Log('{energy}')}} geometry = Log('{freq}') frequencies = Log('{freq}') rotors = [HinderedRotor(scanLog=Log('{scan}'), pivots=[1, 2], top=[1, 3], symmetry=1, fit='fourier')] """ abs_arkane_path = os.path.abspath(os.path.dirname( __file__)) # this is the absolute path to `.../RMG-Py/arkane` energy_path = os.path.join('arkane', 'data', 'H2O2', 'sp_a19032.out') freq_path = os.path.join('arkane', 'data', 'H2O2', 'freq_a19031.out') scan_path = os.path.join('arkane', 'data', 'H2O2', 'scan_a19034.out') h2o2_input = h2o2_input.format(energy=energy_path, freq=freq_path, scan=scan_path) h2o2_path = os.path.join(abs_arkane_path, 'data', 'H2O2', 'H2O2.py') if not os.path.exists(os.path.dirname(h2o2_path)): os.makedirs(os.path.dirname(h2o2_path)) with open(h2o2_path, 'w') as f: f.write(h2o2_input) h2o2 = Species(label='H2O2', smiles='OO') self.assertIsNone(h2o2.conformer) statmech_job = StatMechJob(species=h2o2, path=h2o2_path) statmech_job.level_of_theory = LevelOfTheory('b3lyp', '6-311+g(3df,2p)') statmech_job.load(pdep=False, plot=False) self.assertAlmostEqual(h2o2.conformer.E0.value_si, -146031.49933673252) os.remove(h2o2_path)
def testJobackOnBenzeneBonds(self): """Test Joback doesn't crash on Cb desription of benzene""" species = Species().fromAdjacencyList(""" 1 C u0 p0 {2,B} {6,B} {7,S} 2 C u0 p0 {1,B} {3,B} {8,S} 3 C u0 p0 {2,B} {4,B} {9,S} 4 C u0 p0 {3,B} {5,B} {10,S} 5 C u0 p0 {4,B} {6,B} {11,S} 6 C u0 p0 {1,B} {5,B} {12,S} 7 H u0 p0 {1,S} 8 H u0 p0 {2,S} 9 H u0 p0 {3,S} 10 H u0 p0 {4,S} 11 H u0 p0 {5,S} 12 H u0 p0 {6,S} """) transportData, blank, blank2 = self.database.getTransportPropertiesViaGroupEstimates( species) self.assertIsNotNone(transportData)
def combine_spc_list(spc_list1, spc_list2, same_source=True, resonance=True): """ Combine two species list used in ARC input files Args: spc_list1 (list): One of the list containing species info for ARC input files spc_list2 (list): The other list same_source (bool): If two lists are generated using the same set of chemkin file and species dictionary resonance (bool): Generate resonance structures when checking isomorphism Returns: spc_list (list): A list contains all of the species in spc_list1 and spc_list2 """ # If same source, then just compare the label if same_source: spc_list = spc_list1 + spc_list2 spc_list = list(set(spc_list)) # If not same source, compare the structure else: spc_list = list() for spc in spc_list1: if 'smiles' in spc.keys(): spc_list.append(Species().from_smiles(spc['smiles'])) elif 'adjlist' in spc.keys(): spc_list.append(Species().from_adjacency_list(spc['adjlist'])) for spc in spc_list2: if 'smiles' in spc.keys(): species = Species().from_smiles(spc['smiles']) elif 'adjlist' in spc.keys(): species = Species().from_adjacency_list(spc['adjlist']) if resonance: species.generate_resonance_structures() for species1 in spc_list: if species1.is_isomorphic(species): break else: spc_list.append(spc) return spc_list
def setUpClass(self): """A function that is run ONCE before all unit tests in this class.""" self.database = TransportDatabase() self.database.load(os.path.join(settings['database.directory'], 'transport'), ['GRI-Mech', 'PrimaryTransportLibrary']) self.speciesList = [ Species().from_smiles('C'), Species().from_smiles('CCCC'), Species().from_smiles('O'), Species().from_smiles('[CH3]'), Species().from_smiles('[OH]'), Species().from_smiles('c1ccccc1'), ]
def test_joback(self): """Test transport property estimation via Joback groups.""" self.testCases = [ ['acetone', 'CC(=O)C', Length(5.36421, 'angstroms'), Energy(3.20446, 'kJ/mol'), "Epsilon & sigma estimated with Tc=500.53 K, Pc=47.11 bar (from Joback method)"], ['cyclopenta-1,2-diene', 'C1=C=CCC1', None, None, None], # not sure what to expect, we just want to make sure it doesn't crash ['benzene', 'c1ccccc1', None, None, None], ] # values calculate from joback's estimations for name, smiles, sigma, epsilon, comment in self.testCases: species = Species().from_smiles(smiles) transport_data, blank, blank2 = self.database.get_transport_properties_via_group_estimates(species) # check Joback worked. # If we don't know what to expect, don't check (just make sure we didn't crash) if comment: self.assertTrue(transport_data.comment == comment) if sigma: self.assertAlmostEqual(transport_data.sigma.value_si * 1e10, sigma.value_si * 1e10, 4) if epsilon: self.assertAlmostEqual(transport_data.epsilon.value_si, epsilon.value_si, 1)
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]) if not reaction.isForward: spec.generateResonanceIsomers(keepIsomorphic=True) reaction.reactants[i] = spec for i, mol in enumerate(reaction.products): spec = Species(molecule=[mol]) if reaction.isForward: 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
def save_kinetics_lib(rxn_list, path, name, lib_long_desc): """ Save an RMG kinetics library of all reactions in `rxn_list` in the supplied `path` `rxn_list` is a list of ARCReaction objects `name` is the library's name (or project's name) `long_desc` is a multiline string with level of theory description """ entries = dict() if rxn_list: for i, rxn in enumerate(rxn_list): if rxn.kinetics is not None: if len(rxn.rmg_reaction.reactants): reactants = rxn.rmg_reaction.reactants products = rxn.rmg_reaction.products elif rxn.r_species.mol_list is not None: reactants = [Species(molecule=arc_spc.mol_list) for arc_spc in rxn.r_species] products = [Species(molecule=arc_spc.mol_list) for arc_spc in rxn.p_species] elif rxn.r_species.mol is not None: reactants = [Species(molecule=[arc_spc.mol]) for arc_spc in rxn.r_species] products = [Species(molecule=[arc_spc.mol]) for arc_spc in rxn.p_species] else: reactants = [Species(molecule=[arc_spc.xyz_mol]) for arc_spc in rxn.r_species] products = [Species(molecule=[arc_spc.xyz_mol]) for arc_spc in rxn.p_species] rxn.rmg_reaction.reactants = reactants rxn.rmg_reaction.products = products entry = Entry( index=i, item=rxn.rmg_reaction, data=rxn.kinetics, label=rxn.label) rxn.ts_species.make_ts_report() entry.longDesc = rxn.ts_species.ts_report + '\n\nOptimized TS geometry:\n' + rxn.ts_species.final_xyz rxn.rmg_reaction.kinetics = rxn.kinetics rxn.rmg_reaction.kinetics.comment = str('') entries[i+1] = entry else: logging.warning('Reaction {0} did not contain any kinetic data and was omitted from the kinetics' ' library.'.format(rxn.label)) kinetics_library = KineticsLibrary(name=name, longDesc=lib_long_desc, autoGenerated=True) kinetics_library.entries = entries lib_path = os.path.join(path, 'kinetics', '') if os.path.exists(lib_path): shutil.rmtree(lib_path) try: os.makedirs(lib_path) except OSError: pass kinetics_library.save(os.path.join(lib_path, 'reactions.py')) kinetics_library.saveDictionary(os.path.join(lib_path, 'dictionary.txt'))
def testJobackOnBenzeneBonds(self): "Test Joback doesn't crash on Cb desription of beneze" adjlist = """ 1 C u0 p0 {2,D} {6,S} {7,S} 2 C u0 p0 {1,D} {3,S} {8,S} 3 C u0 p0 {2,S} {4,D} {9,S} 4 C u0 p0 {3,D} {5,S} {10,S} 5 C u0 p0 {4,S} {6,D} {11,S} 6 C u0 p0 {1,S} {5,D} {12,S} 7 H u0 p0 {1,S} 8 H u0 p0 {2,S} 9 H u0 p0 {3,S} 10 H u0 p0 {4,S} 11 H u0 p0 {5,S} 12 H u0 p0 {6,S} """ m = Molecule().fromAdjacencyList(adjlist) species = Species(molecule=[m]) transportData, blank, blank2 = self.transportdb.getTransportPropertiesViaGroupEstimates(species) self.assertIsNotNone(transportData)
def testMcGowan(self): "Test we can calculate and set the McGowan volume for species containing H,C,O,N or S" self.testCases = [ ['CCCCCCCC', 1.2358], #n-octane, in library ['C(CO)O', 0.5078], #ethylene glycol ['CC#N', 0.4042], #acetonitrile ['CCS', 0.5539] #ethanethiol ] for smiles, volume in self.testCases: species = Species(molecule=[Molecule(SMILES=smiles)]) soluteData = self.database.getSoluteData(species) soluteData.setMcGowanVolume( species) # even if it was found in library, recalculate self.assertTrue( soluteData.V is not None ) # so if it wasn't found in library, we should have calculated it self.assertAlmostEqual( soluteData.V, volume ) # the volume is what we expect given the atoms and bonds
def testDeflateReaction(self): """ Test if the deflateReaction function works. """ molA = Molecule().fromSMILES('[OH]') molB = Molecule().fromSMILES('CC') molC = Molecule().fromSMILES('[CH3]') reactants = [molA, molB] # both reactants were already part of the core: reactantIndices = [1, 2] molDict = {molA: 1, molB: 2} rxn = Reaction(reactants=[molA, molB], products=[molC], pairs=[(molA, molC), (molB, molC)]) deflateReaction(rxn, molDict) for spc, t in zip(rxn.reactants, [int, int]): self.assertTrue(isinstance(spc, t)) self.assertEquals(rxn.reactants, reactantIndices) for spc in rxn.products: self.assertTrue(isinstance(spc, Species)) # one of the reactants was not yet part of the core: reactantIndices = [-1, 2] molDict = {molA: Species(molecule=[molA]), molB: 2} rxn = Reaction(reactants=[molA, molB], products=[molC], pairs=[(molA, molC), (molB, molC)]) deflateReaction(rxn, molDict) for spc, t in zip(rxn.reactants, [Species, int]): self.assertTrue(isinstance(spc, t)) for spc in rxn.products: self.assertTrue(isinstance(spc, Species))
def test_get_kinetic_isotope_effect_simple(self): reactant_pair = [Species().from_smiles("C"), Species().from_smiles("[H]")] product_pair = [Species().from_smiles("[H][H]"), Species().from_smiles("[CH3]")] rxn_unlabeled = TemplateReaction(reactants=reactant_pair, products=product_pair, family='H_Abstraction', kinetics=Arrhenius(A=(1e5, 'cm^3/(mol*s)'), Ea=(0, 'J/mol'))) rxn_labeled = TemplateReaction(reactants=[ Species().from_adjacency_list(""" 1 C u0 p0 c0 i13 {2,S} {3,S} {4,S} {5,S} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} 5 H u0 p0 c0 {1,S} """), Species().from_adjacency_list(""" multiplicity 2 1 H u1 p0 c0 """)], products=[ Species().from_adjacency_list(""" 1 H u0 p0 c0 {2,S} 2 H u0 p0 c0 {1,S} """), Species().from_adjacency_list(""" multiplicity 2 1 C u1 p0 c0 i13 {2,S} {3,S} {4,S} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} 4 H u0 p0 c0 {1,S} """)], family='H_Abstraction', kinetics=Arrhenius(A=(1e5, 'cm^3/(mol*s)'), Ea=(0, 'J/mol'))) rxn_cluster = [[rxn_labeled, rxn_unlabeled]] apply_kinetic_isotope_effect_simple(rxn_cluster, self.database.kinetics) expected_kie = ((1 / 1.008 + 1 / (13.01 + 1.008)) / (1 / 1.008 + 1 / (12.01 + 1.008))) ** 0.5 self.assertAlmostEqual(rxn_cluster[0][0].kinetics.A.value, 1e5 * expected_kie, places=-1)
def deflateReaction(rxn, molDict): """ This function deflates a single reaction, and uses the provided dictionary to populate reactants/products/pairs with integer indices, if possible. If the Molecule object could not be found in the dictionary, a new dictionary entry is created, creating a new Species object as the value for the entry. The reactants/products/pairs of both the forward and reverse reaction object are populated with the value of the dictionary, either an integer index, or either a Species object. """ for mol in itertools.chain(rxn.reactants, rxn.products): if not mol in molDict: molDict[mol] = Species(molecule=[mol]) rxn.reactants = [molDict[mol] for mol in rxn.reactants] rxn.products = [molDict[mol] for mol in rxn.products] rxn.pairs = [(molDict[reactant], molDict[product]) for reactant, product in rxn.pairs]
def create_species_from_smiles(smiles_dictionary): """ Creates a dictionary with user names as keys and specie objects as values =========================== ======================================================================= Input Description =========================== ======================================================================= smiles_dictionary A dictionary with user names as keys and SMILES strings as values =================================================================================================== =========================== ======================================================================= Output Description =========================== ======================================================================= user_species_dictionary A dictionary with user names as keys and species objects as values =================================================================================================== """ user_species_dictionary = {} for (user_name, smiles_string) in smiles_dictionary.iteritems(): user_species_dictionary[user_name] = Species( label=user_name).fromSMILES(smiles_string) return user_species_dictionary
def test_mark_duplicate_reactions(self): """Test that we can properly mark duplicate reactions for Chemkin.""" s1 = Species().from_smiles('CC') s2 = Species().from_smiles('[CH3]') s3 = Species().from_smiles('[OH]') s4 = Species().from_smiles('C[CH2]') s5 = Species().from_smiles('O') s6 = Species().from_smiles('[H]') # Try initializing with duplicate=False reaction_list = [ Reaction(reactants=[s1], products=[s2, s2], duplicate=False, kinetics=Arrhenius()), Reaction(reactants=[s1], products=[s2, s2], duplicate=False, kinetics=Arrhenius()), Reaction(reactants=[s1, s3], products=[s4, s5], duplicate=False, kinetics=Arrhenius()), Reaction(reactants=[s1, s3], products=[s4, s5], duplicate=False, kinetics=Chebyshev()), Reaction(reactants=[s1], products=[s4, s6], duplicate=False, kinetics=Arrhenius(), reversible=False), Reaction(reactants=[s1], products=[s4, s6], duplicate=False, kinetics=Arrhenius(), reversible=False), Reaction(reactants=[s5], products=[s3, s6], duplicate=False, kinetics=Arrhenius(), reversible=False), Reaction(reactants=[s3, s6], products=[s5], duplicate=False, kinetics=Arrhenius(), reversible=False), ] expected_flags = [True, True, False, False, True, True, False, False] mark_duplicate_reactions(reaction_list) duplicate_flags = [rxn.duplicate for rxn in reaction_list] self.assertEqual(duplicate_flags, expected_flags) # Try initializing with duplicate=True reaction_list = [ Reaction(reactants=[s1], products=[s2, s2], duplicate=True, kinetics=Arrhenius()), Reaction(reactants=[s1], products=[s2, s2], duplicate=True, kinetics=Arrhenius()), Reaction(reactants=[s1, s3], products=[s4, s5], duplicate=True, kinetics=Arrhenius()), Reaction(reactants=[s1, s3], products=[s4, s5], duplicate=True, kinetics=Chebyshev()), Reaction(reactants=[s1], products=[s4, s6], duplicate=True, kinetics=Arrhenius(), reversible=False), Reaction(reactants=[s1], products=[s4, s6], duplicate=True, kinetics=Arrhenius(), reversible=False), Reaction(reactants=[s5], products=[s3, s6], duplicate=True, kinetics=Arrhenius(), reversible=False), Reaction(reactants=[s3, s6], products=[s5], duplicate=True, kinetics=Arrhenius(), reversible=False), ] mark_duplicate_reactions(reaction_list) duplicate_flags = [rxn.duplicate for rxn in reaction_list] self.assertEqual(duplicate_flags, expected_flags)
def testCorrectionGeneration(self): "Test we can estimate solvation thermochemistry." self.testCases = [ # solventName, soluteName, soluteSMILES, Hsolv, Gsolv ['water', 'acetic acid', 'C(C)(=O)O', -56500, -6700 * 4.184], [ 'water', 'naphthalene', 'C1=CC=CC2=CC=CC=C12', -42800, -2390 * 4.184 ], ['1-octanol', 'octane', 'CCCCCCCC', -40080, -4180 * 4.184], ['1-octanol', 'tetrahydrofuran', 'C1CCOC1', -28320, -3930 * 4.184], ['benzene', 'toluene', 'C1(=CC=CC=C1)C', -37660, -5320 * 4.184], ['benzene', '1,4-dioxane', 'C1COCCO1', -39030, -5210 * 4.184] ] for solventName, soluteName, smiles, H, G in self.testCases: species = Species(molecule=[Molecule(SMILES=smiles)]) soluteData = self.database.getSoluteData(species) solventData = self.database.getSolventData(solventName) solvationCorrection = self.database.getSolvationCorrection( soluteData, solventData) self.assertAlmostEqual( solvationCorrection.enthalpy / 10000., H / 10000., 0, msg= "Solvation enthalpy discrepancy ({2:.0f}!={3:.0f}) for {0} in {1}" .format(soluteName, solventName, solvationCorrection.enthalpy, H)) #0 decimal place, in 10kJ. self.assertAlmostEqual( solvationCorrection.gibbs / 10000., G / 10000., 0, msg= "Solvation Gibbs free energy discrepancy ({2:.0f}!={3:.0f}) for {0} in {1}" .format(soluteName, solventName, solvationCorrection.gibbs, G))
def test_singlet_vs_triplet(self): adjlist_singlet = """ 1 C u0 p1 c0 {2,S} {3,S} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} """ adjlist_triplet = """ multiplicity 3 1 C u2 p0 c0 {2,S} {3,S} 2 H u0 p0 c0 {1,S} 3 H u0 p0 c0 {1,S} """ singlet = Species(molecule=[Molecule().from_adjacency_list(adjlist_singlet)]) triplet = Species(molecule=[Molecule().from_adjacency_list(adjlist_triplet)]) singlet_aug_inchi = singlet.get_augmented_inchi() triplet_aug_inchi = triplet.get_augmented_inchi() self.assertTrue(singlet_aug_inchi != triplet_aug_inchi)
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))
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))
def setUpClass(cls): """ A method that is run before all unit tests in this class. """ cls.maxDiff = None spc1 = Species().fromSMILES(str('CON=O')) spc1.label = str('CONO') spc2 = Species().fromSMILES(str('C[N+](=O)[O-]')) spc2.label = str('CNO2') rmg_reaction = Reaction(reactants=[spc1], products=[spc2]) cls.tsg1 = TSGuess(rmg_reaction=rmg_reaction, method='AutoTST', family='H_Abstraction') xyz = """N 0.9177905887 0.5194617797 0.0000000000 H 1.8140204898 1.0381941417 0.0000000000 H -0.4763167868 0.7509348722 0.0000000000 N 0.9992350860 -0.7048575683 0.0000000000 N -1.4430010939 0.0274543367 0.0000000000 H -0.6371484821 -0.7497769134 0.0000000000 H -2.0093636431 0.0331190314 -0.8327683174 H -2.0093636431 0.0331190314 0.8327683174""" cls.tsg2 = TSGuess(xyz=xyz)
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().from_adjacency_list(adjlist) spc = Species(molecule=[mol]) spc.generate_resonance_structures() aug_inchi = spc.get_augmented_inchi() self.assertEqual(Species(molecule=[Molecule().from_augmented_inchi(aug_inchi)]).is_isomorphic(spc), True)
def test_add_atom_labels_for_reaction_2(self): """Test that addAtomLabelsForReaction can identify reactions with identical references The molecule [CH]=C=C has resonance in this reaction""" from rmgpy.data.rmg import getDB s1 = Species().fromSMILES('C=C=C') s2 = Species().fromSMILES('C=C=[CH]') s3 = Species().fromSMILES('C#CC') s2.generate_resonance_structures() reactants = [s1, s2] products = [s2, s3] reaction = TemplateReaction(reactants=reactants, products=products, family='H_Abstraction') family = getDB('kinetics').families['H_Abstraction'] print reaction.reactants print reaction.products family.addAtomLabelsForReaction(reaction, output_with_resonance=False) # test that the reaction has labels found_labels = [] for species in reaction.reactants: for atom in species.molecule[0].atoms: if atom.label != '': found_labels.append(atom.label) self.assertEqual( len(found_labels), 3, 'wrong number of labels found {0}'.format(found_labels)) self.assertIn('*1', found_labels) self.assertIn('*2', found_labels) self.assertIn('*3', found_labels) # test for the products too found_labels = [] for species in reaction.products: for atom in species.molecule[0].atoms: if atom.label != '': found_labels.append(atom.label) self.assertEqual(len(found_labels), 3) self.assertIn('*1', found_labels) self.assertIn('*2', found_labels) self.assertIn('*3', found_labels)
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)
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.generate_resonance_structures() self.entries[label] = Entry( index=index, label=label, item=spc, data=solvent, reference=reference, referenceType=referenceType, shortDesc=shortDesc, longDesc=longDesc.strip(), )
def species_from_spc_info( spc: dict, resonance: bool = True, ) -> Optional[Species]: """ Generate a RMG Species from species info. Args: spc (dict): A single species info contains the species geom info. resonance (bool): Whether generate resonance geom in the species dictionary. Returns: Species: The Species instance from spc. """ label = spc['label'] if 'adjlist' in spc: return Species(label=label).from_adjacency_list(spc['adjlist']) elif 'smiles' in spc: return Species(label=label).from_smiles(spc['smiles']) elif 'xyz' in spc: species = Species(label=label) species.set_structure(xyz_to_mol(spc['xyz']).to_smiles()) return species