196 lines
5.2 KiB
Python
196 lines
5.2 KiB
Python
'''
|
|||
|
|
APBS wrapper
|
||
|
|
|
||
|
|
(c) 2012 Thomas Holder (https://github.com/speleo3/pymol-psico)
|
||
|
|
(c) 2016 Thomas Holder, Schrodinger, Inc.
|
||
|
|
|
||
|
|
License: BSD-2-Clause
|
||
|
|
'''
|
||
|
|
|
||
|
|
import os
|
||
|
|
|
||
|
|
from pymol import cmd, CmdException
|
||
|
|
|
||
|
|
template_apbs_in = '''
|
||
|
|
read
|
||
|
|
mol pqr "{pqrfile}"
|
||
|
|
end
|
||
|
|
elec
|
||
|
|
mg-auto
|
||
|
|
mol 1
|
||
|
|
|
||
|
|
fgcent {fgcent} # fine grid center
|
||
|
|
cgcent mol 1 # coarse grid center
|
||
|
|
fglen {fglen}
|
||
|
|
cglen {cglen}
|
||
|
|
dime {dime}
|
||
|
|
lpbe # l=linear, n=non-linear Poisson-Boltzmann equation
|
||
|
|
bcfl sdh # "Single Debye-Hueckel" boundary condition
|
||
|
|
pdie 2.0 # protein dielectric
|
||
|
|
sdie 78.0 # solvent dielectric
|
||
|
|
chgm spl2 # Cubic B-spline discretization of point charges on grid
|
||
|
|
srfm smol # smoothed surface for dielectric and ion-accessibility coefficients
|
||
|
|
swin 0.3
|
||
|
|
temp 310.0 # temperature
|
||
|
|
sdens 10.0
|
||
|
|
calcenergy no
|
||
|
|
calcforce no
|
||
|
|
srad {srad} # solvent radius
|
||
|
|
|
||
|
|
ion charge +1 conc 0.15 radius 2.0
|
||
|
|
ion charge -1 conc 0.15 radius 1.8
|
||
|
|
|
||
|
|
write pot dx "{mapfile}"
|
||
|
|
end
|
||
|
|
quit
|
||
|
|
'''
|
||
|
|
|
||
|
|
|
||
|
|
def find_apbs_exe():
|
||
|
|
import shutil
|
||
|
|
exe = shutil.which('apbs')
|
||
|
|
if not exe:
|
||
|
|
exe = cmd.exp_path('$SCHRODINGER/utilities/apbs')
|
||
|
|
if not os.path.exists(exe):
|
||
|
|
return None
|
||
|
|
return exe
|
||
|
|
|
||
|
|
|
||
|
|
def validate_apbs_exe(exe):
|
||
|
|
'''Get and validate apbs executable.
|
||
|
|
Raise CmdException if not found or broken.'''
|
||
|
|
import subprocess
|
||
|
|
|
||
|
|
if exe:
|
||
|
|
exe = cmd.exp_path(exe)
|
||
|
|
else:
|
||
|
|
exe = find_apbs_exe() or 'apbs'
|
||
|
|
|
||
|
|
try:
|
||
|
|
r = subprocess.call([exe, "--version"],
|
||
|
|
stdin=subprocess.PIPE, # Windows pythonw fix
|
||
|
|
stdout=open(os.devnull, "w"), stderr=subprocess.STDOUT)
|
||
|
|
if r < 0:
|
||
|
|
raise CmdException("Broken executable: " + exe)
|
||
|
|
except OSError as e:
|
||
|
|
print(e)
|
||
|
|
raise CmdException("Cannot execute: " + exe)
|
||
|
|
|
||
|
|
return exe
|
||
|
|
|
||
|
|
def map_new_apbs(name, selection='all', grid=0.5, buffer=10.0, state=1,
|
||
|
|
preserve=0, exe='', assign=0, focus='', quiet=1, _template='',
|
||
|
|
_proclist=None):
|
||
|
|
'''
|
||
|
|
DESCRIPTION
|
||
|
|
|
||
|
|
Create electrostatic potential map with APBS.
|
||
|
|
|
||
|
|
"selection" needs partial charges (partial_charge) and radii (elec_radius)
|
||
|
|
assigned. These can be loaded for example from a PQR file.
|
||
|
|
|
||
|
|
SEE ALSO
|
||
|
|
|
||
|
|
map_new (coulomb), psico.electrostatics
|
||
|
|
'''
|
||
|
|
import tempfile, shutil, glob, subprocess
|
||
|
|
|
||
|
|
selection = '(%s) and not solvent' % (selection)
|
||
|
|
grid, buffer, state = float(grid), float(buffer), int(state)
|
||
|
|
preserve, assign, quiet = int(preserve), int(assign), int(quiet)
|
||
|
|
|
||
|
|
# path to apbs executable
|
||
|
|
exe = validate_apbs_exe(exe)
|
||
|
|
|
||
|
|
# temporary directory
|
||
|
|
tempdir = tempfile.mkdtemp()
|
||
|
|
if not quiet:
|
||
|
|
print(' Tempdir:', tempdir)
|
||
|
|
|
||
|
|
# filenames
|
||
|
|
pqrfile = os.path.join(tempdir, 'mol.pqr')
|
||
|
|
infile = os.path.join(tempdir, 'apbs.in')
|
||
|
|
stem = os.path.join(tempdir, 'map')
|
||
|
|
|
||
|
|
# temporary selection
|
||
|
|
tmpname = cmd.get_unused_name('_sele')
|
||
|
|
cmd.select(tmpname, selection, 0)
|
||
|
|
|
||
|
|
cmd.save(pqrfile, tmpname, state, format='pqr', quiet=quiet)
|
||
|
|
|
||
|
|
# grid dimensions
|
||
|
|
extent = cmd.get_extent(tmpname, state)
|
||
|
|
extentfocus = cmd.get_extent(focus) if focus else extent
|
||
|
|
fglen = [(emax-emin + 2*buffer) for (emin, emax) in zip(*extentfocus)]
|
||
|
|
cglen = [(emax-emin + 4*buffer) for (emin, emax) in zip(*extent)]
|
||
|
|
# make coarse grid a cube (better for non-globular shapes)
|
||
|
|
cglen = [max(cglen)] * 3
|
||
|
|
|
||
|
|
cmd.delete(tmpname)
|
||
|
|
|
||
|
|
apbs_in = {
|
||
|
|
'pqrfile': pqrfile,
|
||
|
|
'fgcent': 'mol 1',
|
||
|
|
'fglen': '%f %f %f' % tuple(fglen),
|
||
|
|
'cglen': '%f %f %f' % tuple(cglen),
|
||
|
|
'srad': cmd.get('solvent_radius'),
|
||
|
|
'mapfile': stem,
|
||
|
|
}
|
||
|
|
|
||
|
|
if focus:
|
||
|
|
apbs_in['fgcent'] = '%f %f %f' % tuple((emax + emin) / 2.0
|
||
|
|
for (emin, emax) in zip(*extentfocus))
|
||
|
|
|
||
|
|
try:
|
||
|
|
# apbs will fail if grid does not fit into memory
|
||
|
|
# -> on failure repeat with larger grid spacing
|
||
|
|
for _ in range(3):
|
||
|
|
dime = [1 + max(64, n / grid) for n in fglen]
|
||
|
|
apbs_in['dime'] = '%d %d %d' % tuple(dime)
|
||
|
|
|
||
|
|
# apbs input file
|
||
|
|
with open(infile, 'w') as f:
|
||
|
|
f.write((_template or template_apbs_in).format(**apbs_in))
|
||
|
|
|
||
|
|
# run apbs
|
||
|
|
p = subprocess.Popen([exe, infile], cwd=tempdir)
|
||
|
|
|
||
|
|
if _proclist is not None:
|
||
|
|
_proclist.append(p)
|
||
|
|
|
||
|
|
r = p.wait()
|
||
|
|
|
||
|
|
if r == -15: # SIGTERM
|
||
|
|
raise CmdException('apbs terminated')
|
||
|
|
|
||
|
|
if r == 0:
|
||
|
|
break
|
||
|
|
|
||
|
|
if r in (-6, -9):
|
||
|
|
grid *= 2.0
|
||
|
|
if not quiet:
|
||
|
|
print(' Warning: retry with grid =', grid)
|
||
|
|
continue
|
||
|
|
|
||
|
|
raise CmdException('apbs failed with code ' + str(r))
|
||
|
|
|
||
|
|
dx_list = glob.glob(stem + '*.dx')
|
||
|
|
if not dx_list:
|
||
|
|
dx_list = glob.glob(stem + '*.dxbin')
|
||
|
|
if len(dx_list) != 1:
|
||
|
|
raise CmdException('dx file missing')
|
||
|
|
|
||
|
|
# load map
|
||
|
|
cmd.load(dx_list[0], name, quiet=quiet)
|
||
|
|
except OSError as e:
|
||
|
|
print(e)
|
||
|
|
raise CmdException('Cannot execute "%s"' % (exe))
|
||
|
|
finally:
|
||
|
|
if not preserve:
|
||
|
|
shutil.rmtree(tempdir)
|
||
|
|
elif not quiet:
|
||
|
|
print(' Notice: not deleting %s' % (tempdir))
|
||
|
|
|
||
|
|
|
||
|
|
# vi: ts=4:sw=4:smarttab:expandtab
|