def convertPrIMe(family): print 'Loading kinetics families...' database = RMGDatabase() database.kinetics = KineticsDatabase() database.kinetics.loadFamilies('input/kinetics/families') database.loadForbiddenStructures('input/forbiddenStructures.py') for depository in database.kinetics.families[family].depositories: if depository.label == '{0}/PrIMe'.format(family): break else: raise Exception( 'Could not find PrIMe depository in {0} family.'.format(family)) entries = [] print 'Determining unique list of reactions...' for entry0 in depository.entries.values(): for entry in entries: if entry.item.isIsomorphic(entry0.item): break else: entries.append(entry0) print 'Found {0:d} unique reactions out of {1:d} entries.'.format( len(entries), len(depository.entries)) print 'Sorting unique reactions...' entries.sort(key=lambda entry: sum([ 1 for r in entry.item.reactants for a in r.atoms if a.isNonHydrogen() ])) print 'Saving reactions...' for index, entry in enumerate(entries): label = entry.label reaction = entry.item # Determine degeneracy in both directions reactions = database.kinetics.generateReactionsFromFamilies( reaction.reactants, reaction.products, only_families=[family]) if len(reactions) != 1: print 'Warning: could not determine forward degeneracy for reaction #{0:d}.'.format( index + 1) forwardDegeneracy = 1 else: forwardDegeneracy = reactions[0].degeneracy reactions = database.kinetics.generateReactionsFromFamilies( reaction.products, reaction.reactants, only_families=[family]) if len(reactions) != 1: print 'Warning: could not determine reverse degeneracy for reaction #{0:d}.'.format( index + 1) reverseDegeneracy = 1 else: reverseDegeneracy = reactions[0].degeneracy saveReaction( 'input/kinetics/families/{0}/training/{0}.py'.format( family, index + 1), index + 1, label, reaction, forwardDegeneracy, reverseDegeneracy)
def convertPrIMe(family): print 'Loading kinetics families...' database = RMGDatabase() database.kinetics = KineticsDatabase() database.kinetics.loadFamilies('input/kinetics/families') database.loadForbiddenStructures('input/forbiddenStructures.py') for depository in database.kinetics.families[family].depositories: if depository.label == '{0}/PrIMe'.format(family): break else: raise Exception('Could not find PrIMe depository in {0} family.'.format(family)) entries = [] print 'Determining unique list of reactions...' for entry0 in depository.entries.values(): for entry in entries: if entry.item.isIsomorphic(entry0.item): break else: entries.append(entry0) print 'Found {0:d} unique reactions out of {1:d} entries.'.format(len(entries), len(depository.entries)) print 'Sorting unique reactions...' entries.sort(key=lambda entry: sum([1 for r in entry.item.reactants for a in r.atoms if a.isNonHydrogen()])) print 'Saving reactions...' for index, entry in enumerate(entries): label = entry.label reaction = entry.item # Determine degeneracy in both directions reactions = database.kinetics.generateReactionsFromFamilies(reaction.reactants, reaction.products, only_families=[family]) if len(reactions) != 1: print 'Warning: could not determine forward degeneracy for reaction #{0:d}.'.format(index+1) forwardDegeneracy = 1 else: forwardDegeneracy = reactions[0].degeneracy reactions = database.kinetics.generateReactionsFromFamilies(reaction.products, reaction.reactants, only_families=[family]) if len(reactions) != 1: print 'Warning: could not determine reverse degeneracy for reaction #{0:d}.'.format(index+1) reverseDegeneracy = 1 else: reverseDegeneracy = reactions[0].degeneracy saveReaction('input/kinetics/families/{0}/training/{0}.py'.format(family, index+1), index+1, label, reaction, forwardDegeneracy, reverseDegeneracy)
def loadDatabase(component='', section=''): """ Load the requested `component` of the RMG database if modified since last loaded. """ global database if not database: database = RMGDatabase() database.thermo = ThermoDatabase() database.kinetics = KineticsDatabase() database.loadForbiddenStructures(os.path.join(settings.DATABASE_PATH, 'forbiddenStructures.py')) if component in ['thermo', '']: if section in ['depository', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'thermo', 'depository') if isDirModified(dirpath): database.thermo.loadDepository(dirpath) resetDirTimestamps(dirpath) if section in ['libraries', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'thermo', 'libraries') if isDirModified(dirpath): database.thermo.loadLibraries(dirpath) # put them in our preferred order, so that when we look up thermo in order to estimate kinetics, # we use our favourite values first. preferred_order = ['primaryThermoLibrary','DFT_QCI_thermo','GRI-Mech3.0','CBS_QB3_1dHR','KlippensteinH2O2'] new_order = [i for i in preferred_order if i in database.thermo.libraryOrder] for i in database.thermo.libraryOrder: if i not in new_order: new_order.append(i) database.thermo.libraryOrder = new_order resetDirTimestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'thermo', 'groups') if isDirModified(dirpath): database.thermo.loadGroups(dirpath) resetDirTimestamps(dirpath) if component in ['kinetics', '']: if section in ['libraries', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'kinetics', 'libraries') if isDirModified(dirpath): database.kinetics.loadLibraries(dirpath) resetDirTimestamps(dirpath) if section in ['families', '']: dirpath = os.path.join(settings.DATABASE_PATH, 'kinetics', 'families') if isDirModified(dirpath): database.kinetics.loadFamilies(dirpath) resetDirTimestamps(dirpath) return database
def setUpModule(): """A function that is run ONCE before all unit tests in this module.""" global database database = RMGDatabase() database.load( path=os.path.join(settings['test_data.directory'], 'testing_database'), kineticsFamilies=['H_Abstraction', 'intra_H_migration'], testing=True, depository=False, solvation=False, ) database.loadForbiddenStructures() # Prepare the database by loading training reactions and averaging the rate rules for family in database.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True)
def setUpModule(): """A function that is run ONCE before all unit tests in this module.""" global database database = RMGDatabase() database.load( path=os.path.join(settings['test_data.directory'], 'testing_database'), kineticsFamilies=[ 'H_Abstraction','intra_H_migration' ], testing=True, depository=False, solvation=False, ) database.loadForbiddenStructures() # Prepare the database by loading training reactions and averaging the rate rules for family in database.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True)
def setUpModule(): """A function that is run ONCE before all unit tests in this module.""" global database database = RMGDatabase() database.load( path=os.path.join(settings['test_data.directory'], 'testing_database'), thermoLibraries=['primaryThermoLibrary'], reactionLibraries=['GRI-Mech3.0'], kineticsFamilies=[ 'R_Recombination', 'Disproportionation', 'R_Addition_MultipleBond', ], testing=True, depository=False, solvation=False, ) database.loadForbiddenStructures() # Prepare the database by loading training reactions and averaging the rate rules for family in database.kinetics.families.values(): family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) family.fillKineticsRulesByAveragingUp(verbose=True)
class RMGWebDatabase(object): """Wrapper class for RMGDatabase that provides loading functionality.""" def __init__(self): self.database = RMGDatabase() self.database.kinetics = KineticsDatabase() self.database.thermo = ThermoDatabase() self.database.transport = TransportDatabase() self.database.statmech = StatmechDatabase() self.database.solvation = SolvationDatabase() self.database.loadForbiddenStructures(os.path.join(rmgweb.settings.DATABASE_PATH, 'forbiddenStructures.py')) self.timestamps = {} @property def kinetics(self): """Get the kinetics database.""" return self.database.kinetics @property def thermo(self): """Get the thermo database.""" return self.database.thermo @property def transport(self): """Get the transport database.""" return self.database.transport @property def statmech(self): """Get the statmech database.""" return self.database.statmech @property def solvation(self): """Get the solvation database.""" return self.database.solvation def reset_timestamp(self, path): """ Reset the files timestamp in the dictionary of timestamps. """ mtime = os.stat(path).st_mtime self.timestamps[path] = mtime def reset_dir_timestamps(self, dirpath): """ Walk the directory tree from dirpath, calling reset_timestamp(file) on each file. """ print "Resetting 'last loaded' timestamps for {0} in process {1}".format(dirpath, os.getpid()) for root, dirs, files in os.walk(dirpath): for name in files: self.reset_timestamp(os.path.join(root, name)) def is_file_modified(self, path): """ Return True if the file at `path` has been modified since `reset_timestamp(path)` was last called. """ # If path doesn't denote a file and were previously # tracking it, then it has been removed or the file type # has changed, so return True. if not os.path.isfile(path): return path in self.timestamps # If path wasn't being tracked then it's new, so return True elif path not in self.timestamps: return True # Force restart when modification time has changed, even # if time now older, as that could indicate older file # has been restored. elif os.stat(path).st_mtime != self.timestamps[path]: return True # All the checks have been passed, so the file was not modified else: return False def is_dir_modified(self, dirpath): """ Returns True if anything in the directory at dirpath has been modified since reset_dir_timestamps(dirpath). """ to_check = set([path for path in self.timestamps if path.startswith(dirpath)]) for root, dirs, files in os.walk(dirpath): for name in files: path = os.path.join(root, name) if self.is_file_modified(path): return True to_check.remove(path) # If there's anything left in to_check, it's probably now gone and this will return True: for path in to_check: if self.is_file_modified(path): return True # Passed all tests. return False ################################################################################ def load(self, component='', section=''): """ Load the requested `component` of the RMG database if modified since last loaded. """ if component in ['thermo', '']: if section in ['depository', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'depository') if self.is_dir_modified(dirpath): self.database.thermo.loadDepository(dirpath) self.reset_dir_timestamps(dirpath) if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'libraries') if self.is_dir_modified(dirpath): self.database.thermo.loadLibraries(dirpath) # put them in our preferred order, so that when we look up thermo in order to estimate kinetics, # we use our favorite values first. preferred_order = [ 'primaryThermoLibrary', 'DFT_QCI_thermo', 'GRI-Mech3.0', 'CBS_QB3_1dHR', 'KlippensteinH2O2', ] new_order = [i for i in preferred_order if i in self.database.thermo.libraryOrder] for i in self.database.thermo.libraryOrder: if i not in new_order: new_order.append(i) self.database.thermo.libraryOrder = new_order self.reset_dir_timestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'groups') if self.is_dir_modified(dirpath): self.database.thermo.loadGroups(dirpath) self.reset_dir_timestamps(dirpath) if component in ['transport', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'libraries') if self.is_dir_modified(dirpath): self.database.transport.loadLibraries(dirpath) self.reset_dir_timestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'groups') if self.is_dir_modified(dirpath): self.database.transport.loadGroups(dirpath) self.reset_dir_timestamps(dirpath) if component in ['solvation', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'solvation') if self.is_dir_modified(dirpath): self.database.solvation.load(dirpath) self.reset_dir_timestamps(dirpath) if component in ['kinetics', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'libraries') if self.is_dir_modified(dirpath): self.database.kinetics.loadLibraries(dirpath) self.reset_dir_timestamps(dirpath) if section in ['families', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'families') if self.is_dir_modified(dirpath): self.database.kinetics.loadFamilies(dirpath, families='all', depositories='all') self.reset_dir_timestamps(dirpath) # Make sure to load the entire thermo database prior to adding training values to the rules self.load('thermo', '') for family in self.database.kinetics.families.values(): oldentries = len(family.rules.entries) family.addKineticsRulesFromTrainingSet(thermoDatabase=self.database.thermo) newentries = len(family.rules.entries) if newentries != oldentries: print '{0} new entries added to {1} family after adding rules from training set.'.format( newentries - oldentries, family.label) # Filling in rate rules in kinetics families by averaging... family.fillKineticsRulesByAveragingUp() if component in ['statmech', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'statmech') if self.is_dir_modified(dirpath): self.database.statmech.load(dirpath) self.reset_dir_timestamps(dirpath) def get_transport_database(self, section, subsection): """ Return the component of the transport database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == 'libraries': db = self.database.transport.libraries[subsection] elif section == 'groups': db = self.database.transport.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_solvation_database(self, section, subsection): """ Return the component of the solvation database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == '': db = self.database.solvation # return general SolvationDatabase elif section == 'libraries': db = self.database.solvation.libraries[subsection] elif section == 'groups': db = self.database.solvation.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_statmech_database(self, section, subsection): """ Return the component of the statmech database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == 'depository': db = self.database.statmech.depository[subsection] elif section == 'libraries': db = self.database.statmech.libraries[subsection] elif section == 'groups': db = self.database.statmech.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_thermo_database(self, section, subsection): """ Return the component of the thermodynamics database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == 'depository': db = self.database.thermo.depository[subsection] elif section == 'libraries': db = self.database.thermo.libraries[subsection] elif section == 'groups': db = self.database.thermo.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_kinetics_database(self, section, subsection): """ Return the component of the kinetics database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ db = None try: if section == 'libraries': db = self.database.kinetics.libraries[subsection] elif section == 'families': subsection = subsection.split('/') if subsection[0] != '' and len(subsection) == 2: family = self.database.kinetics.families[subsection[0]] if subsection[1] == 'groups': db = family.groups elif subsection[1] == 'rules': db = family.rules else: label = '{0}/{1}'.format(family.label, subsection[1]) db = (d for d in family.depositories if d.label == label).next() else: raise ValueError('Invalid value "%s" for section parameter.' % section) except (KeyError, StopIteration): raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db
def loadDatabase(component='', section=''): """ Load the requested `component` of the RMG database if modified since last loaded. """ global database if not database: database = RMGDatabase() database.solvation = SolvationDatabase() database.thermo = ThermoDatabase() database.kinetics = KineticsDatabase() database.transport = TransportDatabase() database.statmech = StatmechDatabase() database.loadForbiddenStructures( os.path.join(rmgweb.settings.DATABASE_PATH, 'forbiddenStructures.py')) if component == 'initialize': return database if component in ['thermo', '']: if section in ['depository', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'depository') if isDirModified(dirpath): database.thermo.loadDepository(dirpath) resetDirTimestamps(dirpath) if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'libraries') if isDirModified(dirpath): database.thermo.loadLibraries(dirpath) # put them in our preferred order, so that when we look up thermo in order to estimate kinetics, # we use our favorite values first. preferred_order = [ 'primaryThermoLibrary', 'DFT_QCI_thermo', 'GRI-Mech3.0', 'CBS_QB3_1dHR', 'KlippensteinH2O2' ] new_order = [ i for i in preferred_order if i in database.thermo.libraryOrder ] for i in database.thermo.libraryOrder: if i not in new_order: new_order.append(i) database.thermo.libraryOrder = new_order resetDirTimestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'groups') if isDirModified(dirpath): database.thermo.loadGroups(dirpath) resetDirTimestamps(dirpath) if component in ['transport', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'libraries') if isDirModified(dirpath): database.transport.loadLibraries(dirpath) resetDirTimestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'groups') if isDirModified(dirpath): database.transport.loadGroups(dirpath) resetDirTimestamps(dirpath) if component in ['solvation', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'solvation') if isDirModified(dirpath): database.solvation.load(dirpath) resetDirTimestamps(dirpath) if component in ['kinetics', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'libraries') if isDirModified(dirpath): database.kinetics.loadLibraries(dirpath) resetDirTimestamps(dirpath) if section in ['families', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'families') if isDirModified(dirpath): database.kinetics.loadFamilies(dirpath, families='all', depositories='all') resetDirTimestamps(dirpath) # Make sure to load the entire thermo database prior to adding training values to the rules loadDatabase('thermo', '') for family in database.kinetics.families.values(): oldentries = len(family.rules.entries) family.addKineticsRulesFromTrainingSet( thermoDatabase=database.thermo) newentries = len(family.rules.entries) if newentries != oldentries: print '{0} new entries added to {1} family after adding rules from training set.'.format( newentries - oldentries, family.label) # Filling in rate rules in kinetics families by averaging... family.fillKineticsRulesByAveragingUp() if component in ['statmech', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'statmech') if isDirModified(dirpath): database.statmech.load(dirpath) resetDirTimestamps(dirpath) return database
class RMGWebDatabase(object): """Wrapper class for RMGDatabase that provides loading functionality.""" def __init__(self): self.database = RMGDatabase() self.database.kinetics = KineticsDatabase() self.database.thermo = ThermoDatabase() self.database.transport = TransportDatabase() self.database.statmech = StatmechDatabase() self.database.solvation = SolvationDatabase() self.database.loadForbiddenStructures( os.path.join(rmgweb.settings.DATABASE_PATH, 'forbiddenStructures.py')) self.timestamps = {} @property def kinetics(self): """Get the kinetics database.""" return self.database.kinetics @property def thermo(self): """Get the thermo database.""" return self.database.thermo @property def transport(self): """Get the transport database.""" return self.database.transport @property def statmech(self): """Get the statmech database.""" return self.database.statmech @property def solvation(self): """Get the solvation database.""" return self.database.solvation def reset_timestamp(self, path): """ Reset the files timestamp in the dictionary of timestamps. """ mtime = os.stat(path).st_mtime self.timestamps[path] = mtime def reset_dir_timestamps(self, dirpath): """ Walk the directory tree from dirpath, calling reset_timestamp(file) on each file. """ print "Resetting 'last loaded' timestamps for {0} in process {1}".format( dirpath, os.getpid()) for root, dirs, files in os.walk(dirpath): for name in files: self.reset_timestamp(os.path.join(root, name)) def is_file_modified(self, path): """ Return True if the file at `path` has been modified since `reset_timestamp(path)` was last called. """ # If path doesn't denote a file and were previously # tracking it, then it has been removed or the file type # has changed, so return True. if not os.path.isfile(path): return path in self.timestamps # If path wasn't being tracked then it's new, so return True elif path not in self.timestamps: return True # Force restart when modification time has changed, even # if time now older, as that could indicate older file # has been restored. elif os.stat(path).st_mtime != self.timestamps[path]: return True # All the checks have been passed, so the file was not modified else: return False def is_dir_modified(self, dirpath): """ Returns True if anything in the directory at dirpath has been modified since reset_dir_timestamps(dirpath). """ to_check = set( [path for path in self.timestamps if path.startswith(dirpath)]) for root, dirs, files in os.walk(dirpath): for name in files: path = os.path.join(root, name) if self.is_file_modified(path): return True to_check.remove(path) # If there's anything left in to_check, it's probably now gone and this will return True: for path in to_check: if self.is_file_modified(path): return True # Passed all tests. return False ################################################################################ def load(self, component='', section=''): """ Load the requested `component` of the RMG database if modified since last loaded. """ if component in ['thermo', '']: if section in ['depository', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'depository') if self.is_dir_modified(dirpath): self.database.thermo.loadDepository(dirpath) self.reset_dir_timestamps(dirpath) if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'libraries') if self.is_dir_modified(dirpath): self.database.thermo.loadLibraries(dirpath) # put them in our preferred order, so that when we look up thermo in order to estimate kinetics, # we use our favorite values first. preferred_order = [ 'primaryThermoLibrary', 'DFT_QCI_thermo', 'GRI-Mech3.0', 'CBS_QB3_1dHR', 'KlippensteinH2O2', ] new_order = [ i for i in preferred_order if i in self.database.thermo.libraryOrder ] for i in self.database.thermo.libraryOrder: if i not in new_order: new_order.append(i) self.database.thermo.libraryOrder = new_order self.reset_dir_timestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'groups') if self.is_dir_modified(dirpath): self.database.thermo.loadGroups(dirpath) self.reset_dir_timestamps(dirpath) if component in ['transport', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'libraries') if self.is_dir_modified(dirpath): self.database.transport.loadLibraries(dirpath) self.reset_dir_timestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'groups') if self.is_dir_modified(dirpath): self.database.transport.loadGroups(dirpath) self.reset_dir_timestamps(dirpath) if component in ['solvation', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'solvation') if self.is_dir_modified(dirpath): self.database.solvation.load(dirpath) self.reset_dir_timestamps(dirpath) if component in ['kinetics', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'libraries') if self.is_dir_modified(dirpath): self.database.kinetics.loadLibraries(dirpath) self.reset_dir_timestamps(dirpath) if section in ['families', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'families') if self.is_dir_modified(dirpath): self.database.kinetics.loadFamilies(dirpath, families='all', depositories='all') self.reset_dir_timestamps(dirpath) # Make sure to load the entire thermo database prior to adding training values to the rules self.load('thermo', '') for family in self.database.kinetics.families.values(): oldentries = len(family.rules.entries) family.addKineticsRulesFromTrainingSet( thermoDatabase=self.database.thermo) newentries = len(family.rules.entries) if newentries != oldentries: print '{0} new entries added to {1} family after adding rules from training set.'.format( newentries - oldentries, family.label) # Filling in rate rules in kinetics families by averaging... family.fillKineticsRulesByAveragingUp() if component in ['statmech', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'statmech') if self.is_dir_modified(dirpath): self.database.statmech.load(dirpath) self.reset_dir_timestamps(dirpath) def get_transport_database(self, section, subsection): """ Return the component of the transport database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == 'libraries': db = self.database.transport.libraries[subsection] elif section == 'groups': db = self.database.transport.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_solvation_database(self, section, subsection): """ Return the component of the solvation database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == '': db = self.database.solvation # return general SolvationDatabase elif section == 'libraries': db = self.database.solvation.libraries[subsection] elif section == 'groups': db = self.database.solvation.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_statmech_database(self, section, subsection): """ Return the component of the statmech database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == 'depository': db = self.database.statmech.depository[subsection] elif section == 'libraries': db = self.database.statmech.libraries[subsection] elif section == 'groups': db = self.database.statmech.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_thermo_database(self, section, subsection): """ Return the component of the thermodynamics database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ try: if section == 'depository': db = self.database.thermo.depository[subsection] elif section == 'libraries': db = self.database.thermo.libraries[subsection] elif section == 'groups': db = self.database.thermo.groups[subsection] else: raise ValueError('Invalid value "%s" for section parameter.' % section) except KeyError: raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db def get_kinetics_database(self, section, subsection): """ Return the component of the kinetics database corresponding to the given `section` and `subsection`. If either of these is invalid, a :class:`ValueError` is raised. """ db = None try: if section == 'libraries': db = self.database.kinetics.libraries[subsection] elif section == 'families': subsection = subsection.split('/') if subsection[0] != '' and len(subsection) == 2: family = self.database.kinetics.families[subsection[0]] if subsection[1] == 'groups': db = family.groups elif subsection[1] == 'rules': db = family.rules else: label = '{0}/{1}'.format(family.label, subsection[1]) db = (d for d in family.depositories if d.label == label).next() else: raise ValueError('Invalid value "%s" for section parameter.' % section) except (KeyError, StopIteration): raise ValueError('Invalid value "%s" for subsection parameter.' % subsection) return db
def loadDatabase(component='', section=''): """ Load the requested `component` of the RMG database if modified since last loaded. """ global database if not database: database = RMGDatabase() database.solvation = SolvationDatabase() database.thermo = ThermoDatabase() database.kinetics = KineticsDatabase() database.transport = TransportDatabase() database.statmech = StatmechDatabase() database.loadForbiddenStructures(os.path.join(rmgweb.settings.DATABASE_PATH, 'forbiddenStructures.py')) if component == 'initialize': return database if component in ['thermo', '']: if section in ['depository', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'depository') if isDirModified(dirpath): database.thermo.loadDepository(dirpath) resetDirTimestamps(dirpath) if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'libraries') if isDirModified(dirpath): database.thermo.loadLibraries(dirpath) # put them in our preferred order, so that when we look up thermo in order to estimate kinetics, # we use our favorite values first. preferred_order = ['primaryThermoLibrary','DFT_QCI_thermo','GRI-Mech3.0','CBS_QB3_1dHR','KlippensteinH2O2'] new_order = [i for i in preferred_order if i in database.thermo.libraryOrder] for i in database.thermo.libraryOrder: if i not in new_order: new_order.append(i) database.thermo.libraryOrder = new_order resetDirTimestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'thermo', 'groups') if isDirModified(dirpath): database.thermo.loadGroups(dirpath) resetDirTimestamps(dirpath) if component in ['transport', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'libraries') if isDirModified(dirpath): database.transport.loadLibraries(dirpath) resetDirTimestamps(dirpath) if section in ['groups', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'transport', 'groups') if isDirModified(dirpath): database.transport.loadGroups(dirpath) resetDirTimestamps(dirpath) if component in ['solvation', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'solvation') if isDirModified(dirpath): database.solvation.load(dirpath) resetDirTimestamps(dirpath) if component in ['kinetics', '']: if section in ['libraries', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'libraries') if isDirModified(dirpath): database.kinetics.loadLibraries(dirpath) resetDirTimestamps(dirpath) if section in ['families', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'kinetics', 'families') if isDirModified(dirpath): database.kinetics.loadFamilies(dirpath, families = 'all', depositories = 'all') resetDirTimestamps(dirpath) # Make sure to load the entire thermo database prior to adding training values to the rules loadDatabase('thermo','') for family in database.kinetics.families.values(): oldentries = len(family.rules.entries) family.addKineticsRulesFromTrainingSet(thermoDatabase=database.thermo) newentries = len(family.rules.entries) if newentries != oldentries: print '{0} new entries added to {1} family after adding rules from training set.'.format(newentries-oldentries, family.label) # Filling in rate rules in kinetics families by averaging... family.fillKineticsRulesByAveragingUp() if component in ['statmech', '']: dirpath = os.path.join(rmgweb.settings.DATABASE_PATH, 'statmech') if isDirModified(dirpath): database.statmech.load(dirpath) resetDirTimestamps(dirpath) return database
class TestReact(unittest.TestCase): def setUp(self): """ A function run before each unit test in this class. """ # load kinetics database db_path = settings['database.directory'] self.database = RMGDatabase() # forbidden structure loading self.database.loadForbiddenStructures( os.path.join(db_path, 'forbiddenStructures.py')) # kinetics family loading self.database.loadKinetics(os.path.join(db_path, 'kinetics'), kineticsFamilies=[ 'R_Recombination', 'H_Abstraction', '1,2_Insertion_carbene' ], reactionLibraries=[]) def test_react_fragments1(self): frag1 = afm.fragment.Fragment( label='frag1').from_SMILES_like_string('c1ccccc1CCCR') fragment_tuple = (frag1, ) reactions = afm.react.react_fragments( self.database.kinetics, fragment_tuple, only_families=['R_Recombination'], prod_resonance=False) self.assertTrue(len(reactions) == 28) def test_react_fragments2(self): frag1 = afm.fragment.Fragment( label='frag1').from_SMILES_like_string('c1ccccc1CCCR') frag2 = afm.fragment.Fragment( label='frag2').from_SMILES_like_string('[CH2]CR') fragment_tuple = (frag1, frag2) reactions = afm.react.react_fragments(self.database.kinetics, fragment_tuple, only_families=['H_Abstraction'], prod_resonance=False) self.assertTrue(len(reactions) == 11) def test_generate_reactions_from_families1(self): frag1 = afm.fragment.Fragment( label='frag1').from_SMILES_like_string('CC') spec1 = Species(molecule=[frag1]) spec_tuple = (spec1, ) reactions = self.database.kinetics.generate_reactions_from_families( spec_tuple) self.assertTrue(len(reactions) == 3) def test_generate_reactions_from_families2(self): frag1 = afm.fragment.Fragment( label='frag1').from_SMILES_like_string('CCR') spec1 = Species(molecule=[frag1]) spec_tuple = (spec1, ) reactions = self.database.kinetics.generate_reactions_from_families( spec_tuple) self.assertTrue(len(reactions) == 4)