From db7a2b927e5b698a3475f4fb424ef88d512620bd Mon Sep 17 00:00:00 2001 From: alongd Date: Thu, 14 Mar 2019 20:40:00 -0400 Subject: [PATCH 1/3] Added a get_structure() method to Species To get the molecule list from either SMILES or adjList --- rmgpy/species.pxd | 2 ++ rmgpy/species.py | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/rmgpy/species.pxd b/rmgpy/species.pxd index 82413b0434..71d84d6468 100644 --- a/rmgpy/species.pxd +++ b/rmgpy/species.pxd @@ -96,6 +96,8 @@ cdef class Species: cpdef bint has_reactive_molecule(self) except -1 cpdef Species copy(self, bint deep=?) + + cpdef set_structure(self, str structure) ################################################################################ diff --git a/rmgpy/species.py b/rmgpy/species.py index ee58e2c262..3e7388b4b6 100644 --- a/rmgpy/species.py +++ b/rmgpy/species.py @@ -717,9 +717,27 @@ def generateEnergyTransferModel(self): alpha0 = (300*0.011962,"kJ/mol"), T0 = (300,"K"), n = 0.85, - ) + ) + + def set_structure(self, structure): + """ + Set self.molecule from `structure` which could be either a SMILES string or an adjacency list multi-line string + """ + if not self.molecule: + try: + self.molecule = [Molecule(SMILES=structure)] + except ValueError: + try: + self.molecule = [Molecule().fromAdjacencyList(structure)] + except ValueError: + logging.error("Cannot understand the given structure '{0}' of species {1}. Could not " + "interpret it as SMILES nor as adjacency list".format(structure, self.label)) + raise + self.generate_resonance_structures() + ################################################################################ + class TransitionState(): """ A chemical transition state, representing a first-order saddle point on a From f96fc9d1e95b4c734d835056ba112349692868a7 Mon Sep 17 00:00:00 2001 From: alongd Date: Thu, 14 Mar 2019 20:40:51 -0400 Subject: [PATCH 2/3] Allow cosolvents to be defined in a solvent library `item` is now a list of species (even if there's only one species of solvent) --- rmgpy/data/solvation.py | 39 +++++++++++++++++++-------------------- rmgpy/rmg/main.py | 5 +++-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/rmgpy/data/solvation.py b/rmgpy/data/solvation.py index a5a09279aa..c275babed9 100644 --- a/rmgpy/data/solvation.py +++ b/rmgpy/data/solvation.py @@ -277,28 +277,26 @@ def loadEntry(self, 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() + 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, - data = solvent, - reference = reference, - referenceType = referenceType, - shortDesc = shortDesc, - longDesc = longDesc.strip(), + index=index, + label=label, + item=spc_list, + data=solvent, + reference=reference, + referenceType=referenceType, + shortDesc=shortDesc, + longDesc=longDesc.strip(), ) def load(self, path): @@ -324,7 +322,8 @@ def getSolventStructure(self, label): Get a solvent's molecular structure as SMILES or adjacency list from its name """ return self.entries[label].item - + + class SoluteLibrary(Database): """ A class for working with a RMG solute library. Not currently used. diff --git a/rmgpy/rmg/main.py b/rmgpy/rmg/main.py index f97899e769..6cefe307de 100644 --- a/rmgpy/rmg/main.py +++ b/rmgpy/rmg/main.py @@ -524,8 +524,9 @@ def initialize(self, **kwargs): # For liquidReactor, checks whether the solvent is listed as one of the initial species. if self.solvent: - solventStructure = self.database.solvation.getSolventStructure(self.solvent) - self.database.solvation.checkSolventinInitialSpecies(self,solventStructure) + solvent_structure_list = self.database.solvation.getSolventStructure(self.solvent) + for spc in solvent_structure_list: + self.database.solvation.checkSolventinInitialSpecies(self, spc) #Check to see if user has input Singlet O2 into their input file or libraries #This constraint is special in that we only want to check it once in the input instead of every time a species is made From cd9d91afea83c623eda654534c53673e4d0a0c05 Mon Sep 17 00:00:00 2001 From: alongd Date: Thu, 14 Mar 2019 20:43:20 -0400 Subject: [PATCH 3/3] Added a cosolvent test to Solvation --- rmgpy/data/solvationTest.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/rmgpy/data/solvationTest.py b/rmgpy/data/solvationTest.py index 05f34c7afb..7b79b3ee4e 100644 --- a/rmgpy/data/solvationTest.py +++ b/rmgpy/data/solvationTest.py @@ -153,7 +153,7 @@ def testSoluteDataGenerationAmmonia(self): self.assertTrue(soluteData is not None) def testSoluteDataGenerationAmide(self): - "Test that we can obtain solute parameters via group additivity for an amide" + "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} @@ -171,7 +171,7 @@ def testSoluteDataGenerationAmide(self): self.assertTrue(soluteData is not None) def testSoluteDataGenerationCO(self): - "Test that we can obtain solute parameters via group additivity for CO." + "Test that we can obtain solute parameters via group additivity for CO." molecule=Molecule().fromAdjacencyList( """ 1 C u0 p1 c-1 {2,T} @@ -254,7 +254,7 @@ def testInitialSpecies(self): self.assertTrue(rmg.initialSpecies[0].isSolvent) def testSolventMolecule(self): - " Test we can give a proper value for the solvent molecular structure when different solvent databases are given " + """Test that we can assign a proper solvent molecular structure when different formats are given""" # solventlibrary.entries['solvent_label'].item should be the instance of Species with the solvent's molecular structure # if the solvent database contains the solvent SMILES or adjacency list. If not, then item is None @@ -267,8 +267,8 @@ def testSolventMolecule(self): # Case 2: When the solventDatabase contains the correct solvent SMILES, the item attribute is the instance of # Species with the correct solvent molecular structure solventlibrary.loadEntry(index=2, label='octane', solvent=None, molecule='CCCCCCCC') - solventSpecies = Species().fromSMILES('C(CCCCC)CC') - self.assertTrue(solventSpecies.isIsomorphic(solventlibrary.entries['octane'].item)) + solvent_species = Species().fromSMILES('C(CCCCC)CC') + self.assertTrue(solvent_species.isIsomorphic(solventlibrary.entries['octane'].item[0])) # Case 3: When the solventDatabase contains the correct solvent adjacency list, the item attribute is the instance of # the species with the correct solvent molecular structure. @@ -285,15 +285,23 @@ def testSolventMolecule(self): 8 H u0 p0 c0 {2,S} 9 H u0 p0 c0 {3,S} """) - solventSpecies = Species().fromSMILES('CCO') - self.assertTrue(solventSpecies.isIsomorphic(solventlibrary.entries['ethanol'].item)) + solvent_species = Species().fromSMILES('CCO') + self.assertTrue(solvent_species.isIsomorphic(solventlibrary.entries['ethanol'].item[0])) # Case 4: when the solventDatabase contains incorrect values for the molecule attribute, it raises Exception # This will display the SMILES Parse Error message from the external function, but ignore it. self.assertRaises(Exception, solventlibrary.loadEntry, index=4, label='benzene', solvent=None, molecule='ring') + # Case 5: when the solventDatabase contains data for co-solvents. + solventlibrary.loadEntry(index=5, label='methanol_50_water_50', solvent=None, molecule=['CO', 'O']) + solvent_species_list = [Species().fromSMILES('CO'), Species().fromSMILES('O')] + self.assertEqual(len(solventlibrary.entries['methanol_50_water_50'].item), 2) + for spc1 in solventlibrary.entries['methanol_50_water_50'].item: + self.assertTrue(any([spc1.isIsomorphic(spc2) for spc2 in solvent_species_list])) + ##################################################### + if __name__ == '__main__': suite = TestLoader().loadTestsFromTestCase(TestSoluteDatabase) TextTestRunner(verbosity=2).run(suite)