"""
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