252 lines
7.1 KiB
Python
252 lines
7.1 KiB
Python
'''
|
|
(c) 2010-2012 Thomas Holder (https://github.com/speleo3/pymol-psico)
|
|
(c) 2016 Thomas Holder, Schrodinger, Inc.
|
|
|
|
License: BSD-2-Clause
|
|
'''
|
|
|
|
from pymol import cmd, CmdException
|
|
|
|
|
|
def pdb2pqr(name, selection='all', ff='amber', debump=1, opt=1, assignonly=0,
|
|
ffout='', ph=None, neutraln=0, neutralc=0, state=-1, preserve=0,
|
|
exe='pdb2pqr', quiet=1):
|
|
'''
|
|
DESCRIPTION
|
|
|
|
Creates a new molecule object from a selection and adds missing atoms,
|
|
assignes charges and radii using PDB2PQR.
|
|
|
|
http://www.poissonboltzmann.org/pdb2pqr/
|
|
|
|
USAGE
|
|
|
|
pdb2pqr name [, selection [, ff [, debump [, opt [, assignonly [, ffout [,
|
|
ph [, neutraln [, neutralc [, state [, preserve ]]]]]]]]]]]
|
|
|
|
ARGUMENTS
|
|
|
|
name = string: name of object to create or modify
|
|
|
|
selection = string: atoms to include in the new object {default: all}
|
|
|
|
ff = string: forcefield {default: amber}
|
|
'''
|
|
debump, opt, assignonly = int(debump), int(opt), int(assignonly)
|
|
neutraln, neutralc = int(neutraln), int(neutralc)
|
|
quiet = int(quiet)
|
|
|
|
args = ['--ff=' + ff, '--chain']
|
|
if not debump:
|
|
args.append('--nodebump')
|
|
if not opt:
|
|
args.append('--noopt')
|
|
if assignonly:
|
|
args.append('--assign-only')
|
|
if ffout:
|
|
args.append('--ffout=' + ffout)
|
|
if ph is not None:
|
|
args.append('--with-ph=%f' % float(ph))
|
|
if neutraln:
|
|
args.append('--neutraln')
|
|
if neutralc:
|
|
args.append('--neutralc')
|
|
if not quiet:
|
|
args.append('--verbose')
|
|
|
|
r = pdb2pqr_cli(name, selection, args, state, preserve, exe, quiet)
|
|
|
|
if not quiet:
|
|
if r:
|
|
print(r)
|
|
|
|
print(' pdb2pqr: done')
|
|
|
|
return r
|
|
|
|
|
|
def pdb2pqr_cli(name, selection, options, state=-1, preserve=0,
|
|
exe='pdb2pqr', quiet=1, fixrna=0, _proclist=None):
|
|
import os, tempfile, subprocess, shutil
|
|
|
|
state, preserve, quiet = int(state), int(preserve), int(quiet)
|
|
|
|
if cmd.is_string(options):
|
|
import shlex
|
|
options = shlex.split(options)
|
|
|
|
args = [cmd.exp_path(exe)] + list(options)
|
|
|
|
tmpdir = tempfile.mkdtemp()
|
|
# Input format should be PDB, but use PQR instead because we can support
|
|
# multi-state assemblies by not writing MODEL records.
|
|
infile = os.path.join(tmpdir, 'in.pqr')
|
|
outfile = os.path.join(tmpdir, 'out.pqr')
|
|
args.extend([infile, outfile])
|
|
|
|
# For some reason, catching stdout/stderr with PIPE and communicate()
|
|
# blocks terminate() calls from terminating early. Using a file
|
|
# redirect doesn't show this problem.
|
|
f_stdout = open(os.path.join(tmpdir, 'stdout.txt'), 'w+')
|
|
|
|
# RNA resdiue names must be RA, RC, RG, and RU
|
|
tmpmodel = ''
|
|
if int(fixrna) and cmd.count_atoms('(%s) & resn A+C+G+U' % (selection)):
|
|
tmpmodel = cmd.get_unused_name('_tmp')
|
|
cmd.create(tmpmodel, selection, zoom=0)
|
|
cmd.alter(tmpmodel + ' & polymer.nucleic & resn A+C+G+U',
|
|
'resn = "R" + resn')
|
|
selection = tmpmodel
|
|
|
|
try:
|
|
cmd.save(infile, selection, state)
|
|
|
|
p = subprocess.Popen(args, cwd=tmpdir,
|
|
stdin=subprocess.PIPE, # Windows pythonw fix
|
|
stdout=f_stdout,
|
|
stderr=f_stdout)
|
|
p.stdin.close() # Windows pythonw fix
|
|
|
|
if _proclist is not None:
|
|
_proclist.append(p)
|
|
|
|
p.wait()
|
|
|
|
# This allows PyMOL to capture it and display the output in the GUI.
|
|
f_stdout.seek(0)
|
|
print(f_stdout.read().rstrip())
|
|
|
|
if p.returncode == -15: # SIGTERM
|
|
raise CmdException('pdb2pqr terminated')
|
|
|
|
if p.returncode != 0:
|
|
raise CmdException('%s failed with exit status %d' %
|
|
(args[0], p.returncode))
|
|
|
|
warnings = [L[10:] for L in open(outfile) if L.startswith('REMARK 5')]
|
|
warnings = ''.join(warnings).strip()
|
|
|
|
cmd.load(outfile, name)
|
|
|
|
return warnings
|
|
|
|
except OSError as e:
|
|
print(e)
|
|
raise CmdException('Cannot execute "%s"' % (exe))
|
|
finally:
|
|
if tmpmodel:
|
|
cmd.delete(tmpmodel)
|
|
|
|
f_stdout.close()
|
|
|
|
if not preserve:
|
|
shutil.rmtree(tmpdir)
|
|
elif not quiet:
|
|
print(' Notice: not deleting', tmpdir)
|
|
|
|
|
|
def _is_exe(exe):
|
|
import os, sys
|
|
if os.path.exists(exe):
|
|
return True
|
|
if sys.platform.startswith('win'):
|
|
return os.path.exists(exe + '.exe')
|
|
return False
|
|
|
|
|
|
def prepwizard(name, selection='all', options='', state=-1,
|
|
preserve=0, exe='$SCHRODINGER/utilities/prepwizard', quiet=1,
|
|
_proclist=None):
|
|
'''
|
|
DESCRIPTION
|
|
|
|
Run the SCHRODINGER Protein Preparation Wizard. Builds missing side
|
|
chains and converts MSE to MET. Other non-default options need to be
|
|
passed with the "options=" argument.
|
|
|
|
USAGE
|
|
|
|
prepwizard name [, selection [, options [, state ]]]
|
|
|
|
ARGUMENTS
|
|
|
|
name = str: name of object to create
|
|
|
|
selection = str: atoms to send to the wizard {default: all}
|
|
|
|
options = str: additional command line options for prepwizard
|
|
|
|
state = int: object state {default: -1 (current)}
|
|
'''
|
|
import os, tempfile, subprocess, shutil, shlex
|
|
|
|
state, preserve, quiet = int(state), int(preserve), int(quiet)
|
|
|
|
exe = cmd.exp_path(exe)
|
|
if not _is_exe(exe):
|
|
if 'SCHRODINGER' not in os.environ:
|
|
print(' Warning: SCHRODINGER environment variable not set')
|
|
raise CmdException('no such script: ' + exe)
|
|
|
|
args = [exe, '-mse', '-fillsidechains', '-WAIT']
|
|
|
|
if options:
|
|
if cmd.is_string(options):
|
|
options = shlex.split(options)
|
|
args.extend(options)
|
|
|
|
tmpdir = tempfile.mkdtemp()
|
|
infile = 'in.pdb'
|
|
outfile = 'out.mae'
|
|
args.extend([infile, outfile])
|
|
|
|
try:
|
|
cmd.save(os.path.join(tmpdir, infile), selection, state)
|
|
|
|
env = dict(os.environ)
|
|
env.pop('PYTHONEXECUTABLE', '') # messes up Python on Mac
|
|
|
|
import pymol
|
|
if pymol.IS_WINDOWS:
|
|
# Fix for 2020-4 (PYMOL-3572)
|
|
import ctypes
|
|
ctypes.windll.kernel32.SetDllDirectoryW(None)
|
|
|
|
p = subprocess.Popen(args, cwd=tmpdir,
|
|
env=env,
|
|
universal_newlines=True,
|
|
stdin=subprocess.PIPE, # Windows pythonw fix
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT)
|
|
|
|
if _proclist is not None:
|
|
_proclist.append(p)
|
|
|
|
print(p.communicate()[0].rstrip())
|
|
|
|
if p.wait() == -15: # SIGTERM
|
|
raise CmdException('prepwizard terminated')
|
|
|
|
if p.returncode != 0:
|
|
raise CmdException('%s failed with exit status %d' % (args[0], p.returncode))
|
|
|
|
cmd.load(os.path.join(tmpdir, outfile), name)
|
|
except OSError as e:
|
|
print(e)
|
|
raise CmdException('Cannot execute "%s"' % (exe))
|
|
finally:
|
|
logfile = os.path.join(tmpdir, 'in.log')
|
|
if os.path.exists(logfile):
|
|
with open(logfile) as handle:
|
|
print(handle.read())
|
|
if not preserve:
|
|
shutil.rmtree(tmpdir)
|
|
elif not quiet:
|
|
print(' Notice: not deleting', tmpdir)
|
|
|
|
if not quiet:
|
|
print(' prepwizard: done')
|
|
|
|
|
|
# vi: ts=4:sw=4:smarttab:expandtab
|