def read_frq_psi(psiout): """ """ VMode = 0 XMode = 0 EMode = 0 frqs = [] modes = [] xyzs = [] xyz = [] elem = [] for line in open(psiout).readlines(): VModeNxt = None if 'Frequency:' in line: VModeNxt = 1 if line.split()[-1].endswith('i'): frqs.append(-1*float(line.split()[-1][:-1])) # frqs.append(0.0) # After the optimization this mode is going to be useless... else: frqs.append(float(line.split()[-1])) if VMode == 1: if re.match('^[ \t]+X', line): VModeNxt = 2 readmode = [] if VMode == 2: s = line.split() if len(s) != 5: VMode = 0 modes.append(readmode[:]) else: m = float(s[-1]) # Un-massweight the eigenvectors so that the output matches Q-Chem or Gaussian. readmode.append([float(i)/np.sqrt(m) for i in s[1:4]]) if VModeNxt != None: VMode = VModeNxt if XMode == 1: s = line.split() if len(s) == 4 and isfloat(s[1]) and isfloat(s[2]) and isfloat(s[3]): e = s[0] xyz.append([float(i) for i in s[1:4]]) if EMode == 1: elem.append(e) elif len(xyz) > 0: xyzs.append(np.array(xyz)) xyz = [] XMode = 0 if line.strip().startswith("Geometry (in Angstrom)"): XMode = 1 EMode = len(elem) == 0 unnorm = [np.array(i) for i in modes] return np.array(frqs), [i/np.linalg.norm(i) for i in unnorm], elem, np.array(xyzs[-1])
def read_frq_psi(psiout): """ """ VMode = 0 XMode = 0 EMode = 0 frqs = [] modes = [] xyzs = [] xyz = [] elem = [] for line in open(psiout).readlines(): VModeNxt = None if 'Frequency:' in line: VModeNxt = 1 if line.split()[-1].endswith('i'): frqs.append(-1*float(line.split()[-1][:-1])) # frqs.append(0.0) # After the optimization this mode is going to be useless... else: frqs.append(float(line.split()[-1])) if VMode == 1: if re.match('^[ \t]+X', line): VModeNxt = 2 readmode = [] if VMode == 2: s = line.split() if len(s) != 5: VMode = 0 modes.append(readmode[:]) else: m = float(s[-1]) # Un-massweight the eigenvectors so that the output matches Q-Chem or Gaussian. readmode.append([float(i)/np.sqrt(m) for i in s[1:4]]) if VModeNxt is not None: VMode = VModeNxt if XMode == 1: s = line.split() if len(s) == 4 and isfloat(s[1]) and isfloat(s[2]) and isfloat(s[3]): e = s[0] xyz.append([float(i) for i in s[1:4]]) if EMode == 1: elem.append(e) elif len(xyz) > 0: xyzs.append(np.array(xyz)) xyz = [] XMode = 0 if line.strip().startswith("Geometry (in Angstrom)"): XMode = 1 EMode = len(elem) == 0 unnorm = [np.array(i) for i in modes] return np.array(frqs), [i/np.linalg.norm(i) for i in unnorm], elem, np.array(xyzs[-1])
def Calculate_AMBER(Structure, mdp_opts): pbc = mdp_opts["pbc"].lower() == "xyz" # Create AMBER inpcrd file inpcrd = amber.AmberAsciiRestart("inpcrd", mode="w") inpcrd.coordinates = np.array(Structure.positions.value_in_unit( u.angstrom)).reshape(-1, 3) inpcrd.box = Structure.box inpcrd.close() # sander insists on providing a trajectory to iterate over, # so we feed it the same coordinates again. But we don't use it # because the positions are imprecise. mdcrd = amber.AmberMdcrd("mdcrd", natom=len(Structure.atoms), hasbox=pbc, mode="w") mdcrd.add_coordinates( np.array(Structure.positions.value_in_unit(u.angstrom)).reshape(-1, 3)) if pbc: mdcrd.add_box(Structure.box[:3]) mdcrd.close() # Create AMBER prmtop object from ParmEd Structure :) prmtop = amber.AmberParm.from_structure(Structure) prmtop.write_parm("prmtop") # Create AMBER mdin file and append some stuff mdin = Mdin() # Single point energies? mdin.change('cntrl', 'imin', '5') # Periodic boundary conditions? if pbc: mdin.change('cntrl', 'ntb', '1') else: mdin.change('cntrl', 'ntb', '0') # Cutoff zero is really infinite if float(mdp_opts['rlist']) == 0.0: mdin.change('cntrl', 'cut', '9999') else: mdin.change('cntrl', 'cut', str(int(float(mdp_opts['rlist']) * 10))) # Take zero MD steps mdin.change('cntrl', 'nstlim', '0') # Don't update nonbond parameters mdin.change('cntrl', 'nsnb', '0') # if mdp_opts['coulombtype'].lower() == 'pme': # mdin.change('ewald','order',5) # mdin.change('ewald','skinnb',0) mdin.write("mdin") # Nonbonded method if mdp_opts['coulombtype'].lower() == 'pme': with open("mdin", 'a') as f: print >> f, """&ewald order=5, skinnb=0 /""" with open("mdin", 'a') as f: print >> f, """&debugf do_debugf=1, dumpfrc=1 /""" # Call sander for energy and force os.system('rm -f forcedump.dat') _exec("sander -O -y mdcrd", print_command=False) # Parse energy and force ParseMode = 0 Energies = [] Forces = [] Force = [] iatom = 0 isAtom = [atom.atomic_number > 0 for atom in Structure.atoms] for line in open('forcedump.dat'): line = line.strip() sline = line.split() if ParseMode == 1: if len(sline) == 1 and isfloat(sline[0]): Energies.append(float(sline[0]) * 4.184) ParseMode = 0 if ParseMode == 2: if len(sline) == 3 and all(isfloat(sline[i]) for i in range(3)): if isAtom[iatom]: Force += [float(sline[i]) * 4.184 * 10 for i in range(3)] iatom += 1 if len(Force) == 3 * sum(isAtom): Forces.append(np.array(Force)) Force = [] ParseMode = 0 iatom = 0 if line == '0 START of Energies': ParseMode = 1 elif line == '1 Total Force' or line == '2 Total Force': ParseMode = 2 # Obtain energy components ParseMode = 0 Ecomps = OrderedDict() for line in open("mdout").readlines(): if "NSTEP = " in line: ParseMode = 1 if ParseMode == 1: if "=" not in line: ParseMode = 0 continue else: ieq = None wkey = [] # Assume the line is split-able for i, w in enumerate(line.split()): if w == '=': ieq = i elif i - 1 == ieq: Ecomps.setdefault(' '.join(wkey), []).append(float(w) * 4.184) wkey = [] else: wkey.append(w) Ecomps_Sav = OrderedDict() for key in Ecomps: if set(Ecomps[key]) == set([0.0]): continue elif key.lower() in ['eptot', 'etot', 'volume', 'density']: continue else: Ecomps_Sav[key] = Ecomps[key][0] Ecomps_Sav['EPTOT'] = Ecomps['EPtot'][0] # Save just the first frame from the .mdcrd Energies = Energies[0] Forces = Forces[0] return Energies, Forces, Ecomps_Sav
def parse_inputs(input_file=None): """ Parse through the input file and read all user-supplied options. This is usually the first thing that happens when an executable script is called. Our parser first loads the default options, and then updates these options as it encounters keywords. Each keyword corresponds to a variable type; each variable type (e.g. string, integer, float, boolean) is treated differently. For more elaborate inputs, there is a 'section' variable type. There is only one set of general options, but multiple sets of target options. Each target has its own section delimited by the \em $target keyword, and we build a list of target options. @param[in] input_file The name of the input file. @return options General options. @return tgt_opts List of fitting target options. @todo Implement internal coordinates. @todo Implement sampling correction. @todo Implement charge groups. """ logger.info("Reading options from file: %s\n" % input_file) section = "NONE" # First load in all of the default options. options = deepcopy(gen_opts_defaults) # deepcopy to make sure options doesn't make changes to gen_opts_defaults options['root'] = os.getcwd() options['input_file'] = input_file tgt_opts = [] this_tgt_opt = deepcopy(tgt_opts_defaults) # Give back a bunch of default options if input file isn't specified. if input_file == None: return (options, [this_tgt_opt]) fobj = open(input_file) for line in fobj: try: # Anything after "#" is a comment line = line.split("#")[0].strip() s = line.split() # Skip over blank lines if len(s) == 0: continue key = s[0].lower() if key in bkwd: # Do option replacement for backward compatibility. key = bkwd[key] # If line starts with a $, this signifies that we're in a new section. if re.match('^\$',line): newsection = re.sub('^\$','',line).upper() if section in ["SIMULATION","TARGET"] and newsection in mainsections: tgt_opts.append(this_tgt_opt) this_tgt_opt = deepcopy(tgt_opts_defaults) if newsection == "END": newsection = "NONE" section = newsection elif section in ["OPTIONS","SIMULATION","TARGET"]: ## Depending on which section we are in, we choose the correct type dictionary ## and add stuff to 'options' and 'this_tgt_opt' (this_opt, opts_types) = (options, gen_opts_types) if section == "OPTIONS" else (this_tgt_opt, tgt_opts_types) ## Note that "None" is a special keyword! The variable will ACTUALLY be set to None. if len(s) > 1 and s[1].upper() == "NONE": this_opt[key] = None elif key in opts_types['strings']: this_opt[key] = s[1] elif key in opts_types['allcaps']: this_opt[key] = s[1].upper() elif key in opts_types['lists']: for word in s[1:]: this_opt.setdefault(key,[]).append(word) elif key in opts_types['ints']: if isfloat(s[1]): this_opt[key] = int(float(s[1])) else: this_opt[key] = int(s[1]) elif key in opts_types['bools']: if len(s) == 1: this_opt[key] = True elif s[1].upper() in ["0", "NO", "FALSE", "OFF"]: this_opt[key] = False elif isfloat(s[1]) and int(float(s[1])) == 0: this_opt[key] = False elif s[1].upper() in ["1", "YES", "TRUE", "ON"]: this_opt[key] = True elif isfloat(s[1]) and int(float(s[1])) == 1: this_opt[key] = True else: raise RuntimeError('%s is a true/false option but you provided %s; to enable, provide ["1", "yes", "true", "on" or <no value>]. To disable, provide ["0", "no", "false", or "off"].' % (key, s[1])) elif key in opts_types['floats']: this_opt[key] = float(s[1]) elif key in opts_types['sections']: this_opt[key] = ParsTab[key](fobj) else: logger.error("Unrecognized keyword: --- \x1b[1;91m%s\x1b[0m --- in %s section\n" \ % (key, section)) logger.error("Perhaps this option actually belongs in %s section?\n" \ % (section == "OPTIONS" and "a TARGET" or "the OPTIONS")) raise RuntimeError elif section == "NONE" and len(s) > 0: logger.error("Encountered a non-comment line outside of a section\n") raise RuntimeError elif section not in mainsections: logger.error("Unrecognized section: %s\n" % section) raise RuntimeError except: # traceback.print_exc() logger.exception("Failed to read in this line! Check your input file.\n") logger.exception('\x1b[91m' + line + '\x1b[0m\n') raise RuntimeError if section == "SIMULATION" or section == "TARGET": tgt_opts.append(this_tgt_opt) if not options['verbose_options']: printcool("Options at their default values are not printed\n Use 'verbose_options True' to Enable", color=5) return options, tgt_opts
def parse_inputs(input_file=None): """ Parse through the input file and read all user-supplied options. This is usually the first thing that happens when an executable script is called. Our parser first loads the default options, and then updates these options as it encounters keywords. Each keyword corresponds to a variable type; each variable type (e.g. string, integer, float, boolean) is treated differently. For more elaborate inputs, there is a 'section' variable type. There is only one set of general options, but multiple sets of target options. Each target has its own section delimited by the \em $target keyword, and we build a list of target options. @param[in] input_file The name of the input file. @return options General options. @return tgt_opts List of fitting target options. @todo Implement internal coordinates. @todo Implement sampling correction. @todo Implement charge groups. """ logger.info("Reading options from file: %s\n" % input_file) section = "NONE" # First load in all of the default options. options = deepcopy(gen_opts_defaults) # deepcopy to make sure options doesn't make changes to gen_opts_defaults options['root'] = os.getcwd() options['input_file'] = input_file tgt_opts = [] this_tgt_opt = deepcopy(tgt_opts_defaults) # Give back a bunch of default options if input file isn't specified. if input_file == None: return (options, [this_tgt_opt]) fobj = open(input_file) for line in fobj: try: # Anything after "#" is a comment line = line.split("#")[0].strip() s = line.split() # Skip over blank lines if len(s) == 0: continue key = s[0].lower() if key in bkwd: # Do option replacement for backward compatibility. key = bkwd[key] # If line starts with a $, this signifies that we're in a new section. if re.match('^\$',line): newsection = re.sub('^\$','',line).upper() if section in ["SIMULATION","TARGET"] and newsection in mainsections: tgt_opts.append(this_tgt_opt) this_tgt_opt = deepcopy(tgt_opts_defaults) if newsection == "END": newsection = "NONE" section = newsection elif section in ["OPTIONS","SIMULATION","TARGET"]: ## Depending on which section we are in, we choose the correct type dictionary ## and add stuff to 'options' and 'this_tgt_opt' (this_opt, opts_types) = (options, gen_opts_types) if section == "OPTIONS" else (this_tgt_opt, tgt_opts_types) ## Note that "None" is a special keyword! The variable will ACTUALLY be set to None. if len(s) > 1 and s[1].upper() == "NONE": this_opt[key] = None elif key in opts_types['strings']: this_opt[key] = s[1] elif key in opts_types['allcaps']: this_opt[key] = s[1].upper() elif key in opts_types['lists']: for word in s[1:]: this_opt.setdefault(key,[]).append(word) elif key in opts_types['ints']: if isfloat(s[1]): this_opt[key] = int(float(s[1])) else: this_opt[key] = int(s[1]) elif key in opts_types['bools']: if len(s) == 1: this_opt[key] = True elif s[1].upper() in ["0", "NO", "FALSE", "OFF"]: this_opt[key] = False elif isfloat(s[1]) and int(float(s[1])) == 0: this_opt[key] = False elif s[1].upper() in ["1", "YES", "TRUE", "ON"]: this_opt[key] = True elif isfloat(s[1]) and int(float(s[1])) == 1: this_opt[key] = True else: logger.error('%s is a true/false option but you provided %s; to enable, provide ["1", "yes", "true", "on" or <no value>]. To disable, provide ["0", "no", "false", or "off"].\n' % (key, s[1])) raise RuntimeError elif key in opts_types['floats']: this_opt[key] = float(s[1]) elif key in opts_types['sections']: this_opt[key] = ParsTab[key](fobj) else: logger.error("Unrecognized keyword: --- \x1b[1;91m%s\x1b[0m --- in %s section\n" \ % (key, section)) logger.error("Perhaps this option actually belongs in %s section?\n" \ % (section == "OPTIONS" and "a TARGET" or "the OPTIONS")) raise RuntimeError elif section == "NONE" and len(s) > 0: logger.error("Encountered a non-comment line outside of a section\n") raise RuntimeError elif section not in mainsections: logger.error("Unrecognized section: %s\n" % section) raise RuntimeError except: # traceback.print_exc() logger.exception("Failed to read in this line! Check your input file.\n") logger.exception('\x1b[91m' + line + '\x1b[0m\n') raise RuntimeError if section == "SIMULATION" or section == "TARGET": tgt_opts.append(this_tgt_opt) if not options['verbose_options']: printcool("Options at their default values are not printed\n Use 'verbose_options True' to Enable", color=5) # Expand target options (i.e. create multiple tgt_opts dictionaries if multiple target names are specified) tgt_opts_x = [] for topt in tgt_opts: for name in topt['name']: toptx = deepcopy(topt) toptx['name'] = name tgt_opts_x.append(toptx) return options, tgt_opts_x
def Calculate_AMBER(Structure, mdp_opts): pbc = mdp_opts["pbc"].lower() == "xyz" # Create AMBER inpcrd file inpcrd = amber.AmberAsciiRestart("inpcrd", mode="w") inpcrd.coordinates = np.array(Structure.positions.value_in_unit(u.angstrom)).reshape(-1, 3) inpcrd.box = Structure.box inpcrd.close() # sander insists on providing a trajectory to iterate over, # so we feed it the same coordinates again. But we don't use it # because the positions are imprecise. mdcrd = amber.AmberMdcrd("mdcrd", natom=len(Structure.atoms), hasbox=pbc, mode="w") mdcrd.add_coordinates(np.array(Structure.positions.value_in_unit(u.angstrom)).reshape(-1, 3)) if pbc: mdcrd.add_box(Structure.box[:3]) mdcrd.close() # Create AMBER prmtop object from ParmEd Structure :) prmtop = amber.AmberParm.from_structure(Structure) prmtop.write_parm("prmtop") # Create AMBER mdin file and append some stuff mdin = Mdin() # Single point energies? mdin.change("cntrl", "imin", "5") # Periodic boundary conditions? if pbc: mdin.change("cntrl", "ntb", "1") else: mdin.change("cntrl", "ntb", "0") # Cutoff zero is really infinite if float(mdp_opts["rlist"]) == 0.0: mdin.change("cntrl", "cut", "9999") else: mdin.change("cntrl", "cut", str(int(float(mdp_opts["rlist"]) * 10))) # Take zero MD steps mdin.change("cntrl", "nstlim", "0") # Don't update nonbond parameters mdin.change("cntrl", "nsnb", "0") # if mdp_opts['coulombtype'].lower() == 'pme': # mdin.change('ewald','order',5) # mdin.change('ewald','skinnb',0) mdin.write("mdin") # Nonbonded method if mdp_opts["coulombtype"].lower() == "pme": with open("mdin", "a") as f: print >> f, """&ewald order=5, skinnb=0 /""" with open("mdin", "a") as f: print >> f, """&debugf do_debugf=1, dumpfrc=1 /""" # Call sander for energy and force os.system("rm -f forcedump.dat") _exec("sander -O -y mdcrd", print_command=False) # Parse energy and force ParseMode = 0 Energies = [] Forces = [] Force = [] iatom = 0 isAtom = [atom.atomic_number > 0 for atom in Structure.atoms] for line in open("forcedump.dat"): line = line.strip() sline = line.split() if ParseMode == 1: if len(sline) == 1 and isfloat(sline[0]): Energies.append(float(sline[0]) * 4.184) ParseMode = 0 if ParseMode == 2: if len(sline) == 3 and all(isfloat(sline[i]) for i in range(3)): if isAtom[iatom]: Force += [float(sline[i]) * 4.184 * 10 for i in range(3)] iatom += 1 if len(Force) == 3 * sum(isAtom): Forces.append(np.array(Force)) Force = [] ParseMode = 0 iatom = 0 if line == "0 START of Energies": ParseMode = 1 elif line == "1 Total Force" or line == "2 Total Force": ParseMode = 2 # Obtain energy components ParseMode = 0 Ecomps = OrderedDict() for line in open("mdout").readlines(): if "NSTEP = " in line: ParseMode = 1 if ParseMode == 1: if "=" not in line: ParseMode = 0 continue else: ieq = None wkey = [] # Assume the line is split-able for i, w in enumerate(line.split()): if w == "=": ieq = i elif i - 1 == ieq: Ecomps.setdefault(" ".join(wkey), []).append(float(w) * 4.184) wkey = [] else: wkey.append(w) Ecomps_Sav = OrderedDict() for key in Ecomps: if set(Ecomps[key]) == set([0.0]): continue elif key.lower() in ["eptot", "etot", "volume", "density"]: continue else: Ecomps_Sav[key] = Ecomps[key][0] Ecomps_Sav["EPTOT"] = Ecomps["EPtot"][0] # Save just the first frame from the .mdcrd Energies = Energies[0] Forces = Forces[0] return Energies, Forces, Ecomps_Sav