def validate_apbs_exe(exe): '''Get and validate apbs executable. Raise CmdException if not found or broken.''' import os, subprocess if exe: exe = cmd.exp_path(exe) else: try: import freemol.apbs exe = freemol.apbs.get_exe_path() except: pass if not exe: exe = cmd.exp_path('$SCHRODINGER/utilities/apbs') if not os.path.exists(exe): exe = "apbs" try: r = subprocess.call([exe, "--version"], stdout=open(os.devnull, "w"), stderr=subprocess.STDOUT) if r < 0: raise CmdException("Broken executable: " + exe) except OSError: raise CmdException("Cannot execute: " + exe) return exe
def loadall(pattern, group="", quiet=1, **kwargs): """ DESCRIPTION Load all files matching given globbing pattern """ import glob, os filenames = glob.glob(cmd.exp_path(pattern)) for filename in filenames: if not quiet: print " Loading", filename cmd.load(filename, **kwargs) if len(group): if kwargs.get("object", "") != "": print " Warning: group and object arguments given" members = [kwargs["object"]] else: from pymol.cmd import file_ext_re, gz_ext_re, safe_oname_re members = [ gz_ext_re.sub("", file_ext_re.sub("", safe_oname_re.sub("_", os.path.split(filename)[-1]))) for filename in filenames ] cmd.group(group, " ".join(members))
def save_pdb_with_anisou(filename, selection='(all)', state=1, quiet=1): ''' DESCRIPTION Save in PDB format including ANISOU records. SEE ALSO save ''' state, quiet = int(state), int(quiet) pdbstr = cmd.get_pdbstr(selection, state) atom_it = iter(cmd.get_model(selection, state).atom) def mergeaniso(): for line in pdbstr.splitlines(True): yield line if line[:6] in ['ATOM ', 'HETATM']: u_str = ''.join('%7.0f' % (u * 1e4) for u in atom_it.next().u_aniso) yield 'ANISOU' + line[6:28] + u_str + line[70:] pdbstr = ''.join(mergeaniso()) filename = cmd.exp_path(filename) f = open(filename, 'w') f.write(pdbstr) f.close() if not quiet: print(' Save with ANISOU: wrote "%s"' % (filename))
def get_sess(self,file): from chempy import io file = cmd.exp_path(file) sess = io.pkl.fromFile(file) del sess['wizard'] del sess['main'] return sess
def loadall(pattern, group='', quiet=1, **kwargs): ''' DESCRIPTION Load all files matching given globbing pattern ''' import glob, os filenames = glob.glob(cmd.exp_path(pattern)) for filename in filenames: if not quiet: print(' Loading ' + filename) cmd.load(filename, **kwargs) if len(group): if kwargs.get('object', '') != '': print(' Warning: group and object arguments given') members = [kwargs['object']] else: from pymol.cmd import file_ext_re, gz_ext_re, safe_oname_re members = [ gz_ext_re.sub( '', file_ext_re.sub( '', safe_oname_re.sub('_', os.path.split(filename)[-1]))) for filename in filenames ] cmd.group(group, ' '.join(members))
def get_sess(self, file): from chempy import io file = cmd.exp_path(file) sess = io.pkl.fromFile(file) del sess['wizard'] del sess['main'] return sess
def pref_save(filename=PYMOLPLUGINSRC, quiet=1): import pprint repr = pprint.pformat try: f = open(cmd.exp_path(filename), 'w') except IOError: print(' Plugin-Error: Cannot write Plugins resource file to', filename) return print('# AUTOGENERATED FILE', file=f) print('try:', file=f) print(' import', __name__, file=f) print(' ' + __name__ + '.autoload =', repr(autoload), file=f) print(' ' + __name__ + '.preferences =', repr(preferences), file=f) print(' ' + __name__ + '.set_startup_path(', repr(get_startup_path(True)), ', False)', file=f) print('except:', file=f) print(' import os', file=f) print(' print("Error while loading " + os.path.abspath(__script__))', file=f) f.close() if not int(quiet): print(' Plugin settings saved!')
def intra_theseus(selection, state=1, cov=0, cycles=200, exe='theseus', preserve=0, quiet=1, *, _self=cmd): ''' DESCRIPTION Fits all states of an object to an atom selection with maximum likelihood. THESEUS: Maximum likelihood multiple superpositioning http://www.theseus3d.org ARGUMENTS selection = string: atoms to fit state = integer: keep transformation of this state unchanged {default: 1} cov = 0/1: 0 is variance weighting, 1 is covariance weighting (slower) {default: 0} SEE ALSO intra_fit, intra_rms_cur ''' import tempfile, os state, cov, cycles = int(state), int(cov), int(cycles) preserve, quiet = int(preserve), int(quiet) tempdir = tempfile.mkdtemp() filename = os.path.join(tempdir, 'mobile.pdb') _self.save(filename, selection, 0) exe = cmd.exp_path(exe) args = [exe, '-a0', '-c' if cov else '-v', '-i%d' % cycles, filename] translations = [] rotations = [] translations, rotations = _run_theseus(args, tempdir, preserve, quiet) matrices = [R[0:3] + [-t[0]] + R[3:6] + [-t[1]] + R[6:9] + [-t[2], 0,0,0, 1] for (R, t) in zip(rotations, translations)] # intra fit states obj_list = _self.get_object_list(selection) for i, m in enumerate(matrices): for obj in obj_list: _self.transform_object(obj, m, i+1, transpose=1) # fit back to given state if 0 < state <= len(matrices): m = list(matrices[state-1]) for i in [3,7,11]: m[i] *= -1 for obj in obj_list: _self.transform_object(obj, m, 0) if not quiet: print(' intra_theseus: %d states aligned' % (len(matrices)))
def intra_theseus(selection, state=1, cov=0, cycles=200, exe='theseus', preserve=0, quiet=1): ''' DESCRIPTION Fits all states of an object to an atom selection with maximum likelihood. THESEUS: Maximum likelihood multiple superpositioning http://www.theseus3d.org ARGUMENTS selection = string: atoms to fit state = integer: keep transformation of this state unchanged {default: 1} cov = 0/1: 0 is variance weighting, 1 is covariance weighting (slower) {default: 0} SEE ALSO intra_fit, intra_rms_cur ''' import tempfile, os state, cov, cycles = int(state), int(cov), int(cycles) preserve, quiet = int(preserve), int(quiet) tempdir = tempfile.mkdtemp() filename = os.path.join(tempdir, 'mobile.pdb') cmd.save(filename, selection, 0) exe = cmd.exp_path(exe) args = [exe, '-a0', '-c' if cov else '-v', '-i%d' % cycles, filename] translations = [] rotations = [] translations, rotations = _run_theseus(args, tempdir, preserve, quiet) matrices = [R[0:3] + [-t[0]] + R[3:6] + [-t[1]] + R[6:9] + [-t[2], 0,0,0, 1] for (R, t) in zip(rotations, translations)] # intra fit states obj_list = cmd.get_object_list('(' + selection + ')') for i, m in enumerate(matrices): for obj in obj_list: cmd.transform_object(obj, m, i+1, transpose=1) # fit back to given state if 0 < state <= len(matrices): m = list(matrices[state-1]) for i in [3,7,11]: m[i] *= -1 for obj in obj_list: cmd.transform_object(obj, m, 0) if not quiet: print(' intra_theseus: %d states aligned' % (len(matrices)))
def prosmart(mobile, target, mobile_state=1, target_state=1, exe='prosmart', transform=1, object=None, quiet=0): ''' DESCRIPTION ProSMART wrapper. http://www2.mrc-lmb.cam.ac.uk/groups/murshudov/ ''' import subprocess, tempfile, os, shutil, glob quiet = int(quiet) tempdir = tempfile.mkdtemp() mobile_filename = os.path.join(tempdir, 'mobile.pdb') target_filename = os.path.join(tempdir, 'target.pdb') cmd.save(mobile_filename, mobile, state=mobile_state) cmd.save(target_filename, target, state=target_state) exe = cmd.exp_path(exe) args = [exe, '-p1', mobile_filename, '-p2', target_filename, '-a'] xglob = lambda x: glob.glob(os.path.join(tempdir, 'ProSMART_Output/Output_Files', x)) try: subprocess.check_call(args, cwd=tempdir) transfiles = xglob('Superposition/Transformations/*/*.txt') with open(transfiles[0]) as f: f = iter(f) for line in f: if line.startswith('ROTATION'): matrix = [list(map(float, next(f).split())) + [0] for _ in range(3)] elif line.startswith('TRANSLATION'): matrix.append([-float(v) for v in next(f).split()] + [1]) break if int(transform): matrix = [v for m in matrix for v in m] assert len(matrix) == 4*4 for model in cmd.get_object_list('(' + mobile + ')'): cmd.transform_object(model, matrix, state=0) if object: from .importing import load_aln alnfiles = xglob('Residue_Alignment_Scores/*/*.txt') alnfiles = [x for x in alnfiles if not x.endswith('_clusters.txt')] load_aln(alnfiles[0], object, mobile, target) except OSError: print(' Error: Cannot execute "%s", please provide full path to prosmart executable' % (exe)) raise CmdException finally: shutil.rmtree(tempdir) if not quiet: print(' prosmart: done')
def run_testfiles(filenames='all', verbosity=2, out=sys.stderr, **kwargs): ''' DESCRIPTION Run one or multiple unit test files as a test suite. USAGE run_testfiles file1 file2 ... [, verbosity [, out ]] ''' import glob if filenames in ('all', ['all']): global run_all run_all = True filenames = os.path.join(pymol_test_dir, 'tests', '*', '*.py') if isinstance(filenames, basestring): filenames = [filename for pattern in filenames.split() for filename in glob.glob(cmd.exp_path(pattern))] suite = unittest.TestSuite() for filename in filenames: if os.path.isdir(filename): filenames.extend(glob.glob(os.path.join(filename, '*.py'))) continue mod = import_from_file(filename) # hacky: register working directory with test cases dirname = os.path.abspath(os.path.dirname(filename)) PyMOLTestCase.moddirs[mod.__name__] = dirname suite.addTest(unittest.defaultTestLoader .loadTestsFromModule(mod)) if not 'xml' in kwargs: kwargs['xml'] = False if kwargs['xml']: import xmlrunner testresult = xmlrunner.XMLTestRunner(output=out, verbosity=int(verbosity)).run(suite) else: if isinstance(out, str): out = open(out, 'w') testresult = unittest.TextTestRunner(stream=out, resultclass=PyMOLTestResult, verbosity=int(verbosity)).run(suite) while deferred_unlink: os.unlink(deferred_unlink.pop()) while deferred_rmtree: import subprocess subprocess.call(['rd', '/s', '/q', deferred_rmtree.pop()], shell=True) return len(testresult.errors) + len(testresult.failures)
def theseus(mobile, target, match='align', cov=0, cycles=200, mobile_state=1, target_state=1, exe='theseus', preserve=0, quiet=1, *, _self=cmd): ''' DESCRIPTION Structural superposition of two molecules with maximum likelihood. THESEUS: Maximum likelihood multiple superpositioning http://www.theseus3d.org ARGUMENTS mobile = string: atom selection for mobile atoms target = string: atom selection for target atoms match = string: in, like, align, none or the name of an alignment object (see "local_rms" help for details) {default: align} cov = 0/1: 0 is variance weighting, 1 is covariance weighting (slower) {default: 0} SEE ALSO align, super, cealign ''' import tempfile, os cov, cycles = int(cov), int(cycles) mobile_state, target_state = int(mobile_state), int(target_state) preserve, quiet = int(preserve), int(quiet) tempdir = tempfile.mkdtemp() mobile_filename = os.path.join(tempdir, 'mobile.pdb') target_filename = os.path.join(tempdir, 'target.pdb') mm = MatchMaker(mobile, target, match, _self=_self) _self.save(mobile_filename, mm.mobile, mobile_state) _self.save(target_filename, mm.target, target_state) exe = cmd.exp_path(exe) args = [exe, '-a0', '-c' if cov else '-v', '-i%d' % cycles, mobile_filename, target_filename] translations, rotations = _run_theseus(args, tempdir, preserve, quiet) matrices = [R[0:3] + [i*t[0]] + R[3:6] + [i*t[1]] + R[6:9] + [i*t[2], 0,0,0, 1] for (R, t, i) in zip(rotations, translations, [-1,1])] obj_list = _self.get_object_list(mobile) for obj in obj_list: _self.transform_object(obj, matrices[0], 0, transpose=1) _self.transform_object(obj, matrices[1], 0) if not quiet: print(' theseus: done')
def dss_promotif(selection="all", exe="", raw="", state=-1, quiet=1): """ DESCRIPTION Secondary structure assignment with PROMOTIF. http://www.rubic.rdg.ac.uk/~gail/#Software SEE ALSO dss, dssp, stride """ from subprocess import Popen, PIPE import tempfile, os, shutil state, quiet = int(state), int(quiet) ss_map = {"B": "S", "E": "S", "H": "H", "G": "H"} exe = cmd.exp_path(exe) if not exe: from . import which motifdir = os.environ.get("motifdir") exe = which("p_sstruc3", "p_sstruc2", "promotif.scr", path=[motifdir] if motifdir else None) tmpdir = tempfile.mkdtemp() tmpfilepdb = os.path.join(tmpdir, "xxxx.pdb") tmpfilesst = os.path.join(tmpdir, "xxxx.sst") ss_dict = dict() try: for model in cmd.get_object_list("(" + selection + ")"): cmd.save(tmpfilepdb, "model %s and (%s)" % (model, selection), state) process = Popen([exe, tmpfilepdb], cwd=tmpdir, stdin=PIPE) process.communicate(tmpfilepdb + os.linesep) with open(tmpfilesst) as handle: for line in handle: if line.startswith(" num seq.no"): break for line in handle: if not line.strip(): break chain = line[6].strip("-") resi = line[7:12].strip() ss = line[23] ss_dict[model, chain, resi] = ss os.remove(tmpfilesst) except OSError: print " Error: Cannot execute exe=" + exe raise CmdException finally: shutil.rmtree(tmpdir) _common_ss_alter(selection, ss_dict, ss_map, raw)
def theseus(mobile, target, match='align', cov=0, cycles=200, mobile_state=1, target_state=1, exe='theseus', preserve=0, quiet=1): ''' DESCRIPTION Structural superposition of two molecules with maximum likelihood. THESEUS: Maximum likelihood multiple superpositioning http://www.theseus3d.org ARGUMENTS mobile = string: atom selection for mobile atoms target = string: atom selection for target atoms match = string: in, like, align, none or the name of an alignment object (see "local_rms" help for details) {default: align} cov = 0/1: 0 is variance weighting, 1 is covariance weighting (slower) {default: 0} SEE ALSO align, super, cealign ''' import tempfile, os cov, cycles = int(cov), int(cycles) mobile_state, target_state = int(mobile_state), int(target_state) preserve, quiet = int(preserve), int(quiet) tempdir = tempfile.mkdtemp() mobile_filename = os.path.join(tempdir, 'mobile.pdb') target_filename = os.path.join(tempdir, 'target.pdb') mm = MatchMaker(mobile, target, match) cmd.save(mobile_filename, mm.mobile, mobile_state) cmd.save(target_filename, mm.target, target_state) exe = cmd.exp_path(exe) args = [exe, '-a0', '-c' if cov else '-v', '-i%d' % cycles, mobile_filename, target_filename] translations, rotations = _run_theseus(args, tempdir, preserve, quiet) matrices = [R[0:3] + [i*t[0]] + R[3:6] + [i*t[1]] + R[6:9] + [i*t[2], 0,0,0, 1] for (R, t, i) in zip(rotations, translations, [-1,1])] obj_list = cmd.get_object_list('(' + mobile + ')') for obj in obj_list: cmd.transform_object(obj, matrices[0], 0, transpose=1) cmd.transform_object(obj, matrices[1], 0) if not quiet: print(' theseus: done')
def get_sess(self,file): from chempy import io try: file = cmd.exp_path(file) sess = io.pkl.fromFile(file) del sess['wizard'] del sess['main'] return sess except: traceback.print_exc() return None
def run(filename, namespace='global', _spawn=0, _self=None): ''' DESCRIPTION "run" executes an external Python script in a local name space, the main Python namespace, the global PyMOL namespace, or in its own namespace (as a module). USAGE run file [, namespace ] ARGUMENTS file = string: a Python program, typically ending in .py or .pym. namespace = local, global, module, main, or private {default: global} NOTES Due to an idiosyncracy in Pickle, you can not pickle objects directly created at the main level in a script run as "module", (because the pickled object becomes dependent on that module). Workaround: delegate construction to an imported module. SEE ALSO spawn ''' from __main__ import __dict__ as ns_main from pymol import __dict__ as ns_pymol if not _self: from pymol import cmd as _self if filename.endswith('.pml'): return _self.load(filename) path = _self.exp_path(filename) spawn = int(_spawn) run_ = spawn_file if spawn else run_file if namespace == 'global': run_(path, ns_pymol, ns_pymol) elif namespace == 'local': run_(path, ns_pymol, {}) elif namespace == 'main': run_(path, ns_main, ns_main) elif namespace == 'private': run_(path, ns_main, {}) elif namespace == 'module': run_file_as_module(path, spawn=spawn) else: raise ValueError('invalid namespace "%s"' % namespace)
def find_apbs_exe(): try: import freemol.apbs exe = freemol.apbs.get_exe_path() except: exe = '' if not exe: exe = cmd.exp_path('$SCHRODINGER/utilities/apbs') if not os.path.exists(exe): from distutils import spawn exe = spawn.find_executable('apbs') return exe
def save(self): # write compounds to a file if self.object==None: print " Filter-Error: please choose an object first" else: self.check_object_dict() fname = self.object+".txt" try: f=open(fname,'w') f.close() except: print " Filter-Warning: '"+fname+"' in current directory is not writable." print " Filter-Warning: attempting to write in home directory." fname = cmd.exp_path(os.path.join('~', fname)) try: f=open(fname,'w') sd = self.state_dict sdo = self.dict[self.object] f.write('Object\t"%s"\n'%(self.object)) f.write('Total\t%d\nAccepted\t%d\nRejected\t%d\nDeferred\t%d\nRemaining\t%d\n\n'%( self.tota, self.acce, self.reje, self.defe, self.togo)) # sort output in order of states lst = [] for a in sd.keys(): lst.append((sd[a],a)) lst.sort() # write list with decisions for a in lst: if sdo.has_key(a[1]): f.write('%d\t"%s"\t"%s"\n'%(a[0],a[1],sdo[a[1]])) else: f.write('%d\t"%s"\t"?"\n'%(a[0],a[1])) f.close() print " Filter: Wrote '%s'."%fname except: traceback.print_exc() print " Filter-Error: Unable to write '%s'."%fname
def save(self): # write compounds to a file if self.object is None: print(" Filter-Error: please choose an object first") else: self.check_object_dict() fname = self.object+".txt" try: f=open(fname,'w') f.close() except: print(" Filter-Warning: '"+fname+"' in current directory is not writable.") print(" Filter-Warning: attempting to write in home directory.") fname = cmd.exp_path(os.path.join('~', fname)) try: f=open(fname,'w') sd = self.state_dict sdo = self.dict[self.object] f.write('Object\t"%s"\n'%(self.object)) f.write('Total\t%d\nAccepted\t%d\nRejected\t%d\nDeferred\t%d\nRemaining\t%d\n\n'%( self.tota, self.acce, self.reje, self.defe, self.togo)) # sort output in order of states lst = [] for a in sd.keys(): lst.append((sd[a],a)) lst.sort() # write list with decisions for a in lst: if a[1] in sdo: f.write('%d\t"%s"\t"%s"\n'%(a[0],a[1],sdo[a[1]])) else: f.write('%d\t"%s"\t"?"\n'%(a[0],a[1])) f.close() print(" Filter: Wrote '%s'."%fname) except: traceback.print_exc() print(" Filter-Error: Unable to write '%s'."%fname)
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 loadall(pattern, group='', quiet=1, **kwargs): ''' DESCRIPTION Load all files matching given globbing pattern ''' import glob, os filenames = glob.glob(cmd.exp_path(pattern)) for filename in filenames: if not quiet: print ' Loading', filename cmd.load(filename, **kwargs) if len(group): if kwargs.get('object', '') != '': print ' Warning: group and object arguments given' members = [kwargs['object']] else: from pymol.cmd import file_ext_re, gz_ext_re, safe_oname_re members = [gz_ext_re.sub('', file_ext_re.sub('', safe_oname_re.sub('_', os.path.split(filename)[-1]))) for filename in filenames] cmd.group(group, ' '.join(members))
def pref_save(filename='~/.pymolrc_plugins.py', quiet=1): import pprint repr = pprint.pformat try: f = open(cmd.exp_path(filename), 'w') except IOError: print ' Plugin-Error: Cannot write Plugins resource file to', filename return print >> f, '# AUTOGENERATED FILE' print >> f, 'try:' print >> f, ' import', __name__ print >> f, ' ' + __name__ + '.autoload =', repr(autoload) print >> f, ' ' + __name__ + '.preferences =', repr(preferences) print >> f, ' ' + __name__ + '.set_startup_path(', repr(get_startup_path()), ', False)' print >> f, 'except:' print >> f, ' import os' print >> f, ' print "Error while loading " + os.path.abspath(__script__)' f.close() if not int(quiet): print ' Plugin settings saved!'
def save_settings(filename='~/.pymolrc-settings.py', quiet=1): ''' DESCRIPTION Dumps all settings with non-default values to ~/.pymolrc-settings.py Feature Request: Save settings for later use - ID: 1009951 https://sourceforge.net/tracker/?func=detail&aid=1009951&group_id=4546&atid=354546 ''' from pymol.setting import get_name_list quiet = int(quiet) if not filename.endswith('.py'): print('Warning: filename should end with ".py"') # temporatily load default settings and remember them cmd.reinitialize('store_defaults') cmd.reinitialize('original_settings') original = [(name, cmd.get(name)) for name in get_name_list()] cmd.reinitialize('settings') # dump to file filename = cmd.exp_path(filename) f = open(filename, 'w') print('# AUTOGENERATED FILE', file=f) print('from pymol import cmd, invocation', file=f) print('if invocation.options.show_splash:', end=' ', file=f) # no newline print(' print "Loading settings from",', repr(filename), file=f) count = 0 for name, o_value in original: value = cmd.get(name) if value != o_value: print('cmd.set("%s", %s)' % (name, repr(value)), file=f) if not quiet: print('set %s, %s # default: %s' % (name, value, o_value)) count += 1 f.close() if not quiet: print('Dumped %d settings to %s' % (count, filename))
def load_aln(filename, object=None, mobile=None, target=None, mobile_id=None, target_id=None, format='', transform=0, quiet=1): ''' DESCRIPTION Load an alignment from file and apply it to already loaded structures. USAGE load_aln filename [, object [, mobile [, target [, mobile_id [, target_id [, format ]]]]]] ARGUMENTS filename = string: alignment file object = string: name of the object {default: filename prefix} mobile, target = string: atom selections {default: ids from alignment file} mobile_id, target_id = string: ids from alignment file {default: first two} format = string: file format, see http://biopython.org/wiki/AlignIO {default: guess from first line in file} EXAMPLE fetch 1bz4 1cpr, async=0 super 1bz4 and guide, 1cpr and guide, object=aln1, window=5 save /tmp/super.aln, aln1 delete aln1 load_aln /tmp/super.aln, aln2, format=clustal ''' from . import one_letter from .seqalign import needle_alignment, alignment_mapping, aln_magic_read quiet = int(quiet) if object is None: object = os.path.basename(filename).rsplit('.', 1)[0] # load alignment file alignment = aln_magic_read(cmd.exp_path(filename), format) aln_dict = dict((record.id, record) for record in alignment) mobile_record = alignment[0] if mobile_id is None else aln_dict[mobile_id] target_record = alignment[1] if target_id is None else aln_dict[target_id] # guess selections from sequence identifiers (if not given) if mobile is None: mobile = mobile_record.id if target is None: target = target_record.id try: mobile_obj = cmd.get_object_list('(' + mobile + ')')[0] target_obj = cmd.get_object_list('(' + target + ')')[0] except: print ' Error: selection "%s" or "%s" does not exist' % (mobile, target) raise CmdException # get structure models and sequences mobile_model = cmd.get_model('(%s) and guide' % mobile) target_model = cmd.get_model('(%s) and guide' % target) mobile_sequence = ''.join(one_letter.get(a.resn, 'X') for a in mobile_model.atom) target_sequence = ''.join(one_letter.get(a.resn, 'X') for a in target_model.atom) # align sequences from file to structures mobile_aln = needle_alignment(str(mobile_record.seq), mobile_sequence) target_aln = needle_alignment(str(target_record.seq), target_sequence) # get index mappings mobile_aln_i2j = dict(alignment_mapping(*mobile_aln)) target_aln_i2j = dict(alignment_mapping(*target_aln)) record_i2j = alignment_mapping(mobile_record, target_record) # build alignment list r = [] for i, j, in record_i2j: if i in mobile_aln_i2j and j in target_aln_i2j: i = mobile_aln_i2j[i] j = target_aln_i2j[j] r.append({ mobile_obj: mobile_model.atom[i].index, target_obj: target_model.atom[j].index, }) set_raw_alignment(object, r, int(transform)) return r
def tmalign(mobile, target, args='', exe='TMalign', ter=0, transform=1, object=None, quiet=0): """ DESCRIPTION TMalign wrapper Reference: Y. Zhang and J. Skolnick, Nucl. Acids Res. 2005 33, 2302-9 http://zhanglab.ccmb.med.umich.edu/TM-align/ USAGE tmalign mobile, target [, args [, exe ]] ARGUMENTS mobile, target = string: atom selections args = string: Extra arguments like -d0 5 -L 100 exe = string: Path to TMalign executable {default: TMalign} ter = 0/1: If ter=0, then ignore chain breaks because TMalign will stop at first TER record {default: 0} SEE ALSO tmscore, mmalign """ import subprocess import tempfile import os import re ter, quiet = int(ter), int(quiet) mobile_filename = tempfile.mktemp('.pdb', 'mobile') target_filename = tempfile.mktemp('.pdb', 'target') matrix_filename = tempfile.mktemp('.txt', 'matrix') mobile_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % mobile target_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % target if ter: save = cmd.save else: save = save_pdb_without_ter save(mobile_filename, mobile_ca_sele) save(target_filename, target_ca_sele) exe = cmd.exp_path(exe) args = [exe, mobile_filename, target_filename, '-m', matrix_filename ] + args.split() try: process = subprocess.Popen(args, stdout=subprocess.PIPE) lines = process.stdout.readlines() except OSError: print('Cannot execute "%s", please provide full path to TMscore or ' 'TMalign executable' % exe) raise CmdException finally: os.remove(mobile_filename) os.remove(target_filename) # TMalign >= 2012/04/17 if os.path.exists(matrix_filename): lines += open(matrix_filename).readlines() os.remove(matrix_filename) r = None re_score = re.compile(r'TM-score\s*=\s*(\d*\.\d*)') rowcount = 0 matrix = [] line_it = iter(lines) alignment = [] for line in line_it: if 4 >= rowcount > 0: if rowcount >= 2: a = list(map(float, line.split())) matrix.extend(a[2:5]) matrix.append(a[1]) rowcount += 1 elif line.lower().startswith(' -------- rotation matrix'): rowcount = 1 elif line.startswith('(":" denotes'): alignment = [] for i in range(3): alignment.append(line_it.next().rstrip()) else: match = re_score.search(line) if match is not None: r = float(match.group(1)) if not quiet: print(line.rstrip()) if not quiet: for i in range(0, len(alignment[0]) - 1, 78): for line in alignment: print(line[i:i + 78]) print('') assert len(matrix) == 3 * 4 matrix.extend([0, 0, 0, 1]) if int(transform): cmd.transform_selection('byobject (%s)' % mobile, matrix, homogenous=1) # alignment object if object is not None: mobile_idx, target_idx = [], [] space = {'mobile_idx': mobile_idx, 'target_idx': target_idx} cmd.iterate(mobile_ca_sele, 'mobile_idx.append("%s`%d" % (model, index))', space=space) cmd.iterate(target_ca_sele, 'target_idx.append("%s`%d" % (model, index))', space=space) for i, aa in enumerate(alignment[0]): if aa == '-': mobile_idx.insert(i, None) for i, aa in enumerate(alignment[2]): if aa == '-': target_idx.insert(i, None) if len(mobile_idx) == len(target_idx) == len(alignment[2]): cmd.rms_cur(' '.join(idx for (idx, m) in zip(mobile_idx, alignment[1]) if m in ':.'), ' '.join(idx for (idx, m) in zip(target_idx, alignment[1]) if m in ':.'), matchmaker=4, object=object) else: print('Could not load alignment object') if not quiet and r is not None: print('Found in output TM-score = %.4f' % r) return r
} autoload = {} plugins = {} HAVE_QT = False # exception types class QtNotAvailableError(Exception): pass # plugins from PYMOL_DATA startup.__path__.append(cmd.exp_path('$PYMOL_DATA/startup')) N_NON_USER_PATHS = len(startup.__path__) # API functions def is_verbose(debug=0): verbose = pref_get('verbose') if debug and verbose < 0: return True return verbose and pymol.invocation.options.show_splash def get_startup_path(useronly=False): if useronly: # assume last item is always from installation directory return startup.__path__[:-N_NON_USER_PATHS] return startup.__path__
def poseview(ligand='organic inorganic', protein='polymer', width=0, height=0, filename='', exe='poseview', state=-1, quiet=1): ''' DESCRIPTION PoseView wrapper http://www.biosolveit.de/poseview/ USAGE poseview [ ligand [, protein [, width [, height [, exe [, state ]]]]]] ARGUMENTS ligand = string: atom selection {default: organic inorganic} protein = string: atom selection {default: polymer} width = int: image width {default: viewport width} height = int: image height {default: viewport height} filename = string: output PNG file name {default: temporary} exe = string: path to executable {default: poseview} SETUP 1) Put poseview executable to PATH (e.g. /usr/bin/poseview) 2) Set environment variable BIOSOLVE_LICENSE_FILE="/path/to/poseview.lic" ''' import tempfile import subprocess import os import shutil width, height = int(width), int(height) state, quiet = int(state), int(quiet) if width == 0 or height == 0: viewport = cmd.get_viewport() if width != 0: height = int(viewport[0] / float(width) * viewport[1]) elif height != 0: width = int(viewport[1] / float(height) * viewport[0]) else: width, height = viewport exe = cmd.exp_path(exe) tempdir = tempfile.mkdtemp() try: ligand_filename = os.path.join(tempdir, 'ligand.sdf') protein_filename = os.path.join(tempdir, 'protein.pdb') if not filename: filename = os.path.join(tempdir, 'image.png') cmd.save(ligand_filename, ligand, state) cmd.save(protein_filename, protein, state) args = [exe, '-l', ligand_filename, '-p', protein_filename, '-t', '', '-o', filename, '-s', str(width), str(height)] if not quiet: print(' poseview: running...') process = subprocess.Popen(args, universal_newlines=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) stdout, _ = process.communicate() if not quiet: print(stdout) print(' poseview: done') if filename.endswith('.png'): cmd.load(filename) elif not quiet: print(' Warning: cannot load "%s" into PyMOL, unsupported file type' % (filename)) except OSError: print(' Error: Cannot execute "%s", please provide full path to poseview executable' % (exe)) raise CmdException finally: shutil.rmtree(tempdir)
def load_aln_multi(filename, object=None, mapping='', alignioformat='', guide='', quiet=1, _self=cmd): ''' DESCRIPTION Load a multiple sequence alignment from file and apply it to already loaded structures. Requires Biopython (conda install biopython) USAGE load_aln_multi filename [, object [, mapping [, alignioformat [, guide ]]]] ARGUMENTS filename = str: alignment file object = str: name of the new alignment object {default: filename prefix} mapping = str: space separated list of sequence-id to object-name mappings {default: assume sequence-id = object-name} alignioformat = str: file format, see http://biopython.org/wiki/AlignIO {default: guess from first line in file} guide = str: object name of "guide" object (PyMOL only knows many-to-one alignment, not true multiple alignments) {default: random object} SEE ALSO psico.importing.load_aln ''' import os quiet = int(quiet) if object is None: object = os.path.basename(filename).rsplit('.', 1)[0] # load alignment file alignment = aln_magic_read(cmd.exp_path(filename), alignioformat) # object name mapping if isinstance(mapping, str): mapping = mapping.split() mapping = dict(zip(mapping[0::2], mapping[1::2])) i2index = [None] * len(alignment) onames = [None] * len(alignment) indices = [-1] * len(alignment) # get structure models and sequences for r, record in enumerate(alignment): oname = mapping.get(record.id, record.id) if not oname: continue atoms = [] n = _self.iterate('?{} & guide'.format(oname), 'atoms.append((oneletter or "?", index))', space=locals()) if n == 0: print(" Warning: no atoms for object '{}'".format(oname)) continue # align sequences from file to structures aln = needle_alignment(str(record.seq), ''.join(a[0] for a in atoms)) # get index mappings i2index[r] = dict((i, atoms[j][1]) for (i, j) in alignment_mapping(*aln)) onames[r] = oname if len(onames) < 2: raise CmdException('Failed to map alignment to objects') # build alignment list raw = [] for c in range(len(alignment[0])): rawcol = [] for r, aa in enumerate(alignment[:, c]): if onames[r] is None: continue if aa != '-': indices[r] += 1 index = i2index[r].get(indices[r], -1) if index >= 0: rawcol.append((onames[r], index)) if len(rawcol) > 1: raw.append(rawcol) _self.set_raw_alignment(object, raw, guide=guide) return raw
def tmalign(mobile, target, args='', exe='TMalign', ter=0, transform=1, object=None, quiet=0): ''' DESCRIPTION TMalign wrapper Reference: Y. Zhang and J. Skolnick, Nucl. Acids Res. 2005 33, 2302-9 http://zhanglab.ccmb.med.umich.edu/TM-align/ USAGE tmalign mobile, target [, args [, exe ]] ARGUMENTS mobile, target = string: atom selections args = string: Extra arguments like -d0 5 -L 100 exe = string: Path to TMalign executable {default: TMalign} ter = 0/1: If ter=0, then ignore chain breaks because TMalign will stop at first TER record {default: 0} SEE ALSO tmscore, mmalign ''' import subprocess, tempfile, os, re ter, quiet = int(ter), int(quiet) mobile_filename = tempfile.mktemp('.pdb', 'mobile') target_filename = tempfile.mktemp('.pdb', 'target') mobile_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (mobile) target_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (target) if ter: save = cmd.save else: save = save_pdb_without_ter save(mobile_filename, mobile_ca_sele) save(target_filename, target_ca_sele) exe = cmd.exp_path(exe) args = [exe, mobile_filename, target_filename] + args.split() try: process = subprocess.Popen(args, stdout=subprocess.PIPE) except OSError: print 'Cannot execute "%s", please provide full path to TMscore or TMalign executable' % (exe) raise CmdException r = None re_score = re.compile(r'TM-score\s*=\s*(\d*\.\d*)') rowcount = 0 matrix = [] line_it = iter(process.stdout) for line in line_it: if 4 >= rowcount > 0: if rowcount >= 2: a = map(float, line.split()) matrix.extend(a[2:5]) matrix.append(a[1]) rowcount += 1 elif line.lower().startswith(' -------- rotation matrix'): rowcount = 1 elif line.startswith('(":" denotes'): alignment = [line_it.next().rstrip() for i in range(3)] else: match = re_score.search(line) if match is not None: r = float(match.group(1)) if not quiet: print line.rstrip() if not quiet: for i in range(0, len(alignment[0])-1, 78): for line in alignment: print line[i:i+78] print '' assert len(matrix) == 3*4 matrix.extend([0,0,0,1]) if int(transform): cmd.transform_selection('byobject (%s)' % (mobile), matrix, homogenous=1) # alignment object if object is not None: mobile_idx, target_idx = [], [] space = {'mobile_idx': mobile_idx, 'target_idx': target_idx} cmd.iterate(mobile_ca_sele, 'mobile_idx.append("%s`%d" % (model, index))', space=space) cmd.iterate(target_ca_sele, 'target_idx.append("%s`%d" % (model, index))', space=space) for i, aa in enumerate(alignment[0]): if aa == '-': mobile_idx.insert(i, None) for i, aa in enumerate(alignment[2]): if aa == '-': target_idx.insert(i, None) if (len(mobile_idx) == len(target_idx) == len(alignment[2])): cmd.rms_cur( ' '.join(idx for (idx, m) in zip(mobile_idx, alignment[1]) if m in ':.'), ' '.join(idx for (idx, m) in zip(target_idx, alignment[1]) if m in ':.'), cycles=0, matchmaker=4, object=object) else: print 'Could not load alignment object' if not quiet and r is not None: print 'Found in output TM-score = %.4f' % (r) os.remove(mobile_filename) os.remove(target_filename) return r
def _normalmodes(selection, cutoff, force, mass, first, last, choose, substruct, blocksize, exe, diag_exe, prefix, states, factor, clean, quiet, wiz=None): import tempfile, subprocess, os, shutil, sys from chempy import cpv cutoff, force = float(cutoff), float(force) first, last, blocksize = int(first), int(last), int(blocksize) clean, quiet = int(clean), int(quiet) exe = cmd.exp_path(exe) diag_exe = cmd.exp_path(diag_exe) tempdir = tempfile.mkdtemp() if not quiet: print(' normalmodes: Temporary directory is', tempdir) try: sele_name = cmd.get_unused_name('__pdbmat') except AttributeError: sele_name = '__pdbmat' try: filename = os.path.join(tempdir, 'mobile.pdb') commandfile = os.path.join(tempdir, 'pdbmat.dat') cmd.select(sele_name, '(%s) and not hetatm' % (selection)) cmd.save(filename, sele_name) f = open(commandfile, 'w') f.write('''! pdbmat file Coordinate FILENAME = %s MATRIx FILENAME = matrix.sdijb INTERACtion DISTance CUTOF = %.3f INTERACtion FORCE CONStant = %.3f Origin of MASS values = %s Output PRINTing level = 0 MATRix FORMat = BINA ''' % (filename, cutoff, force, mass.upper())) f.close() if not quiet: print(' normalmodes: running', exe, '...') if wiz is not None: wiz.message[1] = 'running pdbmat' cmd.refresh_wizard() process = subprocess.Popen([exe], cwd=tempdir, universal_newlines=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) for line in process.stdout: if not quiet: sys.stdout.write(line) try: natoms = len( open(os.path.join(tempdir, 'pdbmat.xyzm')).readlines()) except Exception as e: print(e) natoms = cmd.count_atoms(sele_name) if natoms != cmd.count_atoms(sele_name): print('Error: pdbmat did not recognize all atoms') raise CmdException commandfile = os.path.join(tempdir, 'diagrtb.dat') f = open(commandfile, 'w') f.write('''! diagrtb file MATRIx FILENAME = matrix.sdijb COORdinates filename = %s Eigenvector OUTPut filename= diagrtb.eigenfacs Nb of VECTors required = %d EigeNVALues chosen = %s Type of SUBStructuring = %s Nb of residues per BLOck = %d Origin of MASS values = %s Temporary files cleaning = ALL MATRix FORMat = BINA Output PRINting level = 0 ''' % (filename, last, choose.upper(), substruct.upper(), blocksize, mass.upper())) f.close() exe = diag_exe if not quiet: print(' normalmodes: running', exe, '...') if wiz is not None: wiz.message[1] = 'running diagrtb' cmd.refresh_wizard() process = subprocess.Popen([exe], cwd=tempdir, universal_newlines=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) for line in process.stdout: if not quiet: sys.stdout.write(line) eigenfacs, frequencies = parse_eigenfacs( os.path.join(tempdir, 'diagrtb.eigenfacs'), last) if wiz is not None: wiz.message[1] = 'generating objects' cmd.refresh_wizard() states = int(states) factor = float(factor) if factor < 0: factor = natoms**0.5 for mode in range(first, last + 1): name = prefix + '%d' % mode cmd.delete(name) if not quiet: print(' normalmodes: object "%s" for mode %d with freq. %.6f' % \ (name, mode, frequencies[mode-1])) for state in range(1, states + 1): cmd.create(name, sele_name, 1, state, zoom=0) cmd.alter_state( state, name, '(x,y,z) = cpv.add([x,y,z], cpv.scale(next(myit), myfac))', space={ 'cpv': cpv, 'myit': iter(eigenfacs[mode - 1]), 'next': next, 'myfac': factor * (state - (states + 1) / 2.0) }) # if CA only selection, show ribbon trace if natoms == cmd.count_atoms('(%s) and name CA' % sele_name): cmd.set('ribbon_trace_atoms', 1, prefix + '*') cmd.show_as('ribbon', prefix + '*') # store results if not hasattr(stored, 'nma_results'): stored.nma_results = [] stored.nma_results.append({ 'facs': eigenfacs, 'freq': frequencies, 'sele': sele_name, }) except OSError: print('Cannot execute "%s", please provide full path to executable' % (exe)) except CmdException as e: print(' normalmodes: failed!', e) finally: if clean: shutil.rmtree(tempdir) elif not quiet: print(' normalmodes: Working directory "%s" not removed!' % (tempdir)) # cmd.delete(sele_name) if wiz is not None: cmd.set_wizard_stack( [w for w in cmd.get_wizard_stack() if w != wiz])
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() infile = os.path.join(tmpdir, 'in.pdb') 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 _normalmodes(selection, cutoff, force, mass, first, last, choose, substruct, blocksize, exe, diag_exe, prefix, states, factor, clean, quiet, wiz=None): import tempfile, subprocess, os, shutil, sys from chempy import cpv cutoff, force = float(cutoff), float(force) first, last, blocksize = int(first), int(last), int(blocksize) clean, quiet = int(clean), int(quiet) exe = cmd.exp_path(exe) diag_exe = cmd.exp_path(diag_exe) tempdir = tempfile.mkdtemp() if not quiet: print ' normalmodes: Temporary directory is', tempdir try: sele_name = cmd.get_unused_name('__pdbmat') except AttributeError: sele_name = '__pdbmat' try: filename = os.path.join(tempdir, 'mobile.pdb') commandfile = os.path.join(tempdir, 'pdbmat.dat') cmd.select(sele_name, '(%s) and not hetatm' % (selection)) cmd.save(filename, sele_name) f = open(commandfile, 'w') f.write('''! pdbmat file Coordinate FILENAME = %s MATRIx FILENAME = matrix.sdijb INTERACtion DISTance CUTOF = %.3f INTERACtion FORCE CONStant = %.3f Origin of MASS values = %s Output PRINTing level = 0 MATRix FORMat = BINA ''' % (filename, cutoff, force, mass.upper())) f.close() if not quiet: print ' normalmodes: running', exe, '...' if wiz is not None: wiz.message[1] = 'running pdbmat' cmd.refresh_wizard() process = subprocess.Popen([exe], cwd=tempdir, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) for line in process.stdout: if not quiet: sys.stdout.write(line) natoms = len(open(os.path.join(tempdir, 'pdbmat.xyzm')).readlines()) if natoms != cmd.count_atoms(sele_name): print 'Error: pdbmat did not recognize all atoms' raise CmdException commandfile = os.path.join(tempdir, 'diagrtb.dat') f = open(commandfile, 'w') f.write('''! diagrtb file MATRIx FILENAME = matrix.sdijb COORdinates filename = pdbmat.xyzm Eigenvector OUTPut filename= diagrtb.eigenfacs Nb of VECTors required = %d EigeNVALues chosen = %s Type of SUBStructuring = %s Nb of residues per BLOck = %d Origin of MASS values = %s Temporary files cleaning = ALL MATRix FORMat = BINA Output PRINting level = 0 ''' % (last, choose.upper(), substruct.upper(), blocksize, mass.upper())) f.close() exe = diag_exe if not quiet: print ' normalmodes: running', exe, '...' if wiz is not None: wiz.message[1] = 'running diagrtb' cmd.refresh_wizard() process = subprocess.Popen([exe], cwd=tempdir, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) for line in process.stdout: if not quiet: sys.stdout.write(line) eigenfacs, frequencies = parse_eigenfacs( os.path.join(tempdir, 'diagrtb.eigenfacs'), last) if wiz is not None: wiz.message[1] = 'generating objects' cmd.refresh_wizard() states = int(states) factor = float(factor) if factor < 0: factor = natoms**0.5 for mode in range(first, last+1): name = prefix + '%d' % mode cmd.delete(name) if not quiet: print ' normalmodes: object "%s" for mode %d with freq. %.6f' % \ (name, mode, frequencies[mode-1]) for state in range(1, states+1): cmd.create(name, sele_name, 1, state, zoom=0) cmd.alter_state(state, name, '(x,y,z) = cpv.add([x,y,z], cpv.scale(myit.next(), myfac))', space={'cpv': cpv, 'myit': iter(eigenfacs[mode-1]), 'myfac': factor * (state - (states+1)/2.0)}) # if CA only selection, show ribbon trace if natoms == cmd.count_atoms('(%s) and name CA' % sele_name): cmd.set('ribbon_trace_atoms', 1, prefix + '*') cmd.show_as('ribbon', prefix + '*') # store results if not hasattr(stored, 'nma_results'): stored.nma_results = [] stored.nma_results.append({ 'facs': eigenfacs, 'freq': frequencies, 'sele': sele_name, }) except OSError: print 'Cannot execute "%s", please provide full path to executable' % (exe) except CmdException, e: print ' normalmodes: failed!', e
def save_pdb(filename, selection='(all)', state=-1, symm=1, ss=1, aniso=0, seqres=0, quiet=1): ''' DESCRIPTION Save the coordinates of a selection as pdb including the secondary structure information and, if possible, the unit cell. The latter requires the selction of a single object USAGE save_pdb filename, selection [, state [, symm [, ss [, aniso ]]]] ARGUMENTS filename = string: file path to be written selection = string: atoms to save {default: (all)} Note: to include the unit cell information you need to select a single object state = integer: state to save {default: -1 (current state)} symm = 0 or 1: save symmetry info if possible {default: 1} ss = 0 or 1: save secondary structure info {default: 1} aniso = 0 or 1: save ANISO records {default: 0} SEE ALSO save ''' selection = selector.process(selection) state, quiet = int(state), int(quiet) symm, ss = int(symm), int(ss) filename = cmd.exp_path(filename) f = open(filename, 'w') print('REMARK 200 Generated with PyMOL and psico'.ljust(80), file=f) # Write sequence if int(seqres): f.write(get_pdb_seqres(selection)) # Write the CRYST1 line if possible if symm: try: obj1 = cmd.get_object_list(selection)[0] sym = cmd.get_symmetry(obj1) if len(sym) != 7: raise f.write("CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-10s%4d\n" % tuple(sym + [1])) if not quiet: print(' Info: Wrote unit cell and space group info') except: if not quiet: print(' Info: No crystal information') # Write secondary structure if ss: try: sss = get_pdb_sss(selection, state, quiet) if not sss: raise f.write(sss) if not quiet: print(' Info: Wrote secondary structure info') except: if not quiet: print(' Info: No secondary structure information') # Write coordinates of selection pdbstr = cmd.get_pdbstr(selection, state) # fix END records if state == 0 and cmd.get_version()[1] < 1.6: pdbstr = '\n'.join( line for line in pdbstr.splitlines() if line != 'END') + '\nEND\n' # anisotropic b-factors from . import pymol_version if int(aniso) and pymol_version < 1.6 and \ cmd.get_model('first (%s)' % selection).atom[0].u_aniso[0] != 0.0: def mergeaniso(): atom_it = iter(cmd.get_model(selection, state).atom) for line in pdbstr.splitlines(True): yield line if line[:6] in ['ATOM ', 'HETATM']: yield 'ANISOU' + line[6:28] + \ ''.join('%7.0f' % (u*1e4) for u in atom_it.next().u_aniso) + \ line[70:] pdbstr = ''.join(mergeaniso()) f.write(pdbstr) f.close() if not quiet: print('Wrote PDB to \'' + filename + '\'')
def fiber(seq, num=4, name='', rna=0, single=0, repeats=0, preserve=0, exe='$X3DNA/bin/fiber', quiet=1, *, _self=cmd): ''' DESCRIPTION Run X3DNA's "fiber" tool. For the list of structure identification numbers, see for example: http://xiang-jun.blogspot.com/2009/10/fiber-models-in-3dna.html USAGE fiber seq [, num [, name [, rna [, single ]]]] ARGUMENTS seq = str: single letter code sequence or number of repeats for repeat models. num = int: structure identification number {default: 4} name = str: name of object to create {default: random unused name} rna = 0/1: 0=DNA, 1=RNA {default: 0} single = 0/1: 0=double stranded, 1=single stranded {default: 0} EXAMPLES # environment (this could go into ~/.pymolrc or ~/.bashrc) os.environ["X3DNA"] = "/opt/x3dna-v2.3" # B or A DNA from sequence fiber CTAGCG fiber CTAGCG, 1, ADNA # double or single stranded RNA from sequence fiber AAAGGU, name=dsRNA, rna=1 fiber AAAGGU, name=ssRNA, rna=1, single=1 # poly-GC Z-DNA repeat model with 10 repeats fiber 10, 15 ''' import os, tempfile, subprocess, shutil rna, single = int(rna), int(single) preserve, quiet = int(preserve), int(quiet) if 'X3DNA' not in os.environ: raise CmdException('please set X3DNA environment variable') args = [cmd.exp_path(exe), '-seq=' + seq, '-' + str(num)] if rna: args.append('-rna') if single: args.append('-single') if not name: name = _self.get_unused_name('fiber-' + str(num) + '_') tmpdir = tempfile.mkdtemp() outfile = os.path.join(tmpdir, 'out.pdb') args.append(outfile) if seq.endswith('help'): # call fiber with no arguments to get help page args[1:] = [] try: p = subprocess.Popen(args, cwd=tmpdir, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, _ = p.communicate(str(int(repeats) or seq)) if not quiet: print(stdout) if len(args) != 1: if p.returncode != 0: raise CmdException('Returned non-zero status: ' + str(args)) _self.load(outfile, name, quiet=quiet) except OSError: raise CmdException('Cannot execute "%s"' % (exe)) finally: if not preserve: shutil.rmtree(tmpdir) elif not quiet: print(' Notice: not deleting', tmpdir)
def prepwizard(name, selection='all', options='', state=-1, preserve=0, exe='$SCHRODINGER/utilities/prepwizard', quiet=1, *, _self=cmd): ''' 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 os.path.exists(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 isinstance(options, (str, bytes)): options = shlex.split(options) args.extend(options) tmpdir = tempfile.mkdtemp() infile = 'in.pdb' outfile = 'out.mae' args.extend([infile, outfile]) try: _self.save(os.path.join(tmpdir, infile), selection, state) p = subprocess.Popen(args, cwd=tmpdir, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) print(p.communicate()[0].rstrip()) if p.returncode != 0: logfile = os.path.join(tmpdir, 'in.log') if os.path.exists(logfile): with open(logfile) as handle: print(handle.read()) raise CmdException('%s failed with exit status %d' % (args[0], p.returncode)) _self.load(os.path.join(tmpdir, outfile), name) except OSError: raise CmdException('Cannot execute "%s"' % (exe)) finally: if not preserve: shutil.rmtree(tmpdir) elif not quiet: print(' Notice: not deleting', tmpdir) if not quiet: print(' prepwizard: done')
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='pdb2pqr30', quiet=1, *, keep_chain=1, _self=cmd): ''' 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} ''' import os, tempfile, subprocess, shutil debump, opt, assignonly = int(debump), int(opt), int(assignonly) neutraln, neutralc = int(neutraln), int(neutralc) state, preserve, quiet = int(state), int(preserve), int(quiet) args = [cmd.exp_path(exe), '--ff=' + ff] if int(keep_chain): args.append('--keep-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') tmpdir = tempfile.mkdtemp() infile = os.path.join(tmpdir, 'in.pdb') outfile = os.path.join(tmpdir, 'out.pqr') args.extend([infile, outfile]) try: _self.save(infile, selection, state) p = subprocess.Popen(args, cwd=tmpdir, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) print(p.communicate()[0].rstrip()) if p.returncode != 0: raise CmdException('%s failed with exit status %d' % (args[0], p.returncode)) remark5 = [L for L in open(outfile) if L.startswith('REMARK 5')] if remark5: print(''.join(remark5)) _self.load(outfile, name) except OSError: raise CmdException('Cannot execute "%s"' % (exe)) finally: if not preserve: shutil.rmtree(tmpdir) elif not quiet: print(' Notice: not deleting', tmpdir) if not quiet: print(' pdb2pqr: done')
def tmalign(mobile, target, mobile_state=1, target_state=1, args='', exe='TMalign', ter=0, transform=1, object=None, quiet=0): ''' DESCRIPTION TMalign wrapper. You may also use this as a TMscore or MMalign wrapper if you privide the corresponding executable with the "exe" argument. Reference: Y. Zhang and J. Skolnick, Nucl. Acids Res. 2005 33, 2302-9 http://zhanglab.ccmb.med.umich.edu/TM-align/ ARGUMENTS mobile, target = string: atom selections mobile_state, target_state = int: object states {default: 1} args = string: Extra arguments like -d0 5 -L 100 exe = string: Path to TMalign (or TMscore, MMalign) executable {default: TMalign} ter = 0/1: If ter=0, then ignore chain breaks because TMalign will stop at first TER record {default: 0} ''' import subprocess, tempfile, os, re from .exporting import save_pdb_without_ter ter, quiet = int(ter), int(quiet) mobile_filename = tempfile.mktemp('.pdb', 'mobile') target_filename = tempfile.mktemp('.pdb', 'target') matrix_filename = tempfile.mktemp('.txt', 'matrix') mobile_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (mobile) target_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (target) if ter: save = cmd.save else: save = save_pdb_without_ter save(mobile_filename, mobile_ca_sele, state=mobile_state) save(target_filename, target_ca_sele, state=target_state) exe = cmd.exp_path(exe) args = [exe, mobile_filename, target_filename, '-m', matrix_filename] + args.split() try: process = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True) lines = process.stdout.readlines() except OSError: print('Cannot execute "%s", please provide full path to TMscore or TMalign executable' % (exe)) raise CmdException finally: os.remove(mobile_filename) os.remove(target_filename) # TMalign >= 2012/04/17 if os.path.exists(matrix_filename): lines += open(matrix_filename).readlines() os.remove(matrix_filename) r = None re_score = re.compile(r'TM-score\s*=\s*(\d*\.\d*)') rowcount = 0 matrix = [] line_it = iter(lines) headercheck = False alignment = [] for line in line_it: if 4 >= rowcount > 0: if rowcount >= 2: a = list(map(float, line.split())) matrix.extend(a[2:5]) matrix.append(a[1]) rowcount += 1 elif not headercheck and line.startswith(' * '): a = line.split(None, 2) if len(a) == 3: headercheck = a[1] elif line.lower().startswith(' -------- rotation matrix'): rowcount = 1 elif line.startswith('(":" denotes'): alignment = [next(line_it).rstrip() for i in range(3)] else: match = re_score.search(line) if match is not None: r = float(match.group(1)) if not quiet: print(line.rstrip()) if not quiet: for i in range(0, len(alignment[0])-1, 78): for line in alignment: print(line[i:i+78]) print('') assert len(matrix) == 3*4 matrix.extend([0,0,0,1]) if int(transform): for model in cmd.get_object_list('(' + mobile + ')'): cmd.transform_object(model, matrix, state=0, homogenous=1) # alignment object if object is not None: mobile_idx, target_idx = [], [] space = {'mobile_idx': mobile_idx, 'target_idx': target_idx} cmd.iterate_state(mobile_state, mobile_ca_sele, 'mobile_idx.append("%s`%d" % (model, index))', space=space) cmd.iterate_state(target_state, target_ca_sele, 'target_idx.append("%s`%d" % (model, index))', space=space) for i, aa in enumerate(alignment[0]): if aa == '-': mobile_idx.insert(i, None) for i, aa in enumerate(alignment[2]): if aa == '-': target_idx.insert(i, None) if (len(mobile_idx) == len(target_idx) == len(alignment[2])): cmd.rms_cur( ' '.join(idx for (idx, m) in zip(mobile_idx, alignment[1]) if m in ':.'), ' '.join(idx for (idx, m) in zip(target_idx, alignment[1]) if m in ':.'), cycles=0, matchmaker=4, object=object) else: print('Could not load alignment object') if not quiet: if headercheck: print('Finished Program:', headercheck) if r is not None: print('Found in output TM-score = %.4f' % (r)) return r
def tmalign(mobile, target, mobile_state=1, target_state=1, args='', exe='TMalign', ter=0, transform=1, object=None, quiet=0, *, _self=cmd): ''' DESCRIPTION TMalign wrapper. You may also use this as a TMscore or MMalign wrapper if you privide the corresponding executable with the "exe" argument. Reference: Y. Zhang and J. Skolnick, Nucl. Acids Res. 2005 33, 2302-9 http://zhanglab.ccmb.med.umich.edu/TM-align/ ARGUMENTS mobile, target = string: atom selections mobile_state, target_state = int: object states {default: 1} args = string: Extra arguments like -d0 5 -L 100 exe = string: Path to TMalign (or TMscore, MMalign) executable {default: TMalign} ter = 0/1: If ter=0, then ignore chain breaks because TMalign will stop at first TER record {default: 0} ''' import pymol.exporting import subprocess, tempfile, os, re from .exporting import save_pdb_without_ter ter, quiet = int(ter), int(quiet) mobile_filename = tempfile.mktemp('.pdb', 'mobile') target_filename = tempfile.mktemp('.pdb', 'target') matrix_filename = tempfile.mktemp('.txt', 'matrix') mobile_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (mobile) target_ca_sele = '(%s) and (not hetatm) and name CA and alt +A' % (target) if ter: save = pymol.exporting.save else: save = save_pdb_without_ter save(mobile_filename, mobile_ca_sele, state=mobile_state, _self=_self) save(target_filename, target_ca_sele, state=target_state, _self=_self) exe = cmd.exp_path(exe) args = [exe, mobile_filename, target_filename, '-m', matrix_filename] + args.split() try: process = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True) lines = process.stdout.readlines() except OSError: raise CmdException('Cannot execute "%s", please provide full path to TMscore or TMalign executable' % (exe)) finally: os.remove(mobile_filename) os.remove(target_filename) # TMalign >= 2012/04/17 if os.path.exists(matrix_filename): lines += open(matrix_filename).readlines() os.remove(matrix_filename) r = None re_score = re.compile(r'TM-score\s*=\s*(\d*\.\d*)') rowcount = 0 matrix = [] line_it = iter(lines) headercheck = False alignment = [] for line in line_it: if 4 >= rowcount > 0: if rowcount >= 2: a = list(map(float, line.split())) matrix.extend(a[2:5]) matrix.append(a[1]) rowcount += 1 elif not headercheck and line.startswith(' * '): a = line.split(None, 2) if len(a) == 3: headercheck = a[1] elif line.lower().startswith(' -------- rotation matrix'): rowcount = 1 elif line.startswith('(":" denotes'): alignment = [next(line_it).rstrip() for i in range(3)] else: match = re_score.search(line) if match is not None: r = float(match.group(1)) if not quiet: print(line.rstrip()) if not quiet: for i in range(0, len(alignment[0])-1, 78): for line in alignment: print(line[i:i+78]) print('') assert len(matrix) == 3*4 matrix.extend([0,0,0,1]) if int(transform): for model in _self.get_object_list(mobile): _self.transform_object(model, matrix, state=0, homogenous=1) # alignment object if object is not None: mobile_idx, target_idx = [], [] space = {'mobile_idx': mobile_idx, 'target_idx': target_idx} _self.iterate_state(mobile_state, mobile_ca_sele, 'mobile_idx.append("%s`%d" % (model, index))', space=space) _self.iterate_state(target_state, target_ca_sele, 'target_idx.append("%s`%d" % (model, index))', space=space) for i, aa in enumerate(alignment[0]): if aa == '-': mobile_idx.insert(i, None) for i, aa in enumerate(alignment[2]): if aa == '-': target_idx.insert(i, None) if (len(mobile_idx) == len(target_idx) == len(alignment[2])): _self.rms_cur( ' '.join(idx for (idx, m) in zip(mobile_idx, alignment[1]) if m in ':.'), ' '.join(idx for (idx, m) in zip(target_idx, alignment[1]) if m in ':.'), cycles=0, matchmaker=4, object=object) else: print('Could not load alignment object') if not quiet: if headercheck: print('Finished Program:', headercheck) if r is not None: print('Found in output TM-score = %.4f' % (r)) return r
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} ''' import os, tempfile, subprocess, shutil debump, opt, assignonly = int(debump), int(opt), int(assignonly) neutraln, neutralc = int(neutraln), int(neutralc) state, preserve, quiet = int(state), int(preserve), int(quiet) args = [cmd.exp_path(exe), '--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') tmpdir = tempfile.mkdtemp() infile = os.path.join(tmpdir, 'in.pdb') outfile = os.path.join(tmpdir, 'out.pqr') args.extend([infile, outfile]) try: cmd.save(infile, selection, state) subprocess.check_call(args, cwd=tmpdir) cmd.load(outfile, name) except OSError: print(' Error: Cannot execute "%s"' % (exe)) raise CmdException except subprocess.CalledProcessError as e: print(' Error: %s failed with exit status %d' % (args[0], e.returncode)) raise CmdException finally: if not preserve: shutil.rmtree(tmpdir) elif not quiet: print(' Notice: not deleting', tmpdir) if not quiet: print(' pdb2pqr: done')
def dss_promotif(selection='all', exe='', raw='', state=-1, quiet=1): ''' DESCRIPTION Secondary structure assignment with PROMOTIF. http://www.rubic.rdg.ac.uk/~gail/#Software SEE ALSO dss, dssp, stride ''' from subprocess import Popen, PIPE import tempfile, os, shutil state, quiet = int(state), int(quiet) ss_map = { 'B': 'S', 'E': 'S', 'H': 'H', 'G': 'H', } exe = cmd.exp_path(exe) if not exe: _assert_package_import() from . import which motifdir = os.environ.get('motifdir') exe = which('p_sstruc3', 'p_sstruc2', 'promotif.scr', path=[motifdir] if motifdir else None) tmpdir = tempfile.mkdtemp() tmpfilepdb = os.path.join(tmpdir, 'xxxx.pdb') tmpfilesst = os.path.join(tmpdir, 'xxxx.sst') ss_dict = dict() try: for model in cmd.get_object_list('(' + selection + ')'): cmd.save(tmpfilepdb, 'model %s and (%s)' % (model, selection), state) process = Popen([exe, tmpfilepdb], cwd=tmpdir, stdin=PIPE) process.communicate(tmpfilepdb + os.linesep) with open(tmpfilesst) as handle: for line in handle: if line.startswith(' num seq.no'): break for line in handle: if not line.strip(): break chain = line[6].strip('-') resi = line[7:12].strip() ss = line[23] ss_dict[model, chain, resi] = ss os.remove(tmpfilesst) except OSError: print(' Error: Cannot execute exe=' + exe) raise CmdException finally: shutil.rmtree(tmpdir) _common_ss_alter(selection, ss_dict, ss_map, raw)
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 p = subprocess.Popen( args, cwd=tmpdir, env=env, 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: logfile = os.path.join(tmpdir, 'in.log') if os.path.exists(logfile): with open(logfile) as handle: print(handle.read()) 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: if not preserve: shutil.rmtree(tmpdir) elif not quiet: print(' Notice: not deleting', tmpdir) if not quiet: print(' prepwizard: done')
def map_new_apbs(name, selection='all', grid=0.5, buffer=10.0, state=1, preserve=0, exe='apbs', assign=-1, quiet=1): ''' DESCRIPTION Create electrostatic potential map with APBS. For more control over parameters and a graphical user interface I recommend to use the APBS Tools Plugin instead. In case of missing atoms or residues I recommend to remodel the input structure with modeller before calculating the electrostatic potential. If selection has no charges and radii, they will be automatically assigned with PyMOL (not with pdb2pqr). SEE ALSO apbs_surface, map_new (coulomb), APBS Tools Plugin ''' import tempfile, os, shutil, glob, subprocess from pymol.util import protein_assign_charges_and_radii from .modelling import add_missing_atoms selection = '(%s) and not solvent' % (selection) grid, buffer, state = float(grid), float(buffer), int(state) preserve, assign, quiet = int(preserve), int(assign), int(quiet) exe = cmd.exp_path(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 object tmpname = cmd.get_unused_name('mol' if preserve else '_') cmd.create(tmpname, selection, state, 1) # partial charges assign = [assign] if assign[0] == -1: # auto detect if selection has charges and radii cmd.iterate('first ((%s) and elem O)' % (tmpname), 'assign[0] = (elec_radius * partial_charge) == 0.0', space=locals()) if assign[0]: cmd.remove('hydro and model ' + tmpname) add_missing_atoms(tmpname, quiet=quiet) protein_assign_charges_and_radii(tmpname) elif not quiet: print ' Notice: using exsiting charges and radii' cmd.save(pqrfile, tmpname, 1, format='pqr', quiet=quiet) # grid dimensions extent = cmd.get_extent(tmpname) fglen = [(emax-emin + 2*buffer) for (emin, emax) in zip(*extent)] cglen = [(emax-emin + 4*buffer) for (emin, emax) in zip(*extent)] if not preserve: cmd.delete(tmpname) apbs_in = defaults_apbs_in.copy() apbs_in['fglen'] = '%f %f %f' % tuple(fglen) apbs_in['cglen'] = '%f %f %f' % tuple(cglen) apbs_in['srad'] = cmd.get('solvent_radius') apbs_in['write'] = 'pot dx "%s"' % (stem) # apbs input file def write_input_file(): f = open(infile, 'w') print >> f, ''' read mol pqr "%s" end elec mg-auto ''' % (pqrfile) for (k,v) in apbs_in.items(): if v is None: print >> f, k elif isinstance(v, list): for vi in v: print >> f, k, vi else: print >> f, k, v print >> f, ''' end quit ''' f.close() 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) write_input_file() # run apbs r = subprocess.call([exe, infile], cwd=tempdir) if r == 0: break if r == -6: grid *= 2.0 if not quiet: print ' Warning: retry with grid =', grid continue print ' Error: apbs failed with code', r raise CmdException dx_list = glob.glob(stem + '*.dx') if len(dx_list) != 1: print ' Error: dx file missing' raise CmdException # load map cmd.load(dx_list[0], name, quiet=quiet) except OSError: print ' Error: Cannot execute "%s"' % (exe) raise CmdException finally: if not preserve: shutil.rmtree(tempdir) elif not quiet: print ' Notice: not deleting %s' % (tempdir)
def save_pdb(filename, selection="(all)", state=-1, symm=1, ss=1, aniso=0, quiet=1): """ DESCRIPTION Save the coordinates of a selection as pdb including the secondary structure information and, if possible, the unit cell. The latter requires the selction of a single object USAGE save_pdb filename, selection [, state [, symm [, ss [, aniso ]]]] ARGUMENTS filename = string: file path to be written selection = string: atoms to save {default: (all)} Note: to include the unit cell information you need to select a single object state = integer: state to save {default: -1 (current state)} symm = 0 or 1: save symmetry info if possible {default: 1} ss = 0 or 1: save secondary structure info {default: 1} aniso = 0 or 1: save ANISO records {default: 0} SEE ALSO save """ selection = selector.process(selection) state, quiet = int(state), int(quiet) symm, ss = int(symm), int(ss) filename = cmd.exp_path(filename) f = open(filename, "w") print >> f, "REMARK 200 Generated with PyMOL and psico".ljust(80) # Write the CRYST1 line if possible if symm: try: obj1 = cmd.get_object_list(selection)[0] sym = cmd.get_symmetry(obj1) if len(sym) != 7: raise f.write("CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-10s%4d\n" % tuple(sym + [1])) if not quiet: print " Info: Wrote unit cell and space group info" except: if not quiet: print " Info: No crystal information" # Write secondary structure if ss: try: sss = get_pdb_sss(selection, state, quiet) if not sss: raise f.write(sss) if not quiet: print " Info: Wrote secondary structure info" except: if not quiet: print " Info: No secondary structure information" # Write coordinates of selection pdbstr = cmd.get_pdbstr(selection, state) # fix END records if state == 0 and cmd.get_version()[1] < 1.6: pdbstr = "\n".join(line for line in pdbstr.splitlines() if line != "END") + "\nEND\n" # anisotropic b-factors if int(aniso) and cmd.get_model("first (%s)" % selection).atom[0].u_aniso[0] != 0.0: def mergeaniso(): atom_it = iter(cmd.get_model(selection, state).atom) for line in pdbstr.splitlines(True): yield line if line[:6] in ["ATOM ", "HETATM"]: yield "ANISOU" + line[6:28] + "".join("%7.0f" % (u * 1e4) for u in atom_it.next().u_aniso) + line[ 70: ] pdbstr = "".join(mergeaniso()) f.write(pdbstr) f.close() if not quiet: print "Wrote PDB to '" + filename + "'"
def diagnostics(filename='', compact=0, quiet=1): ''' DESCRIPTION Get system level diagnostics data USAGE diagnostics [ filename ] ARGUMENTS filename = str: If given, write output to text file ''' import time from pymol import invocation from pymol import cmd, CmdException compact, quiet = int(compact), int(quiet) TZ = '%+05d' % (time.timezone / 36) version = cmd.get_version() body = u'PyMOL %s\n' % version[0] if not compact: if version[3]: body += 'build date: %s %s\n' % (time.ctime(version[3]), TZ) if version[4]: body += 'git sha: %s\n' % version[4] body += diagnostics_conda(version[0]) if not compact: body += '\nLicense Information:\n' body += 'Open-Source Build\n' body += diagnostics_platform() if not compact: body += '\nOpenGL Driver:\n' renderer = cmd.get_renderer() body += str(renderer[0] or '(none)') + '\n' body += str(renderer[1] or '(none)') + '\n' body += str(renderer[2] or '(none)') + '\n' body += diagnostics_qt() if not compact: body += diagnostics_python() body += '\nStartup Scripts:\n' pymolrc = invocation.get_user_config() if pymolrc: pymolrc = map(_unicode, pymolrc) body += '\n'.join(pymolrc) + '\n' else: body += '(no pymolrc file found)\n' body += diagnostics_env_vars() body += '\nDiagnostics collected on %s %s\n' % (time.ctime(), TZ) if filename: filename = cmd.exp_path(filename) if not filename.endswith('.txt'): raise CmdException('filename must have .txt extension') with open(filename, 'w') as handle: handle.write(body) print('Diagnostics written to "%s"' % filename) elif not quiet: print(body.rstrip()) return body
def dyndom(mobile, target, window=5, domain=20, ratio=1.0, exe='', transform=1, quiet=1, mobile_state=1, target_state=1, match='align', preserve=0, *, _self=cmd): ''' DESCRIPTION DynDom wrapper DynDom is a program to determine domains, hinge axes and hinge bending residues in proteins where two conformations are available. http://fizz.cmp.uea.ac.uk/dyndom/ USAGE dyndom mobile, target [, window [, domain [, ratio ]]] ''' import tempfile, subprocess, os, shutil, sys from .exporting import save_pdb_without_ter window, domain, ratio = int(window), int(domain), float(ratio) transform, quiet = int(transform), int(quiet) mobile_state, target_state = int(mobile_state), int(target_state) mm = MatchMaker( '(%s) & polymer & state %d' % (mobile, mobile_state), '(%s) & polymer & state %d' % (target, target_state), match, _self=_self) chains = _self.get_chains(mm.mobile) if len(chains) != 1: raise CmdException('mobile selection must be single chain') chain1id = chains[0] chains = _self.get_chains(mm.target) if len(chains) != 1: raise CmdException('target selection must be single chain') chain2id = chains[0] if not exe: from . import which exe = which('DynDom', 'dyndom') if not exe: raise CmdException('Cannot find DynDom executable') else: exe = cmd.exp_path(exe) tempdir = tempfile.mkdtemp() try: filename1 = os.path.join(tempdir, 'mobile.pdb') filename2 = os.path.join(tempdir, 'target.pdb') commandfile = os.path.join(tempdir, 'command.txt') infofile = os.path.join(tempdir, 'out_info') save_pdb_without_ter(filename1, mm.mobile, state=mobile_state, _self=_self) save_pdb_without_ter(filename2, mm.target, state=target_state, _self=_self) f = open(commandfile, 'w') f.write('title=out\nfilename1=%s\nchain1id=%s\nfilename2=%s\nchain2id=%s\n' \ 'window=%d\ndomain=%d\nratio=%.4f\n' % (filename1, chain1id, filename2, chain2id, window, domain, ratio)) f.close() process = subprocess.Popen([exe, commandfile], cwd=tempdir, universal_newlines=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) for line in process.stdout: if not quiet: sys.stdout.write(line) if process.poll() != 0: raise CmdException('"%s" failed with status %d' % (exe, process.returncode)) _self.color('gray', mobile) fixed_name = dyndom_parse_info(infofile, mm.mobile, quiet) except OSError: raise CmdException('Cannot execute "%s", please provide full path to DynDom executable' % (exe)) finally: if not int(preserve): shutil.rmtree(tempdir) elif not quiet: print(' Not deleting temporary directory:', tempdir) if transform and fixed_name is not None: _self.align(fixed_name, target)
def fiber(seq, num=4, name="", rna=0, single=0, repeats=0, preserve=0, exe="$X3DNA/bin/fiber", quiet=1): """ DESCRIPTION Run X3DNA's "fiber" tool. For the list of structure identification numbers, see for example: http://xiang-jun.blogspot.com/2009/10/fiber-models-in-3dna.html USAGE fiber seq [, num [, name [, rna [, single ]]]] ARGUMENTS seq = str: single letter code sequence or number of repeats for repeat models. num = int: structure identification number {default: 4} name = str: name of object to create {default: random unused name} rna = 0/1: 0=DNA, 1=RNA {default: 0} single = 0/1: 0=double stranded, 1=single stranded {default: 0} EXAMPLES # environment (this could go into ~/.pymolrc or ~/.bashrc) os.environ["X3DNA"] = "/opt/x3dna-v2.3" # B or A DNA from sequence fiber CTAGCG fiber CTAGCG, 1, ADNA # double or single stranded RNA from sequence fiber AAAGGU, name=dsRNA, rna=1 fiber AAAGGU, name=ssRNA, rna=1, single=1 # poly-GC Z-DNA repeat model with 10 repeats fiber 10, 15 """ import os, tempfile, subprocess, shutil rna, single = int(rna), int(single) preserve, quiet = int(preserve), int(quiet) if "X3DNA" not in os.environ: raise CmdException("please set X3DNA environment variable") args = [cmd.exp_path(exe), "-seq=" + seq, "-" + str(num)] if rna: args.append("-rna") if single: args.append("-single") if not name: name = cmd.get_unused_name("fiber-" + str(num) + "_") tmpdir = tempfile.mkdtemp() outfile = os.path.join(tmpdir, "out.pdb") args.append(outfile) if seq.endswith("help"): # call fiber with no arguments to get help page args[1:] = [] try: p = subprocess.Popen(args, cwd=tmpdir, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, _ = p.communicate(str(int(repeats) or seq)) if not quiet: print(stdout) if len(args) != 1: if p.returncode != 0: raise CmdException("Returned non-zero status: " + str(args)) cmd.load(outfile, name, quiet=quiet) except OSError: raise CmdException('Cannot execute "%s"' % (exe)) finally: if not preserve: shutil.rmtree(tmpdir) elif not quiet: print(" Notice: not deleting", tmpdir)
def dss_promotif(selection='all', exe='', raw='', state=-1, quiet=1): ''' DESCRIPTION Secondary structure assignment with PROMOTIF. http://www.rubic.rdg.ac.uk/~gail/#Software SEE ALSO dss, dssp, stride ''' from subprocess import Popen, PIPE import tempfile, os, shutil state, quiet = int(state), int(quiet) ss_map = { 'B': 'S', 'E': 'S', 'H': 'H', 'G': 'H', } exe = cmd.exp_path(exe) if not exe: from . import which motifdir = os.environ.get('motifdir') exe = which('p_sstruc3', 'p_sstruc2', 'promotif.scr', path=[motifdir] if motifdir else None) tmpdir = tempfile.mkdtemp() tmpfilepdb = os.path.join(tmpdir, 'xxxx.pdb') tmpfilesst = os.path.join(tmpdir, 'xxxx.sst') ss_dict = dict() try: for model in cmd.get_object_list('(' + selection + ')'): cmd.save(tmpfilepdb, 'model %s and (%s)' % (model, selection), state) process = Popen([exe, tmpfilepdb], cwd=tmpdir, stdin=PIPE) process.communicate(tmpfilepdb + os.linesep) with open(tmpfilesst) as handle: for line in handle: if line.startswith(' num seq.no'): break for line in handle: if not line.strip(): break chain = line[6].strip('-') resi = line[7:12].strip() ss = line[23] ss_dict[model,chain,resi] = ss os.remove(tmpfilesst) except OSError: print(' Error: Cannot execute exe=' + exe) raise CmdException finally: shutil.rmtree(tmpdir) _common_ss_alter(selection, ss_dict, ss_map, raw)
def prepwizard( name, selection="all", options="", state=-1, preserve=0, exe="$SCHRODINGER/utilities/prepwizard", quiet=1 ): """ 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 os.path.exists(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) p = subprocess.Popen(args, cwd=tmpdir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) print(p.communicate()[0].rstrip()) if p.returncode != 0: logfile = os.path.join(tmpdir, "in.log") if os.path.exists(logfile): with open(logfile) as handle: print(handle.read()) raise CmdException("%s failed with exit status %d" % (args[0], p.returncode)) cmd.load(os.path.join(tmpdir, outfile), name) except OSError: raise CmdException('Cannot execute "%s"' % (exe)) finally: if not preserve: shutil.rmtree(tmpdir) elif not quiet: print(" Notice: not deleting", tmpdir) if not quiet: print(" prepwizard: done")
def dyndom(mobile, target, window=5, domain=20, ratio=1.0, exe='', transform=1, quiet=1, mobile_state=1, target_state=1, match='align', preserve=0): ''' DESCRIPTION DynDom wrapper DynDom is a program to determine domains, hinge axes and hinge bending residues in proteins where two conformations are available. http://fizz.cmp.uea.ac.uk/dyndom/ USAGE dyndom mobile, target [, window [, domain [, ratio ]]] ''' import tempfile, subprocess, os, shutil, sys from .exporting import save_pdb_without_ter window, domain, ratio = int(window), int(domain), float(ratio) transform, quiet = int(transform), int(quiet) mobile_state, target_state = int(mobile_state), int(target_state) mm = MatchMaker( '(%s) & polymer & state %d' % (mobile, mobile_state), '(%s) & polymer & state %d' % (target, target_state), match) chains = cmd.get_chains(mm.mobile) if len(chains) != 1: print('mobile selection must be single chain') raise CmdException chain1id = chains[0] chains = cmd.get_chains(mm.target) if len(chains) != 1: print('target selection must be single chain') raise CmdException chain2id = chains[0] if not exe: from . import which exe = which('DynDom', 'dyndom') if not exe: print(' Error: Cannot find DynDom executable') raise CmdException else: exe = cmd.exp_path(exe) tempdir = tempfile.mkdtemp() try: filename1 = os.path.join(tempdir, 'mobile.pdb') filename2 = os.path.join(tempdir, 'target.pdb') commandfile = os.path.join(tempdir, 'command.txt') infofile = os.path.join(tempdir, 'out_info') save_pdb_without_ter(filename1, mm.mobile, state=mobile_state) save_pdb_without_ter(filename2, mm.target, state=target_state) f = open(commandfile, 'w') f.write('title=out\nfilename1=%s\nchain1id=%s\nfilename2=%s\nchain2id=%s\n' \ 'window=%d\ndomain=%d\nratio=%.4f\n' % (filename1, chain1id, filename2, chain2id, window, domain, ratio)) f.close() process = subprocess.Popen([exe, commandfile], cwd=tempdir, universal_newlines=True, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) for line in process.stdout: if not quiet: sys.stdout.write(line) if process.poll() != 0: raise CmdException('"%s" failed with status %d' % (exe, process.returncode)) cmd.color('gray', mobile) fixed_name = dyndom_parse_info(infofile, mm.mobile, quiet) except OSError: print('Cannot execute "%s", please provide full path to DynDom executable' % (exe)) raise CmdException finally: if not int(preserve): shutil.rmtree(tempdir) elif not quiet: print(' Not deleting temporary directory:', tempdir) if transform and fixed_name is not None: cmd.align(fixed_name, target)
def compare_10gs_11gs(): # it is possible to download proteins from RCSB (Protein Data Bank) to fetch_path, which is current working # directory by default cmd.set('fetch_path', cmd.exp_path(PATH_data)) cmd.fetch('10gs') cmd.fetch('11gs') cmd.load('{0}10gs.cif'.format(PATH_data), '10gs') cmd.load('{0}11gs.cif'.format(PATH_data), '11gs') # proteins # pymol has several options for proteins alignment, align is better for proteins with high homology align_command = cmd.align # or super, or cealign align_res = align_command('10gs', '11gs') if align_command == cmd.align: print('aligned with rmsd {0}'.format(align_res[0])) # cmd.create creates a separate object (copies everything to it) # het stands for heteroatoms (non-protein) cmd.create('10gs_protein', '10gs and not het') cmd.create('11gs_protein', '11gs and not het') # print protein sequences for fun fasta_10gs = cmd.get_fastastr(selection='10gs_protein') fasta_11gs = cmd.get_fastastr(selection='11gs_protein') print('10gs sequence:{0}'.format(fasta_10gs)) print('11gs sequence:{0}'.format(fasta_11gs)) cmd.delete('*_protein') # delete objects # ligands cmd.select('10gs_ligands', '10gs and not resname HOH and het') cmd.select('11gs_ligands', '11gs and not resname HOH and het') space_10gs = {'lig_names': []} # or simpy lig_names = [] space_11gs = {'lig_names': []} # strange pymol interface to iterate over atoms cmd.iterate('10gs_ligands', 'lig_names.append(resn)', space=space_10gs) cmd.iterate('11gs_ligands', 'lig_names.append(resn)', space=space_11gs) ligs_10gs = set(space_10gs['lig_names']) ligs_11gs = set(space_11gs['lig_names']) # by the way, in both 10gs and 11gs we have MSE, which is actually a modified residue and not a ligand print('ligands found in 10gs: {0}'.format(ligs_10gs)) print('ligands found in 11gs: {0}'.format(ligs_11gs)) for ligand_unique in ligs_10gs.symmetric_difference(ligs_11gs): cmd.save( '{0}{1}_{2}_ligand.sdf'.format( PATH_data, '10gs' if ligand_unique in ligs_10gs else '11gs', ligand_unique), 'resname {0}'.format(ligand_unique)) # deleting selection, objects remain unchanged cmd.delete('ligs*') print('drawing a figure (this will take some time)') cmd.set('transparency_mode', 1) cmd.bg_color('white') cmd.show('sticks', 'het and not resname HOH') cmd.color('white', 'not het') cmd.show('surface', 'not het') cmd.hide('lines') cmd.set('transparency', '0.7') cmd.show('spheres', 'resname HOH') cmd.color('palecyan', 'resname HOH') cmd.hide('nonbonded', 'resname HOH') cmd.set('sphere_transparency', '0.7') cmd.ray() cmd.png('{0}fig.png'.format(PATH_data))
def poseview(ligand='organic inorganic', protein='polymer', width=0, height=0, filename='', exe='poseview', state=-1, quiet=1): ''' DESCRIPTION PoseView wrapper http://www.biosolveit.de/poseview/ USAGE poseview [ ligand [, protein [, width [, height [, exe [, state ]]]]]] ARGUMENTS ligand = string: atom selection {default: organic inorganic} protein = string: atom selection {default: polymer} width = int: image width {default: viewport width} height = int: image height {default: viewport height} filename = string: output PNG file name {default: temporary} exe = string: path to executable {default: poseview} SETUP 1) Put poseview executable to PATH (e.g. /usr/bin/poseview) 2) Set environment variable BIOSOLVE_LICENSE_FILE="/path/to/poseview.lic" ''' import tempfile, subprocess, os, shutil width, height = int(width), int(height) state, quiet = int(state), int(quiet) if width == 0 or height == 0: viewport = cmd.get_viewport() if width != 0: height = int(viewport[0] / float(width) * viewport[1]) elif height != 0: width = int(viewport[1] / float(height) * viewport[0]) else: width, height = viewport exe = cmd.exp_path(exe) tempdir = tempfile.mkdtemp() try: ligand_filename = os.path.join(tempdir, 'ligand.sdf') protein_filename = os.path.join(tempdir, 'protein.pdb') if not filename: filename = os.path.join(tempdir, 'image.png') cmd.save(ligand_filename, ligand, state) cmd.save(protein_filename, protein, state) args = [exe, '-l', ligand_filename, '-p', protein_filename, '-t', '', '-o', filename, '-s', str(width), str(height)] if not quiet: print ' poseview: running...' process = subprocess.Popen(args, stderr=subprocess.STDOUT, stdout=subprocess.PIPE) stdout, _ = process.communicate() if not quiet: print stdout print ' poseview: done' if filename.endswith('.png'): cmd.load(filename) elif not quiet: print ' Warning: cannot load "%s" into PyMOL, unsupported file type' % (filename) except OSError: print ' Error: Cannot execute "%s", please provide full path to poseview executable' % (exe) raise CmdException finally: shutil.rmtree(tempdir)