def read_reference_data(self): """ Read the reference hydrational data from a file. """ # Read the HFE data file. This is a very simple file format: self.IDs = [] self.expval = OrderedDict() self.experr = OrderedDict() self.nicknames = OrderedDict() # We don't need every single line to be the same. This # indicates whether *any* molecule has a nickname for printing # out the nickname column. self.have_nicks = False # Again for experimental errors. Note that we're NOT using them in the optimization at this time. self.have_experr = False for line in open(self.datafile).readlines(): s = line.expandtabs().strip().split('#')[0].split() if len(s) == 0: continue ID = s[0] self.IDs.append(ID) # Dynamic field number for the experimental data. nxt = 1 # If the next field is a string, then it's the "nickname" if not isfloat(s[1]): self.have_nicks = True self.nicknames[ID] = s[1] nxt += 1 else: # We don't need nicknames on every single line. self.nicknames[ID] = ID # Read the experimental value. self.expval[ID] = float(s[nxt]) # Read the experimental error bar, or use a default value of 0.6 (from Mobley). if len(s) > (nxt + 1): self.have_experr = True self.experr[ID] = float(s[nxt + 1]) else: self.experr[ID] = 0.6 self.molecules = OrderedDict([ (i, os.path.abspath( os.path.join(self.root, self.tgtdir, 'molecules', i + self.crdsfx))) for i in self.IDs ]) for fnm, path in self.molecules.items(): if not os.path.isfile(path): logger.error( 'Coordinate file %s does not exist!\nMake sure coordinate files are in the right place\n' % path) raise RuntimeError if self.subset is not None: subset = uncommadash(self.subset) self.whfe = np.array( [1 if i in subset else 0 for i in range(len(self.IDs))]) else: self.whfe = np.ones(len(self.IDs))
def read_reference_data(self): """ Read the reference hydrational data from a file. """ self.refdata = OrderedDict([(l.split()[0], float(l.split()[1])) for l in open(self.datafile).readlines()]) self.molecules = OrderedDict([(i, os.path.abspath(os.path.join(self.root, self.tgtdir, 'molecules', i+self.crdsfx))) for i in self.refdata.keys()]) for fnm, path in self.molecules.items(): if not os.path.isfile(path): logger.error('Coordinate file %s does not exist!\nMake sure coordinate files are in the right place\n' % path) raise RuntimeError if self.subset != None: subset = uncommadash(self.subset) self.whfe = np.array([1 if i in subset else 0 for i in range(len(self.refdata.keys()))]) else: self.whfe = np.ones(len(self.refdata.keys()))
def read_reference_data(self): """ Read the reference hydrational data from a file. """ # Read the HFE data file. This is a very simple file format: self.IDs = [] self.expval = OrderedDict() self.experr = OrderedDict() self.nicknames = OrderedDict() # We don't need every single line to be the same. This # indicates whether *any* molecule has a nickname for printing # out the nickname column. self.have_nicks = False # Again for experimental errors. Note that we're NOT using them in the optimization at this time. self.have_experr = False for line in open(self.datafile).readlines(): s = line.expandtabs().strip().split('#')[0].split() if len(s) == 0: continue ID = s[0] self.IDs.append(ID) # Dynamic field number for the experimental data. nxt = 1 # If the next field is a string, then it's the "nickname" if not isfloat(s[1]): self.have_nicks = True self.nicknames[ID] = s[1] nxt += 1 else: # We don't need nicknames on every single line. self.nicknames[ID] = ID # Read the experimental value. self.expval[ID] = float(s[nxt]) # Read the experimental error bar, or use a default value of 0.6 (from Mobley). if len(s) > (nxt+1): self.have_experr = True self.experr[ID] = float(s[nxt+1]) else: self.experr[ID] = 0.6 self.molecules = OrderedDict([(i, os.path.abspath(os.path.join(self.root, self.tgtdir, 'molecules', i+self.crdsfx))) for i in self.IDs]) for fnm, path in self.molecules.items(): if not os.path.isfile(path): logger.error('Coordinate file %s does not exist!\nMake sure coordinate files are in the right place\n' % path) raise RuntimeError if self.subset != None: subset = uncommadash(self.subset) self.whfe = np.array([1 if i in subset else 0 for i in range(len(self.IDs))]) else: self.whfe = np.ones(len(self.IDs))
def read_reference_data(self): """ Read the reference hydrational data from a file. """ self.refdata = OrderedDict([(l.split()[0], float(l.split()[1])) for l in open(self.datafile).readlines()]) self.molecules = OrderedDict([ (i, os.path.abspath( os.path.join(self.root, self.tgtdir, 'molecules', i + self.crdsfx))) for i in self.refdata.keys() ]) for fnm, path in self.molecules.items(): if not os.path.isfile(path): logger.error( 'Coordinate file %s does not exist!\nMake sure coordinate files are in the right place\n' % path) raise RuntimeError if self.subset != None: subset = uncommadash(self.subset) self.whfe = np.array([ 1 if i in subset else 0 for i in range(len(self.refdata.keys())) ]) else: self.whfe = np.ones(len(self.refdata.keys()))
def __init__(self,options,tgt_opts,forcefield): # Initialize the SuperClass! super(Interaction,self).__init__(options,tgt_opts,forcefield) #======================================# # Options that are given by the parser # #======================================# ## Number of snapshots self.set_option(tgt_opts,'shots','ns') ## Do we call Q-Chem for dielectric energies? (Currently needs to be fixed) self.set_option(tgt_opts,'do_cosmo','do_cosmo') ## Do we put the reference energy into the denominator? self.set_option(tgt_opts,'cauchy','cauchy') ## Do we put the reference energy into the denominator? self.set_option(tgt_opts,'attenuate','attenuate') ## Divide by the number of snapshots? self.set_option(tgt_opts, 'normalize') ## What is the energy denominator? self.set_option(tgt_opts,'energy_denom','energy_denom') ## Set fragment 1 self.set_option(tgt_opts,'fragment1','fragment1') if len(self.fragment1) == 0: logger.error('You need to define the first fragment using the fragment1 keyword\n') raise RuntimeError self.select1 = np.array(uncommadash(self.fragment1)) ## Set fragment 2 self.set_option(tgt_opts,'fragment2','fragment2') if len(self.fragment2) != 0: self.select2 = np.array(uncommadash(self.fragment2)) else: self.select2 = None ## Set upper cutoff energy self.set_option(tgt_opts,'energy_upper','energy_upper') #======================================# # Variables which are set here # #======================================# ## Reference (QM) interaction energies self.eqm = [] ## Snapshot label, useful for graphing self.label = [] ## The qdata.txt file that contains the QM energies and forces self.qfnm = os.path.join(self.tgtdir,"qdata.txt") self.e_err = 0.0 self.e_err_pct = None ## Read in the trajectory file self.mol = Molecule(os.path.join(self.root,self.tgtdir,self.coords), top=(os.path.join(self.root,self.tgtdir,self.pdb) if hasattr(self, 'pdb') else None)) if self.ns != -1: self.mol = self.mol[:self.ns] self.ns = len(self.mol) if self.select2 is None: self.select2 = [i for i in range(self.mol.na) if i not in self.select1] logger.info('Fragment 2 is the complement of fragment 1 : %s\n' % (commadash(self.select2))) ## Build keyword dictionaries to pass to engine. engine_args = OrderedDict(self.OptionDict.items() + options.items()) del engine_args['name'] self.engine = self.engine_(target=self, mol=self.mol, **engine_args) ## Read in the reference data self.read_reference_data() logger.info("The energy denominator is: %s kcal/mol\n" % str(self.energy_denom)) denom = self.energy_denom # Create the denominator. if self.cauchy: self.divisor = np.sqrt(self.eqm**2 + denom**2) if self.attenuate: logger.error('attenuate and cauchy are mutually exclusive\n') raise RuntimeError elif self.attenuate: # Attenuate only large repulsions. self.divisor = np.zeros(len(self.eqm)) for i in range(len(self.eqm)): if self.eqm[i] < denom: self.divisor[i] = denom else: self.divisor[i] = np.sqrt(denom**2 + (self.eqm[i]-denom)**2) else: self.divisor = np.ones(len(self.eqm)) * denom if self.cauchy: logger.info("Each contribution to the interaction energy objective function will be scaled by 1.0 / ( energy_denom**2 + reference**2 )\n") if self.energy_upper > 0: ecut = self.energy_upper self.prefactor = 1.0 * (self.eqm < ecut) logger.info("Interactions more repulsive than %s will not be fitted (%i/%i excluded) \n" % (str(self.energy_upper), sum(self.eqm > ecut), len(self.eqm))) else: self.prefactor = np.ones(len(self.eqm)) if self.normalize: self.prefactor /= len(self.prefactor)
def __init__(self, options, tgt_opts, forcefield): # Initialize the SuperClass! super(Interaction, self).__init__(options, tgt_opts, forcefield) #======================================# # Options that are given by the parser # #======================================# ## Number of snapshots self.set_option(tgt_opts, 'shots', 'ns') ## Do we call Q-Chem for dielectric energies? (Currently needs to be fixed) self.set_option(tgt_opts, 'do_cosmo', 'do_cosmo') ## Do we put the reference energy into the denominator? self.set_option(tgt_opts, 'cauchy', 'cauchy') ## Do we put the reference energy into the denominator? self.set_option(tgt_opts, 'attenuate', 'attenuate') ## Divide by the number of snapshots? self.set_option(tgt_opts, 'normalize') ## What is the energy denominator? self.set_option(tgt_opts, 'energy_denom', 'energy_denom') ## Set fragment 1 self.set_option(tgt_opts, 'fragment1', 'fragment1') if len(self.fragment1) == 0: logger.error( 'You need to define the first fragment using the fragment1 keyword\n' ) raise RuntimeError self.select1 = np.array(uncommadash(self.fragment1)) ## Set fragment 2 self.set_option(tgt_opts, 'fragment2', 'fragment2') if len(self.fragment2) != 0: self.select2 = np.array(uncommadash(self.fragment2)) else: self.select2 = None ## Set upper cutoff energy self.set_option(tgt_opts, 'energy_upper', 'energy_upper') #======================================# # Variables which are set here # #======================================# ## Reference (QM) interaction energies self.eqm = [] ## Snapshot label, useful for graphing self.label = [] ## The qdata.txt file that contains the QM energies and forces self.qfnm = os.path.join(self.tgtdir, "qdata.txt") self.e_err = 0.0 self.e_err_pct = None ## Read in the trajectory file if self.ns == -1: self.mol = Molecule( os.path.join(self.root, self.tgtdir, self.coords)) self.ns = len(self.mol) else: self.mol = Molecule( os.path.join(self.root, self.tgtdir, self.coords))[:self.ns] if self.select2 == None: self.select2 = [ i for i in range(self.mol.na) if i not in self.select1 ] logger.info('Fragment 2 is the complement of fragment 1 : %s\n' % (commadash(self.select2))) ## Build keyword dictionaries to pass to engine. engine_args = OrderedDict(self.OptionDict.items() + options.items()) del engine_args['name'] self.engine = self.engine_(target=self, mol=self.mol, **engine_args) ## Read in the reference data self.read_reference_data() logger.info("The energy denominator is: %s kcal/mol\n" % str(self.energy_denom)) denom = self.energy_denom # Create the denominator. if self.cauchy: self.divisor = np.sqrt(self.eqm**2 + denom**2) if self.attenuate: logger.error('attenuate and cauchy are mutually exclusive\n') raise RuntimeError elif self.attenuate: # Attenuate only large repulsions. self.divisor = np.zeros(len(self.eqm)) for i in range(len(self.eqm)): if self.eqm[i] < denom: self.divisor[i] = denom else: self.divisor[i] = np.sqrt(denom**2 + (self.eqm[i] - denom)**2) else: self.divisor = np.ones(len(self.eqm)) * denom if self.cauchy: logger.info( "Each contribution to the interaction energy objective function will be scaled by 1.0 / ( energy_denom**2 + reference**2 )\n" ) if self.energy_upper > 0: ecut = self.energy_upper self.prefactor = 1.0 * (self.eqm < ecut) logger.info( "Interactions more repulsive than %s will not be fitted (%i/%i excluded) \n" % (str(self.energy_upper), sum(self.eqm > ecut), len(self.eqm))) else: self.prefactor = np.ones(len(self.eqm)) if self.normalize: self.prefactor /= len(self.prefactor)
def __init__(self,options,tgt_opts,forcefield): # Initialize the SuperClass! super(Interaction,self).__init__(options,tgt_opts,forcefield) #======================================# # Options that are given by the parser # #======================================# ## Number of snapshots self.set_option(tgt_opts,'shots','ns') ## Do we call Q-Chem for dielectric energies? (Currently needs to be fixed) self.set_option(tgt_opts,'do_cosmo','do_cosmo') ## Do we put the reference energy into the denominator? self.set_option(tgt_opts,'cauchy','cauchy') ## Do we put the reference energy into the denominator? self.set_option(tgt_opts,'attenuate','attenuate') ## What is the energy denominator? self.set_option(tgt_opts,'energy_denom','energy_denom') ## Set fragment 1 self.set_option(tgt_opts,'fragment1','fragment1') if len(self.fragment1) == 0: raise Exception('You need to define the first fragment using the fragment1 keyword') self.select1 = array(uncommadash(self.fragment1)) ## Set fragment 2 self.set_option(tgt_opts,'fragment2','fragment2') if len(self.fragment2) == 0: raise Exception('You need to define the second fragment using the fragment2 keyword') self.select2 = array(uncommadash(self.fragment2)) ## Set upper cutoff energy self.set_option(tgt_opts,'energy_upper','energy_upper') #======================================# # Variables which are set here # #======================================# ## Reference (QM) interaction energies self.eqm = [] ## Snapshot label, useful for graphing self.label = [] ## The qdata.txt file that contains the QM energies and forces self.qfnm = os.path.join(self.tgtdir,"qdata.txt") ## Qualitative Indicator: average energy error (in kJ/mol) self.e_err = 0.0 self.e_err_pct = None ## Read in the trajectory file if self.ns == -1: self.traj = Molecule(os.path.join(self.root,self.tgtdir,self.trajfnm)) self.ns = len(self.traj) else: self.traj = Molecule(os.path.join(self.root,self.tgtdir,self.trajfnm))[:self.ns] ## Read in the reference data self.read_reference_data() ## Prepare the temporary directory self.prepare_temp_directory(options,tgt_opts) logger.info("The energy denominator is: %s kcal/mol\n" % str(self.energy_denom)) # Internally things are handled in kJ/mol. denom = self.energy_denom * 4.184 # Create the denominator. if self.cauchy: self.divisor = sqrt(self.eqm**2 + denom**2) if self.attenuate: raise Exception('attenuate and cauchy are mutually exclusive') elif self.attenuate: # Attenuate only large repulsions. self.divisor = zeros(len(self.eqm)) for i in range(len(self.eqm)): if self.eqm[i] < denom: self.divisor[i] = denom else: self.divisor[i] = sqrt(denom**2 + (self.eqm[i]-denom)**2) else: self.divisor = ones(len(self.eqm)) * denom if self.cauchy: logger.info("Each contribution to the interaction energy objective function will be scaled by 1.0 / ( energy_denom**2 + reference**2 )\n") if self.energy_upper > 0: logger.info("Interactions more repulsive than %s will not be fitted\n" % str(self.energy_upper)) ecut = self.energy_upper * 4.184 self.prefactor = 1.0 * (self.eqm < ecut) else: self.prefactor = ones(len(self.eqm))
def __init__(self, options, tgt_opts, forcefield): # Initialize the SuperClass! super(Interaction, self).__init__(options, tgt_opts, forcefield) #======================================# # Options that are given by the parser # #======================================# ## Number of snapshots self.set_option(tgt_opts, 'shots', 'ns') ## Do we call Q-Chem for dielectric energies? (Currently needs to be fixed) self.set_option(tgt_opts, 'do_cosmo', 'do_cosmo') ## Attenuate weights for positive interaction energies self.set_option(tgt_opts, 'attenuate', 'attenuate') ## Divide by the number of snapshots? self.set_option(tgt_opts, 'normalize') ## What is the energy denominator? self.set_option(tgt_opts, 'energy_denom', 'energy_denom') ## Set fragment 1 self.set_option(tgt_opts, 'fragment1', 'fragment1') if len(self.fragment1) == 0: logger.error( 'You need to define the first fragment using the fragment1 keyword\n' ) raise RuntimeError self.select1 = np.array(uncommadash(self.fragment1)) ## Set fragment 2 self.set_option(tgt_opts, 'fragment2', 'fragment2') if len(self.fragment2) != 0: self.select2 = np.array(uncommadash(self.fragment2)) else: self.select2 = None ## Set upper cutoff energy self.set_option(tgt_opts, 'energy_upper', 'energy_upper') ## Option for how much data to write to disk. self.set_option(tgt_opts, 'writelevel', 'writelevel') #======================================# # Variables which are set here # #======================================# ## LPW 2018-02-11: This is set to True if the target calculates ## a single-point property over several existing snapshots. self.loop_over_snapshots = True ## Reference (QM) interaction energies self.eqm = [] ## Snapshot label, useful for graphing self.label = [] ## The qdata.txt file that contains the QM energies and forces self.qfnm = os.path.join(self.tgtdir, "qdata.txt") self.e_err = 0.0 self.e_err_pct = None ## Read in the trajectory file self.mol = Molecule( os.path.join(self.root, self.tgtdir, self.coords), top=(os.path.join(self.root, self.tgtdir, self.pdb) if hasattr( self, 'pdb') else None), build_topology=False if self.coords.endswith('.pdb') else True) if self.ns != -1: self.mol = self.mol[:self.ns] self.ns = len(self.mol) if self.select2 is None: self.select2 = [ i for i in range(self.mol.na) if i not in self.select1 ] logger.info('Fragment 2 is the complement of fragment 1 : %s\n' % (commadash(self.select2))) ## Build keyword dictionaries to pass to engine. engine_args = OrderedDict( list(self.OptionDict.items()) + list(options.items())) engine_args.pop('name', None) self.engine = self.engine_(target=self, mol=self.mol, **engine_args) ## Read in the reference data self.read_reference_data() logger.info("The energy denominator is: %s kcal/mol\n" % str(self.energy_denom)) denom = self.energy_denom if self.attenuate: # The attenuation function for weights is constant for energies up to energy_denom, then falls off smoothly in the shape of a "mesa". self.divisor = np.zeros(len(self.eqm)) for i in range(len(self.eqm)): if self.eqm[i] < denom: self.divisor[i] = denom else: self.divisor[i] = np.sqrt(denom**2 + (self.eqm[i] - denom)**2) logger.info( "Interaction energies more positive than %.1f will have reduced weight going as: 1.0 / (%.1f^2 + (energy-%.1f)^2)\n" % (denom, denom, denom)) else: self.divisor = np.ones(len(self.eqm)) * denom if self.energy_upper > 0: ecut = self.energy_upper self.prefactor = 1.0 * (self.eqm < ecut) logger.info( "Interactions more repulsive than %s will not be fitted (%i/%i excluded) \n" % (str(self.energy_upper), sum(self.eqm > ecut), len(self.eqm))) else: self.prefactor = np.ones(len(self.eqm)) if self.normalize: self.prefactor /= len(self.prefactor)