Source code for schrodinger.application.macromodel.utils

"""
Utilities for writing MacroModel com, sbc, and hst (native input) files.

Copyright Schrodinger, LLC. All rights reserved.

"""

# Contributors:  K Shawn Watts

################################################################################
# Globals/Constants
################################################################################

import os
import re
import warnings
from past.utils import old_div

import schrodinger.infra.mm as mm
import schrodinger.structure as structure
import schrodinger.utils.fileutils as fileutils

_version = '$Revision: 1.32.2.1 $'

################################################################################
# Packages
################################################################################

try:
    import schrodinger.job.jobcontrol as jobcontrol
except ImportError:
    jobcontrol = None

################################################################################
# Functions
################################################################################


[docs]def write_hst_file(com_file, host_list): """ Returns the name of the jobname.hst file written specifically for the passed com file. jobname.com -> jobname.hst. host_list is a list of hostentry name strings, the attributes are looked up by jobcontrol.get_host(). If schrodinger.job.jobcontrol can't be imported it returns an empty string. These file are typically only used for NPRC distributed bmin jobs. """ if not jobcontrol: return '' hst_file = '%s.hst' % com_file[:-4] hst_fh = open(hst_file, 'w') hst_fh.write("# host file for %s\n" % com_file) for hostentry in host_list: host = jobcontrol.get_host(hostentry) for host_attribute in str(host).split(','): hst_fh.write(host_attribute.strip()) hst_fh.write("\n") hst_fh.write("\n") hst_fh.flush() hst_fh.close() return hst_file
################################################################################ # Classes ################################################################################
[docs]class ComUtil: """ A class for writing MacroModel com files. The class has methods to write jobname.com files for a broad range of calculation types. The class is initallized with reasonable OPCD argument default values, so the methods like mini() are usable 'out of the box'. The OPCD arguments are easily modified by accessing the dict values. There is a generic writeComFile() method that allows you write any com file by passing a list of arguments, IO and OPCDs. If no arguments are provide to the constructor the defaults are: - Potential energy surface is OPLS_2005, gas phase, with extended non-bonded cutoffs. - Minimization run up to 50000 iterations of PRCG. Convergence is set to a gradient of 0.01. - Energy window is 50 kJ/mol and is only checked at the end of the minimization. - MacroModel/Maestro interaction files are not generated. Enable by setting self.mmod = True. - Atom distance for conformer equivalence is 0.25 angstroms. API examples:: # Example 1 ############################################################ # Writing an energy listing com file via writeComFile. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil() # create a default instance of the class com_file_args = [ 'example1.com', # The name of the com file to write. 'input.mae', # The name of the input structure file. 'output.mae', # The name of the output structure file. 'EXNB', 'BDCO', 'FFLD', 'READ', 'ELST' ] mcu.writeComFile(com_file_args) # Example 2 ############################################################ # Writing an energy listing com file via a utility methods. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil() com_file_name = mcu.elst('example2.mae') # Example 3 ############################################################ # Writing an minimization com file with customized parameters. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil() mcu.MINI[1] = 9 # Use Truncated Newton Conjugate Gradient minimizer. mcu.CONV[5] = 0.0001 # Halt when gradient reaches this stringent value. mcu.mini('example3.mae') # Example 4 ############################################################ # Writing an minimization com file that includes water GB/SA solvation. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil(solv=True) mcu.mini('example4.mae') # Example 5 ############################################################ # Writing an minimization com file that requests a substructure. # See the SbcUtil class for how to construct a .sbc file, this # example assumes an appropriate .sbc file already exists. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil(subs=True) mcu.mini('example5.mae') :ivar serial_nonconf_input: If True enable DEBG 55 property management when self.serial is also True. :vartype serial_nonconf_input: boolean :ivar cgo3: If True enable the writing of CGO3 to com files. By default bdco=True and the opcode is written if it appears in the list of opcodes. :vartype cgo3: boolean :ivar cgo4: If True enable the writing of CGO3 to com files. By default bdco=True and the opcode is written if it appears in the list of opcodes. :vartype cgo4: boolean :ivar cgo5: If True enable the writing of CGO5 to com files. By default bdco=True and the opcode is written if it appears in the list of opcodes. :vartype cgo5: boolean :ivar cgo6: If True enable the writing of CGO6 to com files. By default bdco=True and the opcode is written if it appears in the list of opcodes. :vartype cgo6: boolean :ivar beautify: If True don't write disabled opcds. If False, disabled opcds are printed as commented-out lines. Default is True :vartype beautify: boolean :ivar refit_args: If True reformat large float value to fit in the alternate field format (%6.3f - %9.0f). If False, values are printed as %5.4f Default is True. :vartype refit_args: boolean :ivar mmod: If True enable MMOD and write MacroModel/Maestro interaction-monitor files. This is seldom useful in a script context, but is provided to as an option to make com files look more like Maestro generated files. Default is False. :vartype mmod: boolean :ivar structure_file_ext: Default structure file extention for file names automatically determined by outComFile(). Default is '.mae'. :vartype structure_file_ext: string """
[docs] def __init__(self, ffld="oplsaa2005", solv=False, ddde=False, bdco=True, chgf=False, exnb=True, auto=True, auop=True, subs=False, serial=False, demx=True, demx_final=50, demx_prelim=100, algn=False, nant=False, chyd=True, nprc=False, flap=False, mcrc=False, ddebug=False, nice=False, wait=False, host="", hostfile="", arch="", local=False, interval=5, no_redirect=False, tmpdir="", ver="", rel="", proj="", disp="", user="", para_bmin=False, para_bmin_jobcts=100, para_bmin_njobs=10, para_bmin_output_org="", debug=False, beautify=True, refit_args=True): """ This method loads the default data members and methods. It sets default OPCD arguments, and com file preferences (e.g. no solvent model, OPLSAA_2005, yes to BDCO). :param ffld: String identifier for the force field. The FFLD value is assigned by regular expression evaluation of the string. :type ffld: string :param solv: If True enable the writing of SOLV to com files. By default solv=False and the opcode is not written, even if it appears in the list of opcodes. :type solv: boolean :param ddde: If True enable distance-dependent dielectric electrostatic treatment, with a dielectric constant of 4.0. :type ddde: boolean :param serial: If True enable serial processing mode. This sets AUTO arg6=1, and MCOP arg4=1 where appropriate. :type serial: boolean :param bdco: If True enable the writing of BDCO to com files. By default bdco=True and the opcode is written if it appears in the list of opcodes. :type bdco: boolean :param subs: If True enable the writing of SUBS to com files. By default subs=False and the opcode is not written, even if it appears in the list of opcodes. :type subs: boolean :param chgf: If True enable the writing of CHGF to com files. By default chgf=False and the opcode is not written, even if it appears in the list of opcodes. :type chgf: boolean :param exnb: If True enable the writing of EXNB to com files. By default exnb=True. If False it is not written, even if it appears in the list of opcodes. :type exnb: boolean :param auto: If True enable the writing of AUTO to com files. By default auto=True. If False it is not written, even if it appears in the list of opcodes. :type auto: boolean :param auop: If True enable the writing of AUOP to com files. By default auop=True. If False it is not written, even if it appears in the list of opcodes. :type auop: boolean :param nant: If True enable the writing of NANT to com files. By default nant=False. If False it is not written, even if it appears in the list of opcodes. :type nant: boolean :param algn: If True enable the writing of COPY/ALGN to MBAE com files generated by the pre-defined methods, e.g. mbaeCsLmod() :type algn: boolean :param demx: If True enable the writing of DEMX to com files. By default demx=True. If False it is not written, even if it appears in the list of opcodes. :type demx: boolean :param demx_final: Energy window for the final DEMX test. Default is 50 kJ/mol :type demx_final: float :param demx_prelim: Energy window for the preliminary DEMX test. Default is 100 kJ/mol. By default DEMX arg2 is set to 10000, so the prelimnary test is seldom performed. :type demx_prelim: float """ ## # Data members ## # version self.version = '$Revision: 1.32.2.1 $' self._version = self.version # Adopt current _version convention self._debug = debug # this class only, not MacroModel # These modify the command expression returned by getLaunchCommand() self.ddebug = ddebug # verbose jobcontrol debugging self.nice = nice # niced jobs finish last self.wait = wait # return prompt option self.host = host # run jobs locally self.hostfile = hostfile # use selected hostfile self.proj = proj # maestro project path self.disp = disp # maestro project disposition self.user = user # user id for job invocation self.arch = arch # platform architechure self.local = local # no file copies self.interval = interval # jobcontrol monitoring interval (5 is typical) self.no_redirect = no_redirect # output redirection self.tmpdir = tmpdir # temp file directory self.ver = ver # schrodinger build path self.rel = rel # schrodinger build release self.para_bmin = para_bmin # use utilites/para_bmin, not bmin self.para_bmin_jobcts = para_bmin_jobcts # pbmin max structs/subjob self.para_bmin_njobs = para_bmin_njobs # pbmin num of subtasks self.para_bmin_output_org = para_bmin_output_org # pbmin output # These modify the OPCD in getOpcdArgs(), a '!' comment turns off OPCD self.solv = solv # GB/SA with water if true self.exnb = exnb # extended nonbonded distances (8 vdw, 20 q-q) if true self.bdco = bdco # cutoffs based on interaction type, smart mu cutoffs self.chgf = chgf # partial atomic charges from structure file, not ffld self.ddde = ddde # dist dependent electrostat., dielectric epsilon=4 self.auto = auto # auto setup for mult-MINI, MCMM, mixed MCMM low-mode self.auop = auop # auop modifiers self.subs = subs # use sbc file if true self.serial = serial # AUTO/MCOP set for serial if true self.demx = demx # use delta energy window if true self.algn = algn # use ALGN/COPY to position ligands in MBAE if true self.chyd = chyd # disable hybond dipoles if true self.nant = nant # don't consider enantiomers to be duplicates if true self.nprc = nprc # enable dbmin self.flap = flap # enable FLAP ring vertex sampling. self.mcrc = mcrc # enable MCRC ring template. self.mmod = False # enable MacroModel/Maestro interaction files. self.serial_nonconf_input = False # Set DEBG 55 property management if self.serial is also True. # ffld, demx_final and demx_prelim bound below self.cgo3 = True self.cgo4 = True self.cgo5 = True self.cgo6 = True # These track and control how OPCD are writen in writeComFile() self.beautify = beautify # if true, don't print commented-out opcds self.refit_args = refit_args # if true, quietly refit to max value self._written = [] # array of opcd written, used to test multiplicity self.structure_file_ext = '.mae' # File extension in outComFile() # MacroModel debugging-switches self.DEBG = {} # assoc. array of debug switches # Input structure reading commands. self.READ = {} self.READ[1] = 0 self.BGIN = {} self.BGIN[1] = 0 self.BGIN[2] = 0 # MacroModel force field args self.FFLD = {} self.FFLD[1] = 14 # OPLS_2005 - unmatched ffld string assignment. self.FFLD[2] = 1 # constant dielectric treatment self.FFLD[3] = 0 # ffld h-bond self.FFLD[4] = 0 # BMFF option self.FFLD[5] = 1.0 # dielectric constant # force field selection requires some regex mm2 = re.compile(r'^MM2$', re.IGNORECASE) mm3 = re.compile(r'^MM3$', re.IGNORECASE) amber = re.compile(r'^AMBER\*?$', re.IGNORECASE) amber94 = re.compile(r'^AMBER94$', re.IGNORECASE) opls = re.compile(r'^OPLS$', re.IGNORECASE) mmff = re.compile(r'^MMFF(-|_)?(94)?$', re.IGNORECASE) mmffs = re.compile(r'^MMFF(-|_)?(94)?s(94)?$', re.IGNORECASE) opls_2003 = re.compile(r'^OPLS-?(AA)?(-|_)?(2003)$', re.IGNORECASE) opls_2005 = re.compile(r'^OPLS-?(AA)?(-|_)?(2005)$', re.IGNORECASE) opls_2_x = re.compile(r'^OPLS2\.(0|1)$', re.IGNORECASE) if mm2.match(ffld): self.FFLD[1] = 1 elif mm3.match(ffld): self.FFLD[1] = 2 elif amber.match(ffld): self.FFLD[1] = 3 elif amber94.match(ffld): self.FFLD[1] = 4 elif opls.match(ffld): self.FFLD[1] = 5 elif mmff.match(ffld): self.FFLD[1] = 10 self.FFLD[4] = 0 # turn off BMFF elif mmffs.match(ffld): self.FFLD[1] = 10 self.FFLD[4] = 1 # turn on BMFF elif opls_2003.match(ffld): self.FFLD[1] = 14 elif opls_2005.match(ffld): # keep for back compatibility self.FFLD[1] = 14 elif mm.opls_name_to_version(ffld) == 14: self.FFLD[1] = 14 elif opls_2_x.match(ffld): # keep for back compatibility self.FFLD[1] = 16 elif mm.opls_name_to_version(ffld) == 16: self.FFLD[1] = 16 # MacroModel solvent args self.SOLV = {} self.SOLV[1] = 3 # GB/SA self.SOLV[2] = 1 # water # MacroModel extended nonbonded args self.EXNB = {} self.EXNB[1] = 0 # just leverage BDCO self.EXNB[2] = 5 # close/long range cutoff self.EXNB[5] = 8.0 # vdW cutoff, A self.EXNB[6] = 20.0 # q-q cutoff, A self.EXNB[7] = 4.0 # H-bond cutoff, A self.EXNB[8] = 8.0 # Fmm cutoff for fixed/frozen atoms # MacroModel bond dipole cutoff args self.BDCO = {} self.BDCO[5] = 0.0 # q-mu cutoff = sqrt((cutoff_q-q^3)) self.BDCO[6] = 99999.0 # q-q cutoff, ~none # MacroModel charge file args self.CHGF = {} self.CHGF[1] = 0 # charges from input structure file # MacroModel energy list args self.ELST = {} self.ELST[1] = -1 # just energy to log file self.ELST[2] = 0 # kJ/mol self.DLST = {} self.DLST[3] = 3 # really, really complete # MacroModel geometry optimization self.CONV = {} self.CONV[1] = 2 # converge on derivative gradient self.CONV[2] = 0 # extent modifier self.CONV[5] = 0.01 # extent converge on gradient self.MINI = {} self.MINI[1] = 1 # PRCG, ok general and best for large structures self.MINI[2] = 0 # default line searching self.MINI[3] = 50000 # iterations self.MINI[4] = 0 # DEMX window id self.MINI[5] = 0 # default step-size buffer self.MINI[6] = 0.001 # hessian cutoff, where appropriate self.MINI[7] = 0.0 # update nonbond tied to vdw self.MINI[8] = 0 # report interval energy/rms grad/ rms move self.MINI[9] = 1 # PRCG, best general and large structures self.MINI[10] = 0 # default line searching self.MINI[11] = 50000 # iterations self.MINI[12] = 0 # DEMX window id self.MINI[13] = 0 # default step-size buffer self.MINI[14] = 0.001 # hessian cutoff, where appropriate self.MINI[15] = 0.0 # update nonbond tied to vdw self.MINI[16] = 0 # report energy/rms grad/ rms move # MacroModel MBAE (ediff defaults) self.MBAE = {} self.MBAE[1] = 1 # ediff self.MBAE[2] = 0 # mini calc self.MBAE[3] = 0 # save complex self.MBAE[9] = -1 # turn off mbae # MacroModel ASET args for MBAE self.ASET = {} # MacroModel geometry drives # distance scan A-B, E-F # angle scan A-B-C, E-F-G # torsion scan A-B-C-D, E-F-G-H # Nsteps = |arg5-arg6|/arg7 + 1, with a max of 100 self.DRIV = {} # MacroModel mult minimization filter args self.DEMX = {} self.DEMX[1] = 0 # MINI window id self.DEMX[ 2] = 10000 # pretest E after arg2 iterations=>pretest unlikely self.DEMX[5] = demx_final # window for final test, kJ/mol [50 kJ/mol] self.DEMX[6] = demx_prelim # window for pre test, kJ/mol [100 kJ/mol] # MacroModel logP for mini # DEBG with 530, 531 self.LOGP = {} self.LOGP[2] = 9 # water->octanol # MacroModel Molecular Symmetry Library self.MSYM = {} self.MSYM[1] = 1 # use it # MacroModel low mode csearch args self.LMCS = {} self.LMCS[1] = 1000 # step search self.LMCS[2] = 0 # max stored structs = arg1 or 10,000 self.LMCS[3] = 10 # 10 pure low modes explored self.LMCS[4] = 0 # global search self.LMCS[5] = 0 # single LMCS steps self.LMCS[6] = 0.25 # allowed approach distance in A self.LMCS[7] = 3.0 # minimum distance, A self.LMCS[8] = 6.0 # maximum distance, A self.LMCS[9] = 1000 # step search self.LMCS[10] = 0 # max stored structs = arg1 or 10,000 self.LMCS[11] = 10 # 10 pure low modes explored self.LMCS[12] = 0 # global search self.LMCS[13] = 0 # single LMCS steps self.LMCS[14] = 0.25 # allowed approach distance in A self.LMCS[15] = 3.0 # minimum distance, A self.LMCS[16] = 6.0 # maximum distance, A # MacroModel large scale low mode csearch args self.LMC2 = {} self.LMC2[1] = 1000 # search steps self.LMC2[2] = 0 # keep upto arg1 structs self.LMC2[3] = 30 # number of lowmodes self.LMC2[4] = 0 # global search mode self.LMC2[5] = 0 # calc only the first time self.LMC2[6] = 0.25 # allowed approach fraction of vdw self.LMC2[7] = 3.0 # min dist self.LMC2[8] = 6.0 # max dist self.ARPK = {} self.ARPK[1] = 0 # analytical hessian treatment self.ARPK[2] = 300 # dimension of small prob self.ARPK[3] = 450 # number of small probs self.ARPK[4] = 200 # MB of memory (arg1=0) self.ARPK[5] = 0 # default accuracy 0.0001 self.ARPK[6] = 0 # not used with arg1=0 self.ARPK[7] = 0.01 # not used with arg1=0 self.ARPK[8] = 0.001 # sparse hessian cutoff # MacroModel confsearch general self.MCSS = {} self.MCSS[1] = 2 # use directed search self.MCSS[2] = 0 # don't modify arg5 energy window self.MCSS[3] = 0 # don't use torsional memory self.MCSS[5] = self.DEMX[5] # e window for start point acceptance self.MCOP = {} self.MCOP[1] = 1 # report every step self.MCOP[4] = 0 # lcms serial search if > 0 self.MCOP[5] = 0 # fraction of mols/tors moves self.MCOP[6] = 0 # maximum number of confs kept self.MCOP[7] = 0 # number of confs read for csrch seed self.MCOP[9] = 1 # report every step self.MCOP[12] = 1 # lcms serial search if > 0 self.MCOP[14] = 0 # maximum number of confs kept self.MCOP[15] = 0 # number of confs read for csrch seed self.NANT = {} # takes no args self.CRMS = {} self.CRMS[5] = 4.184 # max energy diff required to skip geometric comp self.CRMS[6] = 0.25 # max dist between 'equivalent' corresponding atoms self.CRMS[7] = 60.0 # maximum dihedral angle change for polar hydrogens self.SEED = {} self.SEED[1] = 0 # random number generator seed self.COMP = {} # this is more for addc, util.py methods use AUTO self.ADDC = {} self.ADDC[1] = 0 # Do not use Jaguar energies self.ADDC[2] = 0 # Store at max. 10,000 structures # MacroModel ConfGen torsion searches self.CGEN = {} self.CGEN[1] = 1000 # number of CGEN steps self.CGEN[2] = 0 # save up to arg1 results self.CGEN[4] = 2 # sample all combinations of peripheral groups self.CGEN[6] = 0.25 # closest vdw approach self.CGOP = {} self.CGOP[1] = 0 # look for symmetry in terminal groups self.CGOP[2] = 2 # use ring_conf library for sampling rings self.CGOP[3] = 500 # minimization iterations self.CGOP[4] = 1 # sample amide geometry self.CGOP[5] = 20 # maximum relative ring conformation energy in kJ/mol self.CGOP[6] = 8.0 # max num of total ring confs self.CGOP[7] = 2.0 # max num of confs per ring system self.CGOP[8] = 50.0 # maximum relative internal (confgen) energy self.CGO2 = {} self.CGO2[5] = 0.6 # vdw radii scale factor for close approach self.CGO2[6] = 1.0 # scale factor for close atom gradients/penalty self.CGO2[7] = 0.0 # min vdw atom radius self.CGO3 = {} # sp2-sp3 small barrier sampling self.CGO3[1] = 6 # Cosine function frequency, number of minima self.CGO3[5] = 12.0 # Energy range between min and max in cosine pot'l self.CGO3[6] = 0.0 # Don't eliminate high energy minima self.CGO3[7] = 1000.0 # Restraint prefactor (v1?) self.CGO3[8] = 10.0 # in degrees, half-width of flat bottom well. self.CGO4 = {} # q-q contact Guassian penalty self.CGO4[5] = 5.0 # in Ang, standard deviaton of Gaussian penalty, s self.CGO4[6] = 2.5 # maximum value for Gaussian penalty, A self.CGO4[7] = 0.75 # Penalty cutoff self.CGO5 = {} # q-h_bond contact Guassian penalty self.CGO5[5] = 5.0 # in Ang, standard deviaton of Gaussian penalty, s self.CGO5[6] = 1.0 # maximum value for Gaussian penalty, A self.CGO5[7] = 0.25 # Penalty cutoff self.CGO6 = {} # close contact Guassian penalty self.CGO6[5] = 2.5 # in Ang, standard deviaton of Gaussian penalty, s self.CGO6[6] = 0.1 # maximum value for Gaussian penalty, A self.CGO6[7] = 1.00 # Penalty cutoff self.CHYD = {} self.CHYD[1] = 1 # turn off hydrogen bond electrostatics self.CHYD[2] = 0 # self.CHYD[3] = 0 # self.CHYD[4] = 0 # self.CHYD[5] = 0.0 # self.CHYD[6] = 0.0 # self.CHYD[7] = 0.0 # self.CHYD[9] = 0.0 # self.FLAP = {} self.FLAP[5] = 0.5 # probability of using a FLAP step. self.MCRC = {} self.MCRC[1] = 0 # use ring templates in conformational search. self.MCRC[5] = 0.5 # probability of using a template. # MacroModel monte carlo confsearches self.MCNV = {} self.MCNV[1] = 1 # min number DOF altered self.MCNV[2] = 0 # max number DOF altered => entire system self.MCNV[3] = 0 # don't use torsional clusters self.MCMM = {} self.MCMM[1] = 1000 # iterations search self.MCMM[2] = 0 # save up to arg1 results self.MCMM[4] = 0 # global seach mode self.MCMM[6] = 0.25 # closest vdW approach self.MCMM[9] = 1000 # iterations search self.MCMM[10] = 0 # save up to arg1 results self.MCMM[12] = 0 # global seach mode self.MCMM[14] = 0.25 # closest vdW approach self.SPMC = {} self.SPMC[1] = 1000 # iterations search self.SPMC[2] = 0 # save up to arg1 results self.SPMC[3] = 24 # 360/arg3 degs max res of tors mods 15 degs self.SPMC[4] = 0 # global seach mode self.SPMC[6] = 0.25 # closest vdW approach # DEBG with 520, 521 self.AUTO = {} self.AUTO[1] = 0 # use it, new setup self.AUTO[2] = 2 # comp new setup with heavy + OH self.AUTO[3] = 1 # chig atoms, new setup self.AUTO[4] = 1 # torc, new setup self.AUTO[5] = 1 # tors, new setup self.AUTO[6] = -1.0 # non-serial self.AUTO[7] = 5.0 # minimum ring size to setup self.AUTO[8] = 0.0 # 'restrictive' sampling (MacroModel 9.0 deflault) self.AUOP = {} self.AUOP[5] = -1 # N search steps = (arg5)*(number of torsions+mols) # -1 so we get the same ComUtil behavior as always # MacroModel Molecular Dynamic args self.MDYN = {} self.MDYN[1] = 0 # no .mmo listing self.MDYN[2] = 1 # SHAKE bonds to H. Don't SHAKE MCSD jobs self.MDYN[3] = 1 # Stochastic self.MDYN[4] = 0 # 25 fs enthalpy data collation interval* self.MDYN[5] = 1.5 # time step (fs) self.MDYN[6] = 1 # simulation times, ps self.MDYN[7] = 300.0 # bath temp, K self.MDYN[8] = 0.2 # bath time constant self.MDYN[9] = 0 # no .mmo listing self.MDYN[10] = 1 # SHAKE bonds to H. Don't SHAKE MCSD jobs self.MDYN[11] = 1 # Stochastic self.MDYN[12] = 0 # 25 fs enthalpy data collation interval* self.MDYN[13] = 1.5 # time step (fs) self.MDYN[14] = 1 # simulation times, ps self.MDYN[15] = 300.0 # bath temp, K self.MDYN[16] = 0.2 # bath time constant # * this dynamically assigned based on run length: # 5 fs for runs < 10 ps long # >25 fs for runs > 1000 ps long self.MDIT = {} self.MDIT[5] = 300.0 # initial temp, K (~27 deg C) self.MDFT = {} self.MDFT[5] = 300.0 # final temp, K (~27 deg C) self.MDVE = {} # arg1=0(write) arg1=1(read) # MacroModel Monte Carlo/Stochastic Dynamic mixed mode self.MCSD = {} self.MCSD[1] = 1 # 1:1 mc/sd self.MCSD[5] = 0 # acceptance ratio # MacroModel structure selection self.MDSA = {} self.MDSA[1] = 10 # write 10 structures # MacroModel Metropolis Monte Carlo self.MCLO = {} self.MCLO[1] = 1 # list to mmo file self.MCLO[3] = -1 # perform one million steps self.MCLO[7] = 300 # temp, kelvin # MacroModel IMPS/JBW/ADF self.IMPS = {} self.IMPS[1] = 1 # perform IMPS transforms self.IMPS[2] = 0 # all trials equally probable self.IMPS[7] = -10.0 # transform if stuck after one million ps self.IMPO = {} self.IMPO[1] = 1 # print E matix to log file self.IMPO[2] = 0 # abort if ediff exceeds threshold self.IMPO[3] = 0 # write only high energy structures self.IMPO[4] = 0 # no .ino output self.IMPO[5] = 20 # conversion threshold, kJ self.IMPO[6] = -1.0 # compare with COMP # MacroModel ZMAT args self.ZMAT = {} # all numerical args, groups of eight # MacroModel Free energy perturbation args self.FESA = {} self.FESA[5] = 0.0 # start of left side window self.FESA[6] = 0.05 # start of right side window # this default calls for 20 lambda windows # MacroModel loop modeling/rebuilding self.LOOP = {} self.LOOP[1] = 0 # N-terminus: Nitrogen's atom number self.LOOP[2] = 0 # C-terminus: Carbonyl Carbon's atom number self.LOOP[3] = 0 # generate alt confs of input loop (1=new seq) self.LOOP[4] = 100 # number of confs to generate self.LOOP[5] = 10000 # max number of confs to keep self.LOOP[6] = 0.25 # allowed approach distance: arg6*(sum(vdW-radii)) self.LOOP[7] = 0 # generate COMP and CHIG for heavy atoms in loop self.LPOP = {} # # MacroModel GEOM self.GEOM = {} # MacroModel Align/copy self.ALGN = {} self.ALGN[1] = 3 # center and princ axes align with ref self.ALGN[2] = 1 # weight atoms by atomic mass self.ALGN[3] = 5 # generate all four and write # primary, primary*C2, secondary, secondary*C2 # MacroModel MINTA args self.MNTA = {} self.MNTA[1] = 5 # MINTA interations: number of blocks self.MNTA[2] = 2000 # evaluations per block self.MNTA[3] = 0 # non-adaptive mode (default) self.MNTA[4] = 0 # numerical integration all DOFs (default) self.MNTA[5] = 300.0 # temp, Kelvin self.MNTA[6] = 1.0 # Ang dist from ideal geom, hard limit self.MNTA[7] = 3.0 # Stdev from ideal geom, soft limit # MacroModel SUBS, FXAT, FXCO, FXDI, FXTA, FXBA, # Note: ASL1, ASL2 don't belong in .com files, use SbcUtil instead self.SUBS = {} # native potential (may all have FXAT constraint) self.FXAT = {} # constrained/frozen atoms self.FXDI = {} # constrain distance self.FXTA = {} # constrain torsion angle self.FXBA = {} # constrain bond angle self.FXCO = {} # constrain all torsions # MacroModel distributed bmin self.NPRC = {} self.NPRC[1] = 4 # four hosts self.NPRC[2] = 100 # steps or molecules per block self.NPRC[3] = 60 # 60 sec interval for internal master checkups self.NPRC[4] = 0 # no energy pre-test # MacroModel oscillator calcs self.MTST = {} self.MTST[1] = 0 # no listing of freqs self.MTST[5] = 2.0 # lower freq limit in wavenumbers (nu-bar) self.RRHO = {} self.RRHO[1] = 0 # summary in log file self.RRHO[2] = 0 # calc: trans, rot and vib self.RRHO[3] = 1 # symmetry self.RRHO[5] = 300 # temp in K self.RRHO[6] = 1.0 # volume in L self.RRHO[7] = 2.0 # lower freq limit in wavenumbers (nu-bar) self.VIBR = {} self.VIBR[1] = 1 # first mode to animate self.VIBR[2] = 0 # last mode (0 => only mode arg1 will be animated) self.VIBR[3] = 10 # number of frames per 1/4 period self.VIBR[4] = 0 # print just eigenvalues to log self.VIBR[5] = 1.0 # amplitude self.VBR2 = {} self.VBR2[1] = 1 # first mode to animate self.VBR2[2] = 0 # last mode (0 => only mode arg1 will be animated) self.VBR2[3] = 10 # number of frames per 1/4 period self.VBR2[4] = 0 # print just eigenvalues to log self.VBR2[5] = 5.0 # amplitude self.VBR2[6] = 0.0001 # min. magnitude of eigenvalue for 'real' modes #For ligprep information self.MXAT = {} self.MXAT[1] = 0 self.MXAT[2] = 0 self.MXAT[3] = 0 self.MXAT[4] = 0 self.MXAT[5] = 0.000 self.MXAT[6] = 0.000 self.MXAT[7] = 0.000 self.MXAT[8] = 0.000 self.CHIP = {} self.CHIP[1] = 0 self.CHIP[2] = 0 self.CHIP[3] = 0 self.CHIP[4] = 0 self.CHIP[5] = 0.000 self.CHIP[6] = 0.000 self.CHIP[7] = 0.000 self.CHIP[8] = 0.000 self.CHOP = {} self.CHOP[1] = 0 self.CHOP[2] = 0 self.CHOP[3] = 0 self.CHOP[4] = 0 self.CHOP[5] = 0.000 self.CHOP[6] = 0.000 self.CHOP[7] = 0.000 self.CHOP[8] = 0.000 self.SPAT = {} # MacroModel/Maestro interaction. self.MMOD = {} self.MMOD[1] = 1 # Default. write mon.mae as frequently as possible. self.MMOD[2] = 1 # Recolor atoms by energy gradient. # Make collective settings (i.e. ddde, serial) so the # instance looks self-consistent. These setting are enforced # again in getOpcdArgs() if self.ddde: self.solv = False # mutually exclusive because epsilon != 1 self.FFLD[2] = 2 # distance dependent self.FFLD[5] = 4.0 # epsilon if self.serial: self.AUTO[6] = 1 # done with init return None
[docs] def writeComFile(self, com_args=[]): # noqa: M511 """ This method writes a com file, and returns the name of the written com file. It requires a list containing the name of the com file to be written, the name of the input file, the name of the output file, and a series of OPCDs. The arguments for the OPCDs are looked up in turn, evaluating the next eight elements for the specific OPCD argument dictionary, each time the OPCD is encountered. See setOpcdArgs(), getOpcdArgs(), and __init__() for more information about default arguments. """ com_file = com_args[0] # name of com file and return value inp_file = com_args[1] # name of calculation input mae file out_file = com_args[2] # name of calculation output mae file # Get our file handl ready to write, clobber existing file com_fh = open(com_file, mode='w') # Write the job IO com_fh.write(inp_file) com_fh.write('\n') com_fh.write(out_file) com_fh.write('\n') # Write the OPCDs with their args opcd_data = '' for opcd in com_args[3:]: # Marshall the opcd arg values opcd_data = self.getOpcdArgs(opcd) # Skip commented out opcds if beautify is true if self.beautify and opcd_data.startswith('!'): continue # Write the opcd with args com_fh.write(opcd_data) # Flush, close com_fh.flush() com_fh.close() # Clean up for next write self._written = [] # Return the name of the com file written return com_file
[docs] def writeSbcFile(self, sbc_args=[]): # noqa: M511 """ Deprecated wrapper for `SbcUtil.writeSbcFile`. """ warnings.warn( 'This method is deprecated; please use ' 'schrodinger.application.macromodel.utils.SbcUtil.writeSbcFile ' 'as a replacement.', DeprecationWarning, stacklevel=2) msb = SbcUtil() msb.SUBS.update(self.SUBS) # native (may have FXAT constraint also) msb.FXAT.update(self.FXAT) # constrained/frozen atoms msb.FXDI.update(self.FXDI) # constrain distance msb.FXTA.update(self.FXTA) # constrain torsion angle msb.FXBA.update(self.FXBA) # constrain bond angle msb.FXCO.update(self.FXCO) # constrain all torsions # return the name of the sbc file written return msb.writeSbcFile(sbc_args)
[docs] def getOpcdArgs(self, opcd=""): """ This method returns a formatted string of OPCD and arguments for the passed OPCD string. The arguments come from the hash data members, any unknown or unassigned values default to 0 or 0.0. You may customize the self hash arguments to your heart's content prior to invoking the method to get the exact behavior you want. The 'OPCD' lookup requires the passed argument to be a key for the hash, i.e. uppercase with no whitespace. The array of arg values are numbers, not strings. This method keeps count of the number of times an OPCD is called and automatically increments the array of args for the passed OPCD. The first call for a given OPCD uses self['OPCD'] arg slices 1-8, the next call for that OPCD uses slices 9-16, the next 17-24, and so on. writeComFile() zeros the count after the com file is serialized. """ # Default opcd arguments. bmin usually interprets 0 as some # other default value args = [opcd, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0.0] # Check multiplicity of this opcode call, i is the index into # the opcd array of args. This is only needed for complex # com files, like when multiple calls to MCOP or MBAE are made i = 8 * self._written.count(opcd) # Apply collective values again to make sure settings are consistent if self.ddde: self.solv = False # mutually exclusive because epsilon != 1 self.FFLD[2] = 2 # distance dependent self.FFLD[5] = 4.0 # epsilon if self.serial: self.AUTO[6] = 1 if self.serial and self.serial_nonconf_input: self.DEBG[1] = 55 # Gather assigned args for this call if opcd in self.__dict__: args[0] = opcd args[1] = self.__dict__[opcd].get(i + 1, 0) args[2] = self.__dict__[opcd].get(i + 2, 0) args[3] = self.__dict__[opcd].get(i + 3, 0) args[4] = self.__dict__[opcd].get(i + 4, 0) args[5] = self.__dict__[opcd].get(i + 5, 0) args[6] = self.__dict__[opcd].get(i + 6, 0) args[7] = self.__dict__[opcd].get(i + 7, 0) args[8] = self.__dict__[opcd].get(i + 8, 0) # Record opcd used to later multiplicity checks. This # semi-private array gets emptied after writeComFile() # serializes the com file self._written.append(opcd) # Toggle unrequested options off # NPRC on/off if (opcd == 'NPRC' and not self.nprc): args[0] = '!NPRC' # GB/SA on/off elif (opcd == 'SOLV' and not self.solv): args[0] = '!SOLV' # Extended nonbonded on/off elif (opcd == 'EXNB' and not self.exnb): args[0] = '!EXNB' # Charges from structure input file on/off elif (opcd == 'CHGF' and not self.chgf): args[0] = '!CHGF' # Bond dipole cutoff on/off elif (opcd == 'BDCO' and not self.bdco): args[0] = '!BDCO' # Automatic variable setup/serial setup on/off elif (opcd == 'AUTO'): if not self.auto: args[0] = '!AUTO' # Automatic variable setup/serial setup on/off elif (opcd == 'AUOP'): if not self.auop: args[0] = '!AUOP' # .sbc file in use elif (opcd == 'SUBS' and not self.subs): args[0] = '!SUBS' # Allow hydrogen bond electrostatics elif (opcd == 'CHYD' and not self.chyd): args[0] = '!CHYD' # Don't consider enantiomers as duplicates elif (opcd == 'NANT' and not self.nant): args[0] = '!NANT' # Enable 9.6 Confgen options: CGO3,CGO4, CGO5, CGO6 elif (opcd == 'CGO3' and not self.cgo3): args[0] = '!CGO3' elif (opcd == 'CGO4' and not self.cgo4): args[0] = '!CGO4' elif (opcd == 'CGO5' and not self.cgo5): args[0] = '!CGO5' elif (opcd == 'CGO6' and not self.cgo6): args[0] = '!CGO6' elif (opcd == 'FLAP' and not self.flap): args[0] = '!FLAP' elif (opcd == 'MCRC' and not self.mcrc): args[0] = '!MCRC' elif (opcd == 'MMOD' and not self.mmod): args[0] = '!MMOD' # Energy window assignments on/off elif (opcd == 'DEMX'): if not self.demx: args[0] = '!DEMX' # No real reason to redefine arg2, maybe the user knows best? # now arg2 is set to a large value by default: 10000 iterations # which means the pretest is unlikely to be triggered # args[2] = int(self.MINI[3]/2) # pre test # END formating workaround to get a four char string elif (opcd == 'END'): args[0] = ' END ' # arg1-4 value size check for arg_pos in [1, 2, 3, 4]: if len(str(args[arg_pos])) > 6: print("%s arg %d value is too large for com file format." % (opcd, args[arg_pos])) if self.refit_args and args[arg_pos] > 0: args[arg_pos] = 999999 elif self.refit_args and args[arg_pos] < 0: args[arg_pos] = -99999 # arg5-8 value size check, reformatting if needed. opcd_format = {} for arg_pos in [5, 6, 7, 8]: opcd_format[arg_pos] = '%5.4f' value = str(args[arg_pos]) if len(value.split('.')[0]) == 6: opcd_format[arg_pos] = '%6.3f' elif len(value.split('.')[0]) == 7: opcd_format[arg_pos] = '%7.2f' elif len(value.split('.')[0]) == 8: opcd_format[arg_pos] = '%8.1f' elif len(value.split('.')[0]) == 9: opcd_format[arg_pos] = '%9.0f.' # note the trailing '.' elif len(value.split('.')[0]) >= 10: print("%s arg %f value is too large for com file format." % (opcd, args[arg_pos])) if self.refit_args and args[arg_pos] > 0: args[arg_pos] = 999999999 elif self.refit_args and args[arg_pos] < 0: args[arg_pos] = -99999999 opcd_format[arg_pos] = '%9.0f.' # Cast arg value number as a string. args[1] = '%d' % args[1] args[2] = '%d' % args[2] args[3] = '%d' % args[3] args[4] = '%d' % args[4] args[5] = opcd_format[5] % args[5] args[6] = opcd_format[6] % args[6] args[7] = opcd_format[7] % args[7] args[8] = opcd_format[8] % args[8] # Justify the string so we can join the list elements contigiously. args[0] = args[0].rjust(5) args[1] = args[1].rjust(8) # eight takes up the OPCD trailing space args[2] = args[2].rjust(7) args[3] = args[3].rjust(7) args[4] = args[4].rjust(7) args[5] = args[5].rjust(11) # the decimal takes a char args[6] = args[6].rjust(11) args[7] = args[7].rjust(11) args[8] = args[8].rjust(11) args.append('\n') args_string = "".join(args) return args_string
[docs] def setOpcdArgs(self, opcd="", arg1=0, arg2=0, arg3=0, arg4=0, arg5=0.0, arg6=0.0, arg7=0.0, arg8=0.0): """ This method returns True after adding the passed values to the desired opcd dictionary. The dictionary is selected by the first parameter, which is required. The rest of the parameters are mapped to the next eight argument indices in the dictionary. Unspecified values default to 0 or 0.0. This method determines the highest existing index (numeric hash key), and then assigns the passed args to the next available slots. You may want to first blank the dictionary with the appropriate call of self['OPCD'].clear(). Assumming the dictionary has has been cleared, the first 'set' of a given OPCD assigns self['OPCD'] arg indices 1-8, the next call for that OPCD defines indices 9-16, the next 17-24, and so on. """ # Try counting the highest indexed key. i = 0 try: keys = list(self.__dict__[opcd]) if len(keys) > 0: i = keys[-1] except KeyError: self.__dict__[opcd] = {} # Determine the proper index y = divmod(i, 8) # tuple[0] = num of whole sets, tuple[1] = num partials i = y[0] if y[1] > 0: i += 1 # Advance the index by eight, or one 'row', or one call... i = 8 * i # Assign self.__dict__[opcd][i + 1] = arg1 self.__dict__[opcd][i + 2] = arg2 self.__dict__[opcd][i + 3] = arg3 self.__dict__[opcd][i + 4] = arg4 self.__dict__[opcd][i + 5] = arg5 self.__dict__[opcd][i + 6] = arg6 self.__dict__[opcd][i + 7] = arg7 self.__dict__[opcd][i + 8] = arg8 # Return True if we made it this far return True
[docs] def outComFile(file_name="", structure_file_ext='.mae'): """ This is a static helper method for the jobs that write com files. Returns an 'out' string for the passed 'in' string. Raises an Exception if the file name can't be determined. :param file_name: If passed 'jobname.com' string argument, it returns the appropriate 'jobname-out.mae' string. If passed a 'foo.mae' file, it returns an appropriate 'foo.com' file name. :type file_name: string :param structure_file_ext: Output structure file extension. Default is '.mae'. :type structure_file_ext: string """ # Initialize false return value, split the file_name. out_com_name = "" (root, ext) = fileutils.splitext(file_name) # Return com file if we received mae file. if ext in ['.mae', '.maegz', '.mae.gz']: out_com_name = "%s.com" % root # Return out.mae|mae.gz|maegz file if we received a com file. elif ext in ['.com']: out_com_name = "%s-out%s" % (root, structure_file_ext) # Panic else: msg = \ "ComUtil.outComFile() can't determine file name pattern: %s." % ( file_name ) raise Exception(msg) return out_com_name
# Announce as static method outComFile = staticmethod(outComFile)
[docs] def setupAset(self, set_dict, arg7=0, arg8=0): """ Define ASET arguments from a set dictionary. Numeric hash keys index the lists of atom numbers. The numerical key is taken as the set number identifier. """ # FIXME: determine if we have mutually exclusive atom sets in set_dict # ev35981 # ASET - # arg5 Set number identifier # arg6 Command mode # 1, 0 add # -1 delete # 2 add range arg1-arg2 # -2 delete range arg1-arg2 # 3 add molecules containing atoms arg1-arg4 # -3 delete molecules containing atoms arg1-arg4 # # arg7 Recording Inter/Intra Set Energies # 0 Inter-Set Energies between Set1 and other Sets # 2 Inter-Set Energies between all sets # 4 Intra-Set Energies for all sets # # arg8 Recording Energetic Properties # 0 Total Energy # 2 Total Energy and Non-bond Energy # 4 All Energetic Components # Wipe the dictionary self.ASET.clear() # Clear any previous sets, defines property output self.setOpcdArgs('ASET', arg7=arg7, arg8=arg8) # Break up set into contiguous atom number blocks # add atoms arg1-4: arg6==1, # add atom range arg1, arg4: arg6==2 # add atom's molecule: arg6==3 # atoms for molecule numbers are identified by a # negative value for key in list(set_dict): i_atom = 0 # range start j_atom = 0 # range end atoms = set_dict[key] atoms.sort() for atom in atoms: # Make any 'molecule number' assignments if atom < 0: self.setOpcdArgs('ASET', -1 * atom, arg5=float(key), arg6=3, arg7=arg7, arg8=arg8) # Make 'atom number' assignments, atom numbers must be > 0 if atom > 0 and i_atom == 0: # Seed range i_atom = atom j_atom = atom if atom > 0 and i_atom > 0 and atom == j_atom + 1: # Expand range j_atom = atom if atom > 0 and i_atom > 0 and atom > j_atom + 1: # Commit singleton atom arg6==1, range arg6==2 if i_atom == j_atom or atom == atoms[-1]: self.setOpcdArgs('ASET', i_atom, arg5=float(key), arg6=1.0, arg7=arg7, arg8=arg8) else: self.setOpcdArgs('ASET', i_atom, j_atom, arg5=float(key), arg6=2.0, arg7=arg7, arg8=arg8) # Reseed if atom > 0: j_atom = atom i_atom = atom # Commit range if atom > 0: self.setOpcdArgs('ASET', i_atom, atom, arg5=float(key), arg6=2, arg7=arg7, arg8=arg8) return
[docs] def getLaunchCommand(self, com_file=""): """ This method returns a list of arguments that form the toplevel command invocation with all the flags set in the instance. It takes a string argument that specifies the name of the com file to run, and returns the fully qualified executable and all commandline arguments. """ # Initialize values flags = [] # list of option and arg strings cmd_args = [] # component strings # Set MacroModel command line flags/args if self.proj: flags.extend(["-PROJ", self.proj]) if self.disp: flags.extend(["-DISP", self.disp]) if self.user: flags.extend(["-USER", self.user]) if self.arch: flags.extend(["-ARCH", self.arch]) if self.host: flags.extend(["-HOST", self.host]) if self.hostfile: flags.extend(["-HOSTFILE", self.hostfile]) if self.tmpdir: flags.extend(["-TMPDIR", self.tmpdir]) if self.nice: flags.extend(["-NICE"]) if self.wait: flags.extend(["-WAIT"]) if self.local: flags.extend(["-LOCAL"]) if self.interval: flags.extend(["-INTERVAL", str(self.interval)]) if self.ddebug: flags.extend(["-DDEBUG"]) if self.no_redirect: flags.extend(["-NO_REDIRECT"]) if self.ver: flags.extend(["-VER", self.ver]) if self.rel: flags.extend(["-REL", self.rel]) if self.para_bmin and self.para_bmin_jobcts: flags.extend(["-JOBCTS", str(self.para_bmin_jobcts)]) if self.para_bmin and self.para_bmin_njobs: flags.extend(["-NJOBS", str(self.para_bmin_njobs)]) if self.para_bmin and self.para_bmin_output_org: flags.extend(["-OUTPUT_ORG", self.para_bmin_output_org]) # Truncate 'jobname.com' to 'jobname' jobname_re = re.compile(r'.com$') com_file = jobname_re.sub('', com_file) # Fashion command expression if self.para_bmin: cmd_args.append('para_bmin') else: cmd_args.append('bmin') cmd_args.extend(flags) cmd_args.append(com_file) if self._debug: print(cmd_args) print(" ".join(cmd_args)) return cmd_args
[docs] def elst(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a single point energy listing, returns the name of the com file written. It requires a string containing the the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() if self.serial: self.DEBG[1] = 601 # write and output file with WRIT only com_args = [ com_file, mae_file, out_file, 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'BGIN', 'READ', 'ELST', 'WRIT', 'END' ] else: com_args = [ com_file, mae_file, out_file, 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'READ', 'ELST' ] return self.writeComFile(com_args)
[docs] def dlst(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a single point energy listing of 1st and 2nd derivatives, returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'READ', 'DLST' ] return self.writeComFile(com_args)
[docs] def mini(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a geometry optimization, returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'BGIN', 'SUBS', 'READ', 'CONV', 'MINI', 'END' ] return self.writeComFile(com_args)
[docs] def addc(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for redundant conformer elimination, returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. COMP atoms must be set outside of this method. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'FFLD', 'DEMX', 'CRMS', 'NANT' ] # add the correct number of args i = 0 while (i < old_div(len(self.COMP), 8)): com_args.append('COMP') i += 1 # big finish com_args.append('MSYM') com_args.append('BGIN') com_args.append('READ') if (len(self.COMP) == 0): com_args.append('AUTO') com_args.append('ADDC') com_args.append('END') return self.writeComFile(com_args)
[docs] def filter(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a special atom filtering, similar to premin's, but with 0 minimization iterations; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.DEBG[1] = 3 self.DEBG[2] = 57 self.DEBG[3] = 49 self.MINI[3] = 0 self.setOpcdArgs('SPAT', 151, 152, 153, 154, 1.0) self.setOpcdArgs('SPAT', 155, 156, 157, 158, 1.0) self.setOpcdArgs('SPAT', 159, 160, 161, 162, 1.0) self.setOpcdArgs('SPAT', 163, 164, 165, 166, 1.0) self.setOpcdArgs('SPAT', 167, 168, 169, 170, 1.0) self.setOpcdArgs('SPAT', 171, 172, 173, 65, 1.0) self.setOpcdArgs('SPAT', 66, 67, 68, 69, 1.0) self.setOpcdArgs('SPAT', 70, 71, 72, 73, 1.0) self.setOpcdArgs('SPAT', 74, 75, 76, 77, 1.0) self.setOpcdArgs('SPAT', 78, 79, 80, 81, 1.0) self.setOpcdArgs('SPAT', 82, 83, 84, 85, 1.0) self.setOpcdArgs('SPAT', 86, 87, 88, 89, 1.0) self.setOpcdArgs('SPAT', 90, 91, 102, arg5=1.0) com_args = [] # passed to writeComFile() com_args = [com_file, mae_file, out_file, 'DEBG', 'EXNB', 'FFLD'] # add the correct number of args i = 0 while (i < old_div(len(self.SPAT), 8)): com_args.append('SPAT') i += 1 # big finish com_args.append('BGIN') com_args.append('READ') com_args.append('CONV') com_args.append('MINI') com_args.append('END') return self.writeComFile(com_args)
[docs] def mult(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a geometry optimization and filtering with MULT and COMP; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. It is intended for filtering conformation search output. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'DEMX', 'BGIN', 'READ', 'MULT', 'COMP', 'CRMS', 'NANT', 'MSYM', 'CONV', 'MINI', 'END' ] return self.writeComFile(com_args)
[docs] def driv(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a geometry drive; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. It is intended for filtering conformation search output. DEGB 150 starts the drive from the input geometry, not the endpoint of the previous iteration. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'READ', 'BGIN', ] # add the correct number of args i = 0 while (i < old_div(len(self.DRIV), 8)): com_args.append('DRIV') i += 1 # add the big finish... com_args.append('CONV') com_args.append('MINI') com_args.append('END') return self.writeComFile(com_args)
[docs] def lmod(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a lowmode conformation search; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments if self.serial: self.MCOP[4] = 1 com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SEED', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'FLAP', 'MCRC', 'LMCS', 'MCSS', 'MCOP', 'DEMX', 'MSYM', 'AUTO', # chig and comp setup, tors/mols if mixed 'CRMS', 'NANT', 'CONV', 'MINI' ] return self.writeComFile(com_args)
[docs] def llmd(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a large scale lowmode conformation search; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments if self.serial: self.MCOP[4] = 1 com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SEED', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'ARPK', 'LMC2', 'MCSS', 'MCOP', 'DEMX', 'MSYM', 'AUTO', # chig and comp setup, tors/mols if mixed 'CRMS', 'NANT', 'CONV', 'MINI' ] return self.writeComFile(com_args)
[docs] def mcmm(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a monte carlo multiple minimum conformation search; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SEED', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'FLAP', 'MCRC', 'MCMM', 'MCSS', 'MCNV', 'MCOP', 'DEMX', 'MSYM', 'AUOP', 'AUTO', 'CRMS', 'NANT', 'CONV', 'MINI' ] return self.writeComFile(com_args)
[docs] def spmc(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a systematic pseudo monte carlo multiple minimum conformation search; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. This method always uses torsional memory and will preoptimize ring closure distances. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.MCOP[2] = 1 # preoptimize ring closure dists self.MCSS[3] = 1 # SUMM => use torsional memory com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SEED', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'SPMC', 'MCSS', 'MCNV', 'MCOP', 'DEMX', 'MSYM', 'AUOP', 'AUTO', 'CRMS', 'NANT', 'CONV', 'MINI' ] return self.writeComFile(com_args)
[docs] def mcmmlmod(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a mixed monte carlo multiple minimum/lowmode conformation search; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments # 1:1 mix if nothing else defined if not self.MCOP[5]: self.MCOP[5] = 0.5 com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SEED', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'FLAP', 'MCRC', 'LMCS', 'MCSS', 'MCNV', 'MCOP', 'DEMX', 'MSYM', 'AUOP', 'AUTO', 'CRMS', 'NANT', 'CONV', 'MINI' ] return self.writeComFile(com_args)
[docs] def mcmmllmd(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a mixed monte carlo multiple minimum/large scale lowmode conformation search; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments # 1:1 mix if nothing else defined if not self.MCOP[5]: self.MCOP[5] = 0.5 com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SEED', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'ARPK', 'LMC2', 'MCNV', 'MCSS', 'MCOP', 'DEMX', 'MSYM', 'AUOP', 'AUTO', 'CRMS', 'NANT', 'CONV', 'MINI' ] return self.writeComFile(com_args)
[docs] def cgen(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a ligand torsion search with ConfGen; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'READ', 'CRMS', 'NANT', 'CGEN', 'CGOP', 'CGO2', 'CGO3', 'CGO4', 'CGO5', 'CGO6', 'CHYD', 'MCOP', 'DEMX', 'MSYM', 'AUOP', 'AUTO', 'CONV', 'MINI' ] return self.writeComFile(com_args)
[docs] def mdyn(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a molecular dynamics simulation; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'MMOD', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'READ', 'CONV', 'MINI', 'MDIT', 'MDYN', 'MDSA', 'MDFT', 'MDYN', 'WRIT' ] return self.writeComFile(com_args)
[docs] def mcsd(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a mixed Monte Carlo/Stochastic Dynamics simulation; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.AUTO[2] = -1 # no comps needed self.AUTO[3] = -1 # no chig needed self.MDYN[2] = 0 # no shake for MCSD, we have MC criteria com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'MMOD', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'READ', 'CONV', 'MINI', 'MCNV', 'AUTO', 'MCSD', 'MDIT', 'MDYN', 'MDSA', 'MDYN', 'MDFT', ] return self.writeComFile(com_args)
[docs] def mmc(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a Metropolis Monte Carlo ensemble generation; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The arguments for ZMAT must be set outside this method. ZMAT makes all the structural changes so the min-max range should allow diverse sampling (5 deg bends, 180 tors). """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'SEED', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'READ', 'MCNV' ] # add the correct number of args i = 0 while (i < old_div(len(self.ZMAT), 8)): com_args.append('ZMAT') i += 1 # add the big finish... com_args.append('MINI') com_args.append('MDSA') com_args.append('MCLO') return self.writeComFile(com_args)
[docs] def adf(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for an All Degrees of Freedom simulation (a Metropolis Monte Carlo with passive Importance sampling) calculation; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The arguments for ZMAT must be set outside this method. ZMAT makes all the structural changes so the min-max range should allow diverse sampling (5 deg bends, 180 tors). """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'READ', 'COMP', # all heavy atoms for IMPS similarity assignment ] # add the correct number of args i = 0 while (i < old_div(len(self.ZMAT), 8)): com_args.append('ZMAT') i += 1 # add the big finish... com_args.append('MCNV') com_args.append('IMPS') com_args.append('IMPO') com_args.append('MINI') com_args.append('MDSA') com_args.append('MCLO') return self.writeComFile(com_args)
[docs] def jbw(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a Jump Between Wells simulation (a Metropolis Monte carlo simulation with active Importance sampling); returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The arguments for ZMAT must be set outside this method. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.IMPS[1] = 1 # all steps IMPS steps self.MDSA[2] = 1 # report IMPS population and statistics self.MDSA[3] = 1 # report IMPS transition statistics self.MDSA[4] = 1 # report IMPS transition statistics com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'COMP', # all heavy atoms for IMPS similarity assignment 'READ', ] # add the correct number of args i = 0 while (i < old_div(len(self.ZMAT), 8)): com_args.append('ZMAT') i += 1 # add the big finish... com_args.append('IMPS') com_args.append('IMPO') com_args.append('MDSA') com_args.append('MCLO') return self.writeComFile(com_args)
[docs] def jbw_sd(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a Jump Between Wells/Stochastic Dynamics simulation (a MCSD simulation with active Importance sampling); returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The arguments for ZMAT must be set outside this method. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.IMPS[1] = 1 # all steps IMPS steps self.MDSA[2] = 1 # report IMPS population and statistics self.MDSA[3] = 1 # report IMPS transition statistics self.MDSA[4] = 1 # report IMPS transition statistics self.MCSD[1] = 1 # no MC, we have JBW self.MCSD[2] = -1 # don't randomize JBW step com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'MCSD', 'COMP', # all heavy atoms for IMPS similarity assignment 'READ', ] # add the correct number of args i = 0 while (i < old_div(len(self.ZMAT), 8)): com_args.append('ZMAT') i += 1 # add the big finish... com_args.append('IMPS') com_args.append('IMPO') com_args.append('MDIT') com_args.append('MDSA') com_args.append('MDYN') return self.writeComFile(com_args)
[docs] def geom(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a geometry analysis; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The arguments for GEOM must be set outside this method. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'FFLD', 'BGIN', 'READ', ] # add the correct number of args i = 0 while (i < old_div(len(self.GEOM), 8)): com_args.append('GEOM') i += 1 # add the big finish... com_args.append('WRIT') com_args.append('END') return self.writeComFile(com_args)
[docs] def copyalgn(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for an ALGN/COPY positioning of ligands on a reference ligand; returns the name of the com file written. The ligands are positioned on the first ligand (all four ways) with ALGN/COPY. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.ALGN[1] = 3 self.ALGN[2] = 1 self.ALGN[3] = 5 com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'FFLD', 'READ', 'COPY', 'BGIN', 'READ', 'ALGN', 'END' ] return self.writeComFile(com_args)
[docs] def mbaeMiniEdiff(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for an MBAE multiple minimization run, in energy difference mode; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.MBAE[1] = 1 # ediff self.MBAE[2] = 0 # mini calc com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'MBAE', 'SUBS', 'READ', 'CONV', 'MINI', 'DEMX', 'BGIN', 'READ', 'CONV', 'MINI', 'END', 'MBAE' ] return self.writeComFile(com_args)
[docs] def mbaeMiniInter(self, mae_file=None, com_file=None, out_file=None, recep_atom=None): """ This method writes a com file for an MBAE multiple minimization run, in set interaction mode; returns the name of the com file written. recep_atom is the last atomic index of the receptor structure. If recep_atom is None then the first structure in the mae_file is evaluated. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The ASET arguments are set by snooping the input file for the number of atoms in the receptor. raises IOError if the receptor atom total can't be determined from the input structure file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.ELST[1] = -1 # don't fill the disk with complete energy listings self.MBAE[1] = 0 # atom set interaction mode self.MBAE[2] = 0 # mini calc # Get the size of the receptor if needed. if recep_atom is None: try: recep_st = structure.Structure.read(mae_file) recep_atom = recep_st.atom_total except: msg = 'Unable to determine the receptor size in file %s' % ( mae_file) raise IOError(msg) # blank any previous sets self.ASET[1] = 0 self.ASET[2] = 0 self.ASET[3] = 0 self.ASET[4] = 0 self.ASET[5] = 0.0 self.ASET[6] = 0.0 self.ASET[7] = 0.0 self.ASET[8] = 0.0 # add all atoms to set 2 self.ASET[13] = 2.0 # cut recptor atoms from set 2 self.ASET[17] = 1 self.ASET[18] = recep_atom self.ASET[21] = 2.0 self.ASET[22] = -2.0 # paste recptor atoms into set 1 self.ASET[25] = 1 self.ASET[26] = recep_atom self.ASET[29] = 1.0 self.ASET[30] = 2.0 com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'MBAE', 'SUBS', 'READ', 'DEMX', 'BGIN', 'READ', 'ASET', 'ASET', 'ASET', 'ASET', 'CONV', 'MINI', 'ELST', 'END', 'MBAE' ] return self.writeComFile(com_args)
[docs] def mbaeCsLmod(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for an MBAE low mode conformation search run, in energy difference mode; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. If ComUtil.algn is true, then a the job will positions the ligands on the reference ligand, with all four alignments. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.MBAE[1] = 1 # ediff self.MBAE[2] = 1 # confs calc self.MCOP[6] = 1 # only one receptor conf self.MCOP[12] = 1 # lcms serial search if > 0 com_args = [] # passed to writeComFile() # compound job with algn/copy as the first step if self.algn: self.SUBS[2] = 1 # specify correct sbc file self.ALGN[1] = 3 # center and princ axes align with ref self.ALGN[2] = 1 # weight atoms by atomic mass self.ALGN[3] = 5 # generate all four and write com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'MSYM', 'READ', 'WRIT', 'READ', 'COPY', 'BGIN', 'READ', 'ALGN', 'END', 'RWND', 'MBAE', 'LMCS', 'MCSS', 'MCOP', 'SUBS', 'AUTO', 'CONV', 'MINI', 'DEMX', 'LMCS', 'BGIN', 'MCOP', 'READ', 'MINI', 'END', 'MBAE' ] else: com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'MSYM', 'MBAE', 'LMCS', 'MCSS', 'MCOP', 'DEMX', 'SUBS', 'READ', 'AUTO', 'CONV', 'MINI', 'LMCS', 'BGIN', 'MCOP', 'READ', 'MINI', 'END', 'MBAE' ] return self.writeComFile(com_args)
[docs] def mbaeCsMcmm(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for an MBAE monte carlo conformation search run, in energy difference mode; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. If ComUtil.algn is true, then a the job will positions the ligands on the reference ligand, with all four alignments. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.AUTO[6] = 1 # serial setup self.MBAE[1] = 1 # ediff self.MBAE[2] = 1 # confs calc self.MCOP[6] = 1 # one receptor conf com_args = [] # passed to writeComFile() # compound job with algn/copy as the first step if self.algn: self.SUBS[2] = 1 # specify correct sbc file self.ALGN[1] = 3 # center and princ axes align with ref self.ALGN[2] = 1 # weight atoms by atomic mass self.ALGN[3] = 5 # generate all four and write com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'MSYM', 'READ', 'WRIT', 'READ', 'COPY', 'BGIN', 'READ', 'ALGN', 'END', 'RWND', 'MBAE', 'MCMM', 'MCSS', 'MCOP', 'DEMX', 'SUBS', 'AUTO', 'CONV', 'MINI', 'LMCS', 'BGIN', 'MCOP', 'READ', 'MINI', 'END', 'MBAE' ] else: com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'MSYM', 'MBAE', 'MCMM', 'MCSS', 'MCOP', 'DEMX', 'SUBS', 'READ', 'AUTO', 'CONV', 'MINI', 'MCMM', 'BGIN', 'MCOP', 'READ', 'MINI', 'END', 'MBAE' ] return self.writeComFile(com_args)
[docs] def mbaeCsMcmmLmod(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for an MBAE mixed lowmode monte carlo conformation search run, in energy difference mode; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. If ComUtil.algn is true, then a the job will positions the ligands on the reference ligand, with all four alignments. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.MBAE[1] = 1 # ediff self.MBAE[2] = 1 # confs calc if not self.MCOP[5]: self.MCOP[5] = 0.5 # half mcmm / half lowmode self.MCOP[6] = 1 # one receptor conf return self.mbaeCsLmod(mae_file, com_file)
[docs] def logP(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a multiple minimization with logP calculation; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments self.serial = True # serial auto self.solv = True # must have solvent com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'LOGP', 'BGIN', 'READ', 'AUTO', 'CONV', 'MINI', 'END' ] return self.writeComFile(com_args)
[docs] def fep(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a Free Energy Perturbation with stochastic dynamics sampling; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'NPRC', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'READ', 'FEIA', 'BGIN', 'FEAV', 'CONV', 'MINI', 'MDIT', 'MDYN', 'FESA', 'MDYN', 'END', 'FESU' ] return self.writeComFile(com_args)
[docs] def loop(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a protein LOOP conformation search; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'LOOP', 'LPOP', 'DEMX', 'COMP', 'MSYM', 'MCOP', 'CONV', 'MINI' ] return self.writeComFile(com_args)
[docs] def aset(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a atom set interaction (ASET) analysis; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The arguments for ASET must be set outside this method. Uses a BGIN/END loop to process each input file member, but single structure input files are allowed. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'BGIN', 'READ', ] # add the correct number of args i = 0 while (i < old_div(len(self.ASET), 8)): com_args.append('ASET') i += 1 # add the big finish... com_args.append('ELST') com_args.append('END') return self.writeComFile(com_args)
[docs] def minta(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a Mode integration MINTA calculation (conformational free energy); returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'BGIN', 'READ', 'CONV', 'MINI', 'MNTA', 'END' ] return self.writeComFile(com_args)
[docs] def rrho(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file for a Rigid Rotor Harmonic Oscillator calculation (normal mode analysis of thermodyanic quantities); returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The structure is minimized prior to RRHO calculation. The optimization can be omitted by setting MINI[3] = 0 """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [ com_file, mae_file, out_file, 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'CONV', 'MINI', 'MTST', 'RRHO', ] return self.writeComFile(com_args)
[docs] def vibr(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file to visualize vibrational modes with VIBR; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The structure is minimized prior to VIBR calculation. The optimization can be omitted by setting MINI[3] = 0 """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'CONV', 'MINI', 'VIBR', ] return self.writeComFile(com_args)
[docs] def vbr2(self, mae_file=None, com_file=None, out_file=None): """ This method writes a com file to visualize vibrational modes with VBR2; returns the name of the com file written. It requires a string containing the name of a maestro format file that will be used as the job input, and returns the string name of the com file. It may also accept an optional string file name that becomes the name of the com file plus the root of the generated -out.mae file. The structure is minimized prior to VBR2 calculation. The optimization can be omitted by setting MINI[3] = 0 """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments com_args = [ com_file, mae_file, out_file, 'MMOD', 'DEBG', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'FFLD', 'SUBS', 'READ', 'CONV', 'MINI', 'ARPK', 'VBR2', ] return self.writeComFile(com_args)
[docs]class ComUtilAppSci(ComUtil): """ Subclass of ComUtil with defaults that are closer to the current Maestro version. Defaults are: - Potential energy surface is OPLS_2005, GB/SA water solvent, with extended non-bonded cutoff. - Minimization run up to 500 iterations of PRCG. Convergence is set to a gradient of 0.05. - Energy window is 21 kJ/mol and an initial energy window of 42 kJ/mol is applied after 166 iteration. - MacroModel/Maestro interaction files are generated. Disable by setting self.mmod = False. - Atom distance for conformer equivalence is 0.50 angstroms. - The maximum number of degrees of freedom sampled per MC step is 5. - Automatic conformation search parameters scale the number of steps to the number of torsions. - Single point energy listing com file follows the Maestro form. - Input structure file is assumed to contain multiple non-conformer ligands. i.e. self.serial = True such that automatic variables are generated in serial mode by AUTO, and self.serial_nonconf_input = True such that DEBG 55 is set for improved property management of non conformer input structures. - The constructor takes no kwargs, but the instance data members can be altered. """
[docs] def __init__(self): ComUtil.__init__(self) self.nant = True self.exnb = True self.solv = True self.mmod = True self.serial = True self.serial_nonconf_input = True self.BDCO[5] = 89.4427 # sqrt(cutoff_electrostatics^3) self.MINI[3] = 500 # Not enough iters, but satisfies ev93833. self.MINI[11] = 500 self.CONV[5] = 0.05 self.MCSS[5] = 21 self.DEMX[2] = 166 self.DEMX[5] = 21.0 self.DEMX[6] = 42.0 self.MDSA[1] = 0 # No structures, but satisfies ev93833. self.MDSA[7] = 1.0 # No structures, but satisfies ev93833. self.MCNV[2] = 5 # max number DOF altered. self.CRMS[6] = 0.50 # max dist between 'equivalent' corresponding atoms self.AUTO[8] = 1.0 # 'intermediate' sampling (MacroModel 9.0 deflault) self.AUOP[5] = 100 # N search steps = (arg5)*(number of torsions+mols)
[docs] def elst(self, mae_file=None, com_file=None, out_file=None): """ :return: The name of the single point energy listing com file written. :rtype: string :param mae_file: Name of the structure file input. :type mae_file: string :param com_file: Optional com_file name. By default it is determined from the basename of the mae_file. :type com_file: string :param out_file: Optional out_file name. By default it determined from the basename of the com_file. :type out_file: string """ # Fashion com file name, if needed if not com_file: com_file = self.outComFile(mae_file) # Fashion output file name if not out_file: out_file = self.outComFile(com_file, self.structure_file_ext) # Prep com file arguments orig_read = {} orig_read.update(self.READ) self.READ[1] = -1 com_args = [] # passed to writeComFile() com_args = [ com_file, mae_file, out_file, 'DEBG', 'MMOD', 'FFLD', 'SOLV', 'EXNB', 'BDCO', 'CHGF', 'BGIN', 'READ', 'ELST', 'WRIT', 'END' ] com_file = self.writeComFile(com_args) self.READ.update(orig_read) return com_file
[docs]class ComUtil_2010(ComUtilAppSci): """ This class will be deprecated in the next release. Consider ComUtilAppSci instead. """
[docs] def __init__(self): warnings.warn( 'This class will be deprecated in the next release. Consider ComUtilAppSci instead.', DeprecationWarning, stacklevel=2) ComUtilAppSci.__init__(self) return
[docs]class SbcUtil: """ A class for writing substructure/constraint files to accompany jobname.com. MacroModel has different ways to define freely moving, restrained and constrained atoms. A good understanding of the SUBS/FXAT behavior is often essential; see the MacroModel Reference Manual for more details. Below are a few examples of some common idioms. This class now supports ASL2 with half-width flat-bottomed restraint potential. If self.use_flat_bottom_asl2 is True, then the ASL2 arguments are formatted thus:: ASL2 arg1 = Flat-bottom width, in units of tenths of an angstrom. ASL2 arg2 = Force constant. ASL2 arg3 = Atom selection language string otherwise, ASL2 argument are formated as:: ASL2 arg1 = Force constant. ASL2 arg2 = Atom selection language string API examples:: # Example 1 ############################################################ # Writing a sbc file to restrain atoms during a minimization with ASL2. # Write com file instructions for a simple geometry optimization. # The ComUtil instance is configured such that it will write the # SUBS opcode in the com file. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil(subs=True) com_file = mcu.mini("example_1.mae") # MacroModel requires that the sbc file name match the input # structure file, not the com file. sbc_file = 'example_1.sbc' # Write sbc file that will modify the geometry optimization such that # all atoms are harmonically restrained about their starting coordinates. sbu = mmodutils.SbcUtil() sbu.ASL2[1] = 200 # force constant for Cartesian restraints. sbu.ASL2[2] = 'mol.n 1' # ASL identifying the restrained atoms. sbu_args = [sbc_file, 'ASL2'] sbu.writeSbcFile(sbu_args) # Example 2 ############################################################ # Writing a sbc file to perform a conformation search on part of a # structure with ASL1/ASL2. # Write com file instructions for a simple conformation search. # The ComUtil instance is configured such that it will write the # SUBS opcode in the com file. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil(subs=True) mcu.MCMM[1] = 100 # Short test search. com_file = mcu.mcmm("example_2.mae") # MacroModel requires that the sbc file name match the input # structure file, not the com file. sbc_file = "example_2.sbc" # Write an sbc file that will modify the search such that # only sidechain atoms are assigned search parameters and sampled. sbu = mmodutils.SbcUtil() sbu.ASL1[1] = 0 # Add the substructure atoms (set up for search). sbu.ASL1[2] = 'sidechain' # Substructure atoms (set up for search). sbu.ASL2[1] = 250 # Restraint's harmonic force constant. sbu.ASL2[2] = 'not sidechain' # The restrained atoms. sbu_args = [sbc_file, 'ASL1', 'ASL2'] sbu.writeSbcFile(sbu_args) # Example 3 ############################################################ # Writing a sbc file to restrain/constrain part of the structure # with SUBS/FXAT during a simple minimization. Here, the input # structure is a ligand-receptor complex where the ligand has # residue name MTW. The ligand will be freely optimized within the # context of the receptor. The side-chain atoms will be fixed # (restrained with a flat-bottom potential, 0.1 angstrom half-width) # and a ~3 angstrom shell of nearby atoms will be frozen # (constrained). All other atoms are ignored. # Write com file instructions for a simple geometry optimization. # The ComUtil instance is configured such that it will write the # SUBS opcode in the com file. import schrodinger.application.macromodel.utils as mmodutils import schrodinger.structure as structure import schrodinger.structutils.analyze as analyze mcu = mmodutils.ComUtil(subs=True) com_file = mcu.mini("example_3.mae") sbc_file = "example_3.sbc" # Identify the atoms to optimize, restrain and constrain. All other # atoms are ignored. st = structure.Structure.read("example_3.mae") ligand_atoms = analyze.evaluate_asl(st, 'res.pt MTW') binding_site_atoms = analyze.evaluate_asl( st, 'fillres (sidechain and within 5 res.pt MTW)' ) nearby_atoms = analyze.evaluate_asl( st, 'not (res.pt MTW or fillres (sidechain and within 5 res.pt MTW)) and within 10 res.pt MTW' ) # Assign the atoms to SUBS and FXAT commands. sbu = mmodutils.SbcUtil() sbu_args = [sbc_file] sbu_args.extend(sbu.setSubs(ligand_atoms)) sbu_args.extend( sbu.setFixed( binding_site_atoms, force_constant=500, half_width=1 ) ) sbu_args.extend(sbu.setFrozen(nearby_atoms)) sbu.writeSbcFile(sbu_args) # Example 4 ############################################################ # Writing a sbc file to restrain/constrain part of the structure # with ASL1/ASL2, where the input is a series of non-conformers. # Here, the structure file contains a series of non-conformer # polypeptides. The side-chains will be freely optimized and the # backbone will be restrained. Note well, READ arg1=-1 tells # MacroModel to evaluate the sbc for each input structure; a # requirement since the input are non-conformers. # Write com file instructions for a geometry optimization on a # series of structures. The ComUtil instance is configured such # that it will write the SUBS opcode in the com file. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil(subs=True) mcu.READ[1] = -1 # re-evaluate substructure information. com_file = mcu.mini("example_4.mae") sbc_file = "example_4.sbc" # Assign the ASL1/2 commands and write the file. sbu = mmodutils.SbcUtil() sbu.ASL1[1] = 0 # Add the substructure atoms (set up for search). sbu.ASL1[2] = 'sidechain' # Substructure atoms (set up for search). sbu.ASL2[1] = 200 # Restraint's harmonic force constant. sbu.ASL2[2] = 'not sidechain' # The restrained atoms. sbu_args = [sbc_file, 'ASL1', 'ASL2'] sbu.writeSbcFile(sbu_args) # Example 5 ############################################################ # Writing a sbc file to restrain part of the structure with # ASL1/ASL2 and flat-bottom restraints. Here, the structure file # contains a series of non-conformer polypeptides. The side-chains # will be freely optimized and the backbone will be restrained. # Note well, READ arg1=-1 which tells MacroModel to evaluate the sbc # for each input structure; a requirement since the input are # non-conformers. # Write com file instructions for a geometry optimization on a # series of structures. The ComUtil instance is configured such # that it will write the SUBS opcode in the com file. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil(subs=True) mcu.READ[1] = -1 # re-evaluate substructure information. com_file = mcu.mini("example_5.mae") sbc_file = "example_5.sbc" # Assign the ASL1/2 commands and write the file. sbu = mmodutils.SbcUtil(use_flat_bottom_asl2=True) sbu.ASL1[1] = 0 # Add the substructure atoms (set up for search). sbu.ASL1[2] = 'sidechain' # Substructure atoms (set up for search). sbu.ASL2[1] = 5 # half-width, 0.5 angstroms. sbu.ASL2[2] = 200.0 # restrain 200 kJ/mol*A^2. sbu.ASL2[3] = 'not sidechain' # The restrained atoms. sbu_args = [sbc_file, 'ASL1', 'ASL2'] sbu.writeSbcFile(sbu_args) # Example 6 ############################################################ # Writing a sbc file to restrain atoms during a minimization # with ASL2, confirming backwards compatible support for # determining a suitable sbc file name. # Write com file instructions for a simple geometry optimization. # The ComUtil instance is configured such that it will write the # SUBS opcode in the com file. import schrodinger.application.macromodel.utils as mmodutils mcu = mmodutils.ComUtil(subs=True) com_file = mcu.mini("example_6.mae", "example_6_test.com") # Write sbc file that will modify the geometry optimization such that # all atoms are harmonically restrained about their starting coordinates. sbu = mmodutils.SbcUtil() sbu.ASL2[1] = 200 # force constant for Cartesian restraints. sbu.ASL2[2] = 'mol.n 1' # ASL identifying the restrained atoms. sbu_args = [com_file, 'ASL2'] # MacroModel requires that the sbc file name match the input # structure file, not the com file. The method expects a # sbc file name as the first argument, but for backwards # compatibility, supports .com extensions. sbc_file = sbu.writeSbcFile(sbu_args) """
[docs] def __init__(self, use_flat_bottom_asl2=False): self.use_flat_bottom_asl2 = use_flat_bottom_asl2 self.SUBS = {} self.FXAT = {} self.FXDI = {} # restrain distance self.FXTA = {} # restrain torsion angle self.FXBA = {} # restrain bond angle self.FXCO = {} # restrain all torsions self.ASL1 = {} # ASL string for SUBS self.ASL1[1] = 0 # Add the subs asl self.ASL2 = {} # ASL string for FXAT self.ASL2[1] = 200.0 # restraint force constant self.ASL2[2] = 'all' # ASL for the fixed/frozen atoms. if self.use_flat_bottom_asl2: self.ASL2[ 1] = 0 # Flat bottom well width, in tenths of an angstrom. self.ASL2[2] = 200.0 # restraint force constant self.ASL2[3] = 'all' # ASL for the fixed/frozen atoms. self._written = [] self.refit_args = True return
[docs] def writeSbcFile(self, sbc_args=[]): # noqa: M511 """ Writes a sbc file for the list of opcodes, and returns the name of the written sbc file. :param sbc_args: List of arguments to serialize. The first element should be the file name to write, e.g. 'jobname.sbc', where the sbc file name corresponds to the input structure file name not the input com file name. The second and subsequent elements should be OPCD strings. :type sbc_args: list :raises: ValueError if the first element doesn't end with .sbc and an appropriate sbc file name can't be determined. The arguments for the OPCDs are looked up in turn, evaluating the next eight list elements for the specific OPCD argument list, each time the OPCD is encountered. See getOpcdArgs() and __init__() for more information about default arguments. For backwards compatibility, the first argument may also be a '.com', which will write basename.sbc if the com file can't be read, but will otherwise inspect the com file for the input structure file name and construct a suitable sbc file name. """ sbc_file = "" if sbc_args[0].endswith('.sbc'): sbc_file = sbc_args[0] elif sbc_args[0].endswith('.com'): com_file = sbc_args[0] mae_file = '' # If the file exists try to get the name of the input # structure file from the com file contents. Otherwise base # it on the com file name which may or may not be valid. try: with open(com_file) as com_fh: mae_file = com_fh.readline().strip() (root, ext) = fileutils.splitext(mae_file) sbc_file = "%s.sbc" % root except IOError: com_re = re.compile(r'\.com$') sbc_file = com_re.sub('.sbc', com_file, 1) # TODO: Determine if this method should also accept .mae(\.?gz) # and fashion a sbc file name. else: msg = "SbcUtil.writeSbcFile() can't determine sbc file name." raise ValueError(msg) sbc_fh = open(sbc_file, mode='w') for opcd in sbc_args[1:]: sbc_fh.write(self.getOpcdArgs(opcd)) sbc_fh.flush() sbc_fh.close() # Clean up for next write. self._written = [] return sbc_file
[docs] def setSubs(self, subs_list): """ :return: List of 'SUBS' strings after assiging all atom indexed in subs_list to the self.SUBS dict, . This is a simple wrapper for setOpcdArgs() to conveniently set a large number of atoms at once. Assigned SUBS have args5-8 set to 0.0 (the default). :rtype: list :param subs_list: List of atom indexes :type subs_list: list """ opcd_list = [] # Do slices of 4, while len(subs_list) >= 4: self.setOpcdArgs('SUBS', subs_list.pop(0), subs_list.pop(0), subs_list.pop(0), subs_list.pop(0)) opcd_list.append('SUBS') # Assign the dregs if subs_list: self.setOpcdArgs('SUBS', *subs_list) opcd_list.append('SUBS') return opcd_list
[docs] def setFixed( self, fixed_list=[], # noqa: M511 force_constant=200, half_width=0): """ :return: List of 'FXAT' strings after assiging all atom indexed in fixed_list to the self.FXAT dict. This is a simple wrapper for setOpcdArgs() to conveniently set a large number of atoms at once. Assigned FXATs have arg5 = force_constant, and arg6 = half_width :rtype: list :param fixed_list: List of atom indexes :type fixed_list: list :param force_constant: Restraining force constant, typically in units of kJ/mol*A^2. Default is 200. :type force_constant: float :param half_width: Half-width of the flat-bottom restraint potential, in tenths of an angstrom units. Default is 0. :type half_width: integer """ opcd_list = [] # Each atom as one line for iat in fixed_list: self.setOpcdArgs('FXAT', arg1=iat, arg4=half_width, arg5=force_constant) opcd_list.append('FXAT') return opcd_list
[docs] def setFrozen(self, frozen_list=[]): # noqa: M511 """ :return: List of 'FXAT' strings after assiging all atom indexed in frozen_list to the self.FXAT dict, . This is a simple wrapper for setOpcdArgs() to conveniently set a large number of atoms at once. Assigned FXATs have arg5 = -1, to freeze (constrain) the atoms in place. :rtype: list :param frozen_list: List of atom indexes :type frozen_list: list """ opcd_list = [] # Each atom as one line for iat in frozen_list: self.setOpcdArgs('FXAT', arg1=iat, arg5=-1) opcd_list.append('FXAT') return opcd_list
[docs] def getOpcdArgs(self, opcd=""): """ The arguments come from the hash data members, any unknown or unassigned values default to 0 or 0.0. You may customize the self hash arguments to your heart's content prior to invoking the method to get the exact behavior you want. The 'OPCD' lookup requires the passed argument to be a key for the hash, i.e. uppercase with no whitespace. The array of arg values are numbers, not strings. This method keeps count of the number of times an OPCD is called and automatically increments the array of args for the passed OPCD. The first call for a given OPCD uses self['OPCD'] arg slices 1-8, the next call for that OPCD uses slices 9-16, the next 17-24, and so on. writeSbcFile() zeros the count after the com or sbc file is serialized. Returns a formatted string of OPCD and arguments for the passed OPCD string. :param opcd: MacroModel operation code. :type opcd: string """ # Default opcd arguments. bmin usually interprets 0 as some # other default value. args = [opcd, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0.0] args_str = "" # Check multiplicity of this opcode call, i is the index into # the opcd array of args. i = 8 * self._written.count(opcd) if opcd in self.__dict__: args[0] = opcd args[1] = self.__dict__[opcd].get(i + 1, 0) args[2] = self.__dict__[opcd].get(i + 2, 0) args[3] = self.__dict__[opcd].get(i + 3, 0) args[4] = self.__dict__[opcd].get(i + 4, 0) args[5] = self.__dict__[opcd].get(i + 5, 0) args[6] = self.__dict__[opcd].get(i + 6, 0) args[7] = self.__dict__[opcd].get(i + 7, 0) args[8] = self.__dict__[opcd].get(i + 8, 0) if opcd in ['ASL1']: args_str = self._formatSbcAsl1Str(args) elif opcd in ['ASL2']: args_str = self._getSbcAsl2Str(args) else: args_str = self._formatOpcdStr(args) # Record opcd used to later multiplicity checks. This # semi-private array gets emptied after writeSbcFile() serializes # the sbc file. self._written.append(opcd) return args_str
def _formatOpcdStr(self, args): # arg1-4 value size check. for arg_pos in [1, 2, 3, 4]: if len(str(args[arg_pos])) > 6: if self.refit_args and args[arg_pos] > 0: args[arg_pos] = 999999 elif self.refit_args and args[arg_pos] < 0: args[arg_pos] = -99999 # arg5-8 value size check, reformatted if needed. opcd_format = {} for arg_pos in [5, 6, 7, 8]: opcd_format[arg_pos] = '%5.4f' value = str("%f" % args[arg_pos]) if len(value.split('.')[0]) == 6: opcd_format[arg_pos] = '%6.3f' elif len(value.split('.')[0]) == 7: opcd_format[arg_pos] = '%7.2f' elif len(value.split('.')[0]) == 8: opcd_format[arg_pos] = '%8.1f' elif len(value.split('.')[0]) == 9: opcd_format[arg_pos] = '%9.0f.' # note the trailing '.' elif len(value.split('.')[0]) >= 10: if self.refit_args and args[arg_pos] > 0: args[arg_pos] = 999999999 elif self.refit_args and args[arg_pos] < 0: args[arg_pos] = -99999999 opcd_format[arg_pos] = '%9.0f.' args[1] = '%d' % args[1] args[2] = '%d' % args[2] args[3] = '%d' % args[3] args[4] = '%d' % args[4] args[5] = opcd_format[5] % args[5] args[6] = opcd_format[6] % args[6] args[7] = opcd_format[7] % args[7] args[8] = opcd_format[8] % args[8] # Justify the string so we can join the list elements contigiously args[0] = args[0].rjust(5) args[1] = args[1].rjust(8) # eight takes up the OPCD trailing space args[2] = args[2].rjust(7) args[3] = args[3].rjust(7) args[4] = args[4].rjust(7) args[5] = args[5].rjust(11) # the decimal takes a char. args[6] = args[6].rjust(11) args[7] = args[7].rjust(11) args[8] = args[8].rjust(11) args.append('\n') args_string = "".join(args) return args_string def _formatSbcAsl1Str(self, args): # ASL1 takes a special string-aware format: 1X,A4,1X,I7,X,A args[0] = args[0].rjust(5) args[1] = '%d'.rjust(8) % args[1] args[2] = " %s\n" % args[2] args_string = ''.join(args[0:3]) return args_string def _getSbcAsl2Str(self, args): # As of suite2010 ASL2 takes two different formats: # format: 1X,A4,1X,I4,X,F7.3,X,A : suite2010 flat-bottom half-width # format: 1X,A4,1X,F7.3,X,A : pre-suite2009 if self.use_flat_bottom_asl2: #OPCD IIII FFFF.FFF SSSSSSSSSSSSSSSSSSSSSSSSSS...many chars args[0] = args[0].rjust(5) args[1] = '%4d'.rjust(4) % args[1] # four char plus a pad. args[3] = ' %s\n' % args[3] value = str("%f" % args[2]) if len(value.split('.')[0]) >= 7: if self.refit_args and args[2] > 0: args[2] = '%7.0f.'.rjust(7) % 9999999 elif self.refit_args and args[2] < 0: args[2] = '%7.0f.'.rjust(7) % -999999 elif len(value.split('.')[0]) == 6: args[2] = '%6.1f'.rjust(6) % args[2] elif len(value.split('.')[0]) == 5: args[2] = '%5.2f'.rjust(6) % args[2] elif len(value.split('.')[0]) == 4: args[2] = '%4.3f'.rjust(6) % args[2] elif len(value.split('.')[0]) == 3: args[2] = '%3.4f'.rjust(6) % args[2] elif len(value.split('.')[0]) == 2: args[2] = '%2.5f'.rjust(6) % args[2] elif len(value.split('.')[0]) == 1: args[2] = '%1.6f'.rjust(6) % args[2] elif len(value.split('.')[0]) == 0: args[2] = '%0.7f'.rjust(6) % args[2] else: args[2] = '%7.1f'.rjust(7) % args[2] args_string = ''.join(args[0:4]) else: #OPCD FFFF.FFF SSSSSSSSSSSSSSSSSSSSSSSSSS...many chars args[0] = args[0].rjust(5) value = str("%f" % args[1]) if len(value.split('.')[0]) >= 7: if self.refit_args and args[1] > 0: args[1] = '%7.0f.'.rjust(7) % 9999999 elif self.refit_args and args[1] < 0: args[1] = '%7.0f.'.rjust(7) % -999999 elif len(value.split('.')[0]) == 6: args[1] = '%6.1f'.rjust(1) % args[1] elif len(value.split('.')[0]) == 5: args[1] = '%5.2f'.rjust(6) % args[1] elif len(value.split('.')[0]) == 4: args[1] = '%4.3f'.rjust(6) % args[1] elif len(value.split('.')[0]) == 3: args[1] = '%3.4f'.rjust(6) % args[1] elif len(value.split('.')[0]) == 2: args[1] = '%2.5f'.rjust(6) % args[1] elif len(value.split('.')[0]) == 1: args[1] = '%1.6f'.rjust(6) % args[1] elif len(value.split('.')[0]) == 0: args[1] = '%0.7f'.rjust(6) % args[1] else: args[1] = '%7.1f'.rjust(7) % args[1] args[2] = ' %s\n' % args[2] args_string = ''.join(args[0:3]) return args_string
[docs] def setOpcdArgs(self, opcd="", arg1=0, arg2=0, arg3=0, arg4=0, arg5=0.0, arg6=0.0, arg7=0.0, arg8=0.0): """ This method returns True after adding the passed values to the desired opcd dictionary. The dictionary is selected by the first parameter, which is required. The rest of the parameters are mapped to the next eight argument indices in the dictionary. Unspecified values default to 0 or 0.0. This method determines the highest existing index (numeric hash key), and then assigns the passed args to the next available slots. You may want to first blank the dictionary with the appropriate call of self['OPCD'].clear(). Assumming the dictionary has has been cleared, the first 'set' of a given OPCD assigns self['OPCD'] arg indices 1-8, the next call for that OPCD defines indices 9-16, the next 17-24, and so on. """ # Try counting the highest indexed key. i = 0 try: keys = list(self.__dict__[opcd]) if len(keys) > 0: i = keys[-1] except KeyError: self.__dict__[opcd] = {} # Determine the proper index y = divmod(i, 8) # tuple[0] = num of whole sets, tuple[1] = num partials i = y[0] if y[1] > 0: i += 1 # Advance the index by eight, or one 'row', or one call... i = 8 * i # Assign self.__dict__[opcd][i + 1] = arg1 self.__dict__[opcd][i + 2] = arg2 self.__dict__[opcd][i + 3] = arg3 self.__dict__[opcd][i + 4] = arg4 self.__dict__[opcd][i + 5] = arg5 self.__dict__[opcd][i + 6] = arg6 self.__dict__[opcd][i + 7] = arg7 self.__dict__[opcd][i + 8] = arg8 # Return True if we made it this far return True
[docs]class CluUtil: """ A class for writing and running Cluster clu files. The class can fabricate jobname.clu files, and optionally run them. The class allows running Cluster or Xcluster jobs. """
[docs] def __init__( self, arms=['heavy'], # noqa: M511 nrms=[], # noqa: M511 trms=[], # noqa: M511 thresh=0, mmsym=True, nant=False): """ This method loads the default data members and methods. """ ## # Data members ## # version self.version = '$Revision: 1.32.2.1 $' self.arms = arms # array of atom numbers, printed 1 per line self.nrms = nrms # array of atom numbers, printed 1 per line self.trms = trms # array of atom numbers, printed 4 per line self.thresh = thresh # integer describing the critical distance self.writecls = "" # string defining file name and cluster level self.writerep = "" # string defining file name and cluster level self.writeavg = "" # string defining file name and cluster level self.writelead = "" # string defining file name and cluster level self.writemap = "" # string defining file name self.writedst = "" # string defining file name self.mmsym = mmsym self.nant = nant # done with init return None
[docs] def writeCluFile(self, in_file=""): """ This method writes a jobname.clu command file for the passed 'jobname.mae', or 'jobname.dst' file; returns the name fo the clu file written. The keyword values are taken from the self object, and need to be defined prior to calling this method. Returns a string for the 'jobname.clu' file written. The first argument for either Arms: or Nrms: is checked for the value 'heavy' or 'all'. If the first argument in these arrays does not match those values then the array is assumed to contain numerical values and is formatted. If the provided input is a distance file, recognized by a .dst extention, then the job will be run in dfile mode. No additional options are used in dfile mode, and exiting self values for mmsym, nant, arms, and trms are set to false/empty values. """ # Prep regular expressions mae_file_re = re.compile(r'.mae$') dst_file_re = re.compile(r'.dst$') # Change file names, and object defaults if dst_file_re.search(in_file): clu_file = dst_file_re.sub('.clu', in_file) self.mmsym = False self.nant = False self.arms = [] self.trms = [] else: clu_file = mae_file_re.sub('.clu', in_file) # Get our file handle ready to write, clobber existing file clu_fh = open(clu_file, mode='w') # Apply keyword arg regex kw_re = re.compile(r'^(heavy|all)$') # Write keywords and args if dst_file_re.search(in_file): clu_fh.write("".join(["Dfile: ", in_file, '\n'])) else: clu_fh.write("".join(["Sfile: ", in_file, '\n'])) if self.mmsym: clu_fh.write("Mmsym: \n") if self.nant: clu_fh.write("Nant: \n") if self.arms: clu_fh.write("Arms: ") if isinstance(self.arms[0], str) and kw_re.match(self.arms[0]): clu_fh.write("".join([self.arms[0], '\n'])) else: clu_fh.write('\n') for atomnum in self.arms: atomline = '%d' % atomnum atomline.rjust(5) clu_fh.write("".join([atomline, '\n'])) clu_fh.write("\n") if self.nrms: clu_fh.write("Nrms: ") if isinstance(self.nrms[0], str) and kw_re.match(self.nrms[0]): clu_fh.write("".join([self.nrms[0], '\n'])) else: clu_fh.write('\n') for atomnum in self.nrms: atomline = '%d' % atomnum atomline.rjust(5) clu_fh.write("".join([atomline, '\n'])) clu_fh.write('\n') if self.trms: clu_fh.write("Trms:\n") while self.trms: atomline = ' %d %d %d %d' % ( self.trms.pop(), self.trms.pop(), self.trms.pop(), self.trms.pop()) clu_fh.write("".join([atomline, '\n'])) clu_fh.write('\n') clu_fh.write("Cluster: \n") # required command, no args if self.thresh: clu_fh.write("".join(["Thresh: ", repr(self.thresh), "\n"])) if self.writecls: clu_fh.write("".join(["Writecls: ", self.writecls, "\n"])) if self.writerep: clu_fh.write("".join(["Writerep: ", self.writerep, "\n"])) if self.writelead: clu_fh.write("".join(["Writelead: ", self.writelead, "\n"])) if self.writeavg: clu_fh.write("".join(["Writeavg: ", self.writeavg, "\n"])) if self.writemap: clu_fh.write("".join(["Writemap: ", self.writemap, "\n"])) if self.writedst: clu_fh.write("".join(["Writedst: ", self.writedst, "\n"])) # Flush, close clu_fh.flush() clu_fh.close() # Return file name for written clu file return clu_file
[docs] def runCluFile(self, clu_file=""): """ This method uses jobcontrol.launch_job (or system call if import failed) to invoke cluster for the passed jobname.clu file. Returns True. It requires a string containing the 'jobname.clu' file name. """ clu_file_re = re.compile(r'.clu$') # truncate file name clu_file = clu_file_re.sub('', clu_file) cmd = " ".join([ os.path.join(os.environ.get('SCHRODINGER'), 'cluster'), clu_file, ]) # ev45987 fixes for windows # If no jobcontrol, do clean up ourselves as described by Aditya cmd = cmd.replace("\\", "\\\\") cmd = "%s" % cmd os.system(cmd) return True
[docs] def runXCluFile(self, clu_file=""): """ This method uses jobcontrol.launch_job (or a system call if import failed) to invoke Xcluster for the passed jobname.clu file. Returns True. It requires a string containing the 'jobname.clu' file name. """ clu_file_re = re.compile(r'.clu$') # truncate file name clu_file = clu_file_re.sub('', clu_file) cmd = " ".join([ os.path.join(os.environ.get('SCHRODINGER'), 'xcluster -r'), clu_file, ]) # ev45987 fixes for windows # Do command line clean up ourselves as described by Aditya cmd = cmd.replace("\\", "\\\\") cmd = "%s" % cmd os.system(cmd) return True
[docs] def doCluster(self, in_file=""): """ This method writes and runs a cluster job for the passed mae or dst file name. returns True A combination of writeCluFile and runCluFile. """ # Do it return self.runCluFile(self.writeCluFile(in_file))
[docs] def doXCluster(self, in_file=""): """ This method writes and runs a Xcluster job for the passed mae or dst file name, returns True A combination of writeCluFile and runXCluFile. """ # Do it return self.runXCluFile(self.writeCluFile(in_file))
[docs] def writeDstFile(self, dst_file="cluster.dst", values=[]): # noqa: M511 """ This method writes a distance file with the provided name, for the passed values. Returns the name of the distance file written, which is cluster.dst by default. This method calculates the 'distances' between the passed values. The distances are calculated as the absolute value of i - j, truncated as 5.5f, right justified as 16 characters, and printed five per line. For example, if passed a list with nine values, the distance file would look like: 9 d12 d13 d14 d15 d16 d17 d18 d19 d23 d24 d25 d26 d27 d28 d29 d34 d35 d36 d37 d38 d39 d45 d46 d47 d48 d49 d56 d57 d58 d59 d67 d68 d69 d78 d79 d89 where d12 is the formatted result of abs(values[0] - values[1]) """ # Count the total number of N values total_num_points = len(values) # List for calculated distances distances = [] # calculate unique i != j distances for i in range(0, total_num_points): for j in range(0, total_num_points): if i == j: pass # skip on-diagonal values elif i != 0 and j < i: pass # skip symmetric values else: distances.append(abs(values[i] - values[j])) # Get our file handle ready to write, clobber existing file dst_fh = open(dst_file, mode='w') # Thankfully, cluster is forgiving with its dfile format # because this is sketchy dst_fh.write("".join([repr(total_num_points), '\n'])) count = 0 for dist in distances: count = count + 1 dist = '%5.5f' % dist dist = dist.rjust(16) # the decimal takes a char dst_fh.write(dist) if count % 5 == 0: dst_fh.write('\n') # Flush, close dst_fh.flush() dst_fh.close() return dst_file
# EOF