#A* ------------------------------------------------------------------- #B* This file contains source code for the PyMOL computer program #C* Copyright (c) Schrodinger, LLC. #D* ------------------------------------------------------------------- #E* It is unlawful to modify or remove this copyright notice. #F* ------------------------------------------------------------------- #G* Please see the accompanying LICENSE file for further information. #H* ------------------------------------------------------------------- #I* Additional authors of this source file include: #-* #-* #-* #Z* ------------------------------------------------------------------- from . import colorprinting if True: import os import sys import _thread as thread from . import selector import re import copy import pymol cmd = sys.modules["pymol.cmd"] from .cmd import _cmd,Shortcut,QuietException from chempy import io from chempy.pkl import cPickle from .cmd import _feedback,fb_module,fb_mask, \ DEFAULT_ERROR, DEFAULT_SUCCESS, is_error, \ is_list, is_dict, is_tuple, loadable def copy_image(quiet=1, *, _self=cmd): # incentive feature / proprietary _self._call_in_gui_thread(lambda: _self._copy_image(_self, int(quiet))) cache_action_dict = { 'enable' : 0, 'disable' : 1, 'read_only' : 2, 'clear' : 3, 'optimize' : 4, } cache_action_sc = Shortcut(cache_action_dict.keys()) def cache(action='optimize', scenes='',state=-1, quiet=1, *, _self=cmd): ''' DESCRIPTION "cache" manages storage of precomputed results, such as molecular surfaces. USAGE cache action [, scenes [, state ]] ARGUMENTS action = string: enable, disable, read_only, clear, or optimize scenes = string: a space-separated list of scene names (default: '') state = integer: state index (default: -1) EXAMPLES cache enable cache optimize cache optimize, F1 F2 F5 NOTES "cache optimize" will iterate through the list of scenes provided (or all defined scenes), compute any missing surfaces, and store them in the cache for later reuse. PYMOL API cmd.cache(string action, string scenes, int state, int quiet) ''' action = cache_action_dict[cache_action_sc.auto_err(str(action),'action')] quiet = int(quiet) if action == 0: # enable _self.set('cache_mode', 2, quiet=quiet) elif action == 1: # disable _self.set('cache_mode', 0, quiet=quiet) elif action == 2: # read_only _self.set('cache_mode', 1, quiet=quiet) elif action == 3: # clear _self._cache_clear() elif action == 4: # optimize _self._cache_mark() cur_scene = _self.get('scene_current_name') cache_max = _self.get_setting_int('cache_max') if cache_max>0: # allow double memory for an optimized cache _self.set('cache_max',cache_max*2) scenes = str(scenes) scene_list = scenes.split() cache_mode = int(_self.get('cache_mode')) _self.set('cache_mode',2) if not len(scene_list): scene_list = _self.get_scene_list() for scene in scene_list: scene = scene.strip() if not quiet: print(" cache: optimizing scene '%s'."%scene) _self.scene(scene,animate=0) _self.rebuild() _self.refresh() if len(cur_scene): _self.scene(cur_scene,animate=0) else: scene_list = _self.get_scene_list() if len(scene_list): _self.scene(scene_list[0],animate=0) else: if not quiet: print(" cache: no scenes defined -- optimizing current display.") _self.rebuild() _self.refresh() usage = _self._cache_purge(-1) if cache_mode: _self.set('cache_mode',cache_mode) else: _self.set('cache_mode',2) # hmm... could use 1 here instead. _self.set('cache_max',cache_max) # restore previous limits if not quiet: print(" cache: optimization complete (~%0.1f MB)."%(usage*4/1000000.0)) else: raise ValueError('action') _resn_to_aa = { 'ALA' : 'A', 'CYS' : 'C', 'ASP' : 'D', 'GLU' : 'E', 'PHE' : 'F', 'GLY' : 'G', 'HIS' : 'H', 'ILE' : 'I', 'LYS' : 'K', 'LEU' : 'L', 'MET' : 'M', 'ASN' : 'N', 'PRO' : 'P', 'GLN' : 'Q', 'ARG' : 'R', 'SER' : 'S', 'THR' : 'T', 'VAL' : 'V', 'TRP' : 'W', 'TYR' : 'Y', # RNA 'A' : 'A', 'U' : 'U', 'G' : 'G', 'C' : 'C', # DNA 'DA' : 'A', 'DT' : 'T', 'DG' : 'G', 'DC' : 'C', } def get_fastastr(selection="all", state=-1, quiet=1, key='', *, _self=cmd): ''' DESCRIPTION API only. Get protein and nucleic acid sequences in fasta format. Used for saving: PyMOL> save foo.fasta New in PyMOL 2.2: - chain specific keys (key argument) - nucleic acid support ARGUMENTS selection = str: atom selection (reduced to "guide & alt +A") {default: all} state = int: (only used if state > 0) quiet = 0/1: UNUSED key = str: python expression {default: model + "_" + chain} Use key=model to get the old (non-chain specific) behavior ''' import textwrap import collections seq = collections.OrderedDict() lines = [] selection = "(" + selection + ") & guide & alt +A" if int(state) > 0: selection += ' & state {}'.format(state) if not key: key = 'model + "_" + chain' # for discrete objects: state specific keys key += ' + (":{}".format(state) if state else "")' _self.iterate(selection, "seq.setdefault((" + key + "),[]).append(resn)", space={'seq': seq, 'str': str}) for key, resn_list in seq.items(): cur_seq = ''.join(_resn_to_aa.get(x, '?') for x in resn_list) lines.append(">{}".format(key)) lines.extend(textwrap.wrap(cur_seq, 70)) if lines: lines.append('') # final newline return '\n'.join(lines) def get_pdbstr(selection="all", state=-1, ref='', ref_state=-1, quiet=1, *, _self=cmd): ''' DESCRIPTION "get_pdbstr" in an API-only function which returns a pdb corresponding to the atoms in the selection provided and that are present in the indicated state PYMOL API cmd.get_pdbstr(string selection, int state) NOTES "state" is a 1-based state index for the object. if state is -1, then current state is used. if state is 0, then all states are saved. ''' return _self.get_str('pdb', selection, state, ref, ref_state, -1, quiet) def _get_dump_str(obj): if is_list(obj): list = map(_get_dump_str,obj) result = "[ " + ",\n".join(list) + " ] " elif is_dict(obj): list = [] for key in obj.keys(): list.append( _get_dump_str(key)+" : "+_get_dump_str(obj[key]) ) result = "{ " + ",\n".join(list) + " } " elif is_tuple(obj): list = map(_get_dump_str,obj) result = "( " + ",\n".join(list) + " ) " else: result = str(obj) return result def _session_convert_legacy(session, version, _self=cmd): ''' Convert session contents to be compatible with previous PyMOL versions ''' if version >= _self.get_version()[1]: return print(" Applying pse_export_version=%.3f compatibility" % (version)) def bitmaskToList(mask): if not isinstance(mask, int): return mask r = [] while (mask >> len(r)): r.append(1 if ((mask >> len(r)) & 1) else 0) return r def convert_settings(settings_list): if not settings_list: return # get index -> setting dict settings = dict((s[0], s) for s in settings_list if s is not None) # changed type cast_fn = { 3: float, 4: lambda v: list(_self.get_color_tuple(v)), } for (i, old, new) in [ (6, 4, 5), # bg_rgb (254, 3, 1), # scenes_changed ]: if i in settings and settings[i][1] == new: settings[i][1] = old settings[i][2] = cast_fn[old](settings[i][2]) # changed defaults changed = [] if version < 1.76: changed += [ (91, 7, -1), # cartoon_sampling (93, 6., -1.), # cartoon_loop_quality (102, 10., -1.), # cartoon_oval_quality (104, 9., -1.), # cartoon_tube_quality (378, 11., -1.), # cartoon_putty_quality ] if version < 1.5: changed += [ (421, -1, 9), # sphere_mode ] for (i, old, new) in changed: if i in settings and settings[i][2] == new: settings[i][2] = old if 'settings' in session: convert_settings(session['settings']) # objects for name in session['names']: if name is None: continue # spec repOn if version < 1.76 and name[3] is None: name[3] = [0] * 20 # only continue for objects if name[1] != 0: continue if name[4] == 8: # gadget cobject = name[5][0][0] else: cobject = name[5][0] # object visRep if version < 1.76: cobject[3] = bitmaskToList(cobject[3]) # object settings convert_settings(cobject[8]) # molecule if name[4] == 1: # atoms visRep if version < 1.76: for atom in name[5][7]: atom[20] = bitmaskToList(atom[20]) # state settings for cset in name[5][4]: if cset: convert_settings(cset[7]) # map elif name[4] == 2: if version < 1.5: # crystal -> [crystal, spacegroup] for state in name[5][2]: if state and state[1]: state[1] = state[1][0] # cgo elif name[4] == 6: if version < 1.506: for state in name[5][2]: if len(state) == 1: # std and ray CGO state.append(state[0]) def get_session(names='', partial=0, quiet=1, compress=-1, cache=-1, binary=-1, version=-1, *, _self=cmd): ''' :param names: Names of objects to export, or the empty string to export all objects. :param partial: If true, do not store selections, settings, view, movie. :param compress: DEPRECATED Pickle the dictionary to a string and compress that with zlib {default: session_compression} :param cache: ? :param binary: Use efficient binary format {default: pse_binary_dump} :param version: {default: pse_export_version} ''' session = {} cache = int(cache) compress = int(compress) partial = int(partial) quiet = int(quiet) if version < 0: version = _self.get_setting_float('pse_export_version') pse_export_version = round(float(version), 4) legacyscenes = (0 < pse_export_version < 1.76) and _self.get_scene_list() if True: legacypickle = (0 < pse_export_version < 1.9) if legacypickle: print(' Using Python 2 compatible legacy pickler') cPickle.configure_legacy_dump(legacypickle) if legacyscenes: _self.pymol._scene_dict = {} scene_current_name = _self.get('scene_current_name') tempname = '_scene_db96724c3cef00875c3bebb4f348f711' _self.scene(tempname, 'store') for name in legacyscenes: _self.scene(name, 'recall', animate=0) wizard = _self.get_wizard() message = wizard.message if getattr(wizard, 'from_scene', 0) else None pymol.viewing._legacy_scene(name, 'store', message, _self=_self) _self.scene(tempname, 'recall', animate=0) _self.scene(tempname, 'clear') _self.set('scene_current_name', scene_current_name) if cache: cache_opt = _self.get_setting_int('session_cache_optimize') if cache_opt == 1 or (cache_opt != 0 and _self.get_setting_int('cache_mode')): _self.cache('optimize') with _self.lockcm: _cmd.get_session(_self._COb, session, str(names), int(partial), int(quiet), binary, pse_export_version) if True: try: session['session'] = copy.deepcopy(_self._pymol.session) if cache and hasattr(_self._pymol,'_cache'): session['cache'] = _self._pymol._cache except: colorprinting.print_exc() for a in _self._pymol._session_save_tasks: assert a is not None error = False try: # TODO _session_restore_tasks use `not ` # instead of `is_error()` error = is_error(a(session, _self=_self)) except: if not quiet: colorprinting.print_exc([__file__]) error = True if error: msg = f'Warning: session-save-task "{a.__name__}" failed.' if not quiet: msg += '\n The resulting session file may be incomplete.' colorprinting.warning(msg) if legacyscenes: del session['moviescenes'] session['scene_dict'] = _self.pymol._scene_dict session['scene_order'] = legacyscenes pymol.viewing._legacy_scene('*', 'clear', _self=_self) del _self.pymol._scene_dict if True: if pse_export_version > 0.0: try: _session_convert_legacy(session, pse_export_version, _self) except Exception as e: print(' Warning: failed to backport session:', e) if(compress<0): compress = _self.get_setting_boolean('session_compression') if(compress): colorprinting.warning( ' Warning: `session_compression` is deprecated. Save ' 'to ".pze" or ".pse.gz" files instead, and/or use ' '`pse_binary_dump`') import zlib session = zlib.compress(cPickle.dumps(session, 1)) return session def _unit2px(value, dpi, unit=''): '''API only. Returns pixel units given a string representation in other units''' if cmd.is_string(value): m = re.search(r'[a-z].*', value, re.I) if m: value, unit = value[:m.start()], m.group(0).lower() if not unit or unit == 'px': return int(value) upi = {'in': 1.0, 'mm': 25.4, 'cm': 2.54} if unit not in upi: raise pymol.CmdException('unknown unit, supported units are: ' + ', '.join(upi)) if dpi < 1: raise pymol.CmdException('dpi > 0 required with unit "%s" ' '(hint: set the "image_dots_per_inch" setting)' % unit) return float(value) * dpi / upi[unit] + 0.5 def png(filename, width=0, height=0, dpi=-1.0, ray=0, quiet=1, prior=0, format=0, *, _self=cmd): ''' DESCRIPTION "png" saves a PNG format image file of the current display. USAGE png filename [, width [, height [, dpi [, ray]]]] ARGUMENTS filename = string: file path to be written width = integer or string: width in pixels (without units), inches (in) or centimeters (cm). If unit suffix is given, dpi argument is required as well. If only one of width or height is given, the aspect ratio of the viewport is preserved. {default: 0 (current)} height = integer or string: height (see width) {default: 0 (current)} dpi = float: dots-per-inch {default -1.0 (unspecified)} ray = 0 or 1: should ray be run first {default: 0 (no)} EXAMPLES png image.png png image.png, dpi=300 png image.png, 10cm, dpi=300, ray=1 NOTES PNG is the only image format supported by PyMOL. SEE ALSO mpng, save PYMOL API cmd.png(string filename, int width, int height, float dpi, int ray, int quiet) ''' ray = int(ray) PRIOR_TRY = -1 PRIOR_NO = 0 PRIOR_YES = 1 prior = int(prior) assert prior in (PRIOR_TRY, PRIOR_YES, PRIOR_NO) FORMAT_GUESS = -1 FORMAT_PNG = 0 FORMAT_PPM = 1 if format == 'png': format = FORMAT_PNG assert format in (FORMAT_PNG, FORMAT_PPM, FORMAT_GUESS) if format == FORMAT_GUESS: if filename and filename.endswith(".ppm"): format = FORMAT_PPM else: format = FORMAT_PNG if filename and not filename.startswith('\x01'): if format == FORMAT_PNG and not filename.endswith(".png"): filename += ".png" filename = cmd.exp_path(filename) dpi = float(dpi) if dpi < 0: dpi = _self.get_setting_float('image_dots_per_inch') width = _unit2px(width, dpi) height = _unit2px(height, dpi) filename = "" if filename is None else filename def func(): with _self.lockcm: return _cmd.png(_self._COb, filename, int(width), int(height), dpi, ray, int(quiet), prior, format) if prior: # fetch the prior image, without doing any work (fast-path / non-GLUT thread-safe) r = func() if r: return r if prior != PRIOR_TRY: raise pymol.CmdException("no prior image available") print("no prior image available, fall back to rendering") prior = PRIOR_NO if ray: return func() return _self._call_with_opengl_context(func) def multisave(filename, pattern="all", state=-1, append=0, format='', quiet=1, *, _self=cmd): ''' DESCRIPTION "multisave" will save a multi-entry PDB file. Every object in the given selection (pattern) will have a HEADER and a CRYST (if symmetry is defined) record, and is terminated with END. Loading such a multi-entry PDB file into PyMOL will load each entry as a separate object. This behavior is different to the "save" command, where a multi-object selection is written "flat" to a PDB file, without HEADER or CRYST records. ARGUMENTS filename = string: file path to be written pattern = str: atom selection (before 1.8.4: object name pattern) state = int: object state (-1=current, 0=all) {default: -1} append = 0/1: append to existing file {default: 0} format = str: file format {default: guess from extension, or 'pdb'} ''' from pymol.importing import filename_to_format _, _, format_guessed, zipped = filename_to_format(filename) if zipped: raise pymol.CmdException(zipped + ' not supported with multisave') if not format: format = format_guessed or 'pdb' if format == 'pmo': raise pymol.CmdException('pmo format not supported anymore') if format not in ('pdb', 'cif'): raise pymol.CmdException(format + ' format not supported with multisave') s = _self.get_str(format, pattern, state, '', -1, 1, quiet) if s is None: raise QuietException filename = _self.exp_path(filename) with open(filename, 'a' if int(append) else 'w') as handle: handle.write(s) return DEFAULT_SUCCESS def assign_atom_types( selection, format = "mol2", state=1, quiet=1, *, _self=cmd): fmt = {'mol2': 1, 'mmd': 2}[format] with _self.lockcm: # format : mol2/sybyl = 1, macromodel/mmd = 2, global setting atom_type_format = 0 _cmd.assign_atom_types(_self._COb, selection, fmt, int(state - 1), quiet) def get_str(format, selection='(all)', state=-1, ref='', ref_state=-1, multi=-1, quiet=1, *, _self=cmd): ''' DESCRIPTION Like "get_bytes" but return a unicode string. ''' assert format not in ('mmtf',), 'binary format, use get_bytes' b = _self.get_bytes(format, selection, state, ref, ref_state, multi, quiet) if b is None: return None return b.decode('utf-8') def get_bytes(format, selection='(all)', state=-1, ref='', ref_state=-1, multi=-1, quiet=1, *, _self=cmd): ''' DESCRIPTION API-only function which exports the selection to a molecular file format and returns it as a binary ("bytes") string. ARGUMENTS format = str: pdb|cif|sdf|mol|mol2|mae|pqr|xyz selection = str: atom selection {default: all} state = int: object state (-1=current, 0=all) {default: -1} ref = str: object name which defines reference frame {default: } ref_state = int: state of ref object {default: -1} multi = int: for multi-entry file formats, 0 = single entry, 1 = by object, 2 = by object-state, -1 = format default {default: -1} ''' with _self.lockcm: return _cmd.get_str(_self._COb, str(format), str(selection), int(state) - 1, str(ref), int(ref_state), int(multi), int(quiet)) def multifilesave(filename, selection='*', state=-1, format='', ref='', ref_state=-1, quiet=1, *, _self=cmd): ''' DESCRIPTION For a selection that spans multiple molecular objects and/or states, save each object and/or state to a separate file. Takes a filename argument with placeholders: {name} : object name {state} : state number {title} : state title {num} : file number {} : object name (first) or state (second) EXAMPLES multifilesave /tmp/{name}.pdb multifilesave /tmp/{name}-{state}.cif, state=0 multifilesave /tmp/{}-{}.cif, state=0 multifilesave /tmp/{}-{title}.sdf, state=0 ''' for (fname, osele, ostate) in multifilenamegen( filename, selection, int(state), _self): r = _self.save(fname, osele, ostate, format, ref, ref_state, quiet) return r def multifilenamegen(filename, selection, state, _self=cmd): '''Given a filename pattern, atom selection and state argument, Generate object-state specific filenames and selections. ''' import string filename = _self.exp_path(filename) fmt_keys = [v[1] for v in string.Formatter().parse(filename) if v[1] is not None] nindexed = fmt_keys.count('') multiobject = nindexed > 0 or 'name' in fmt_keys or 'num' in fmt_keys multistate = nindexed > 1 or 'state' in fmt_keys or 'title' in fmt_keys if not (multiobject or multistate): raise ValueError('need one or more of {name}, {num}, {state}, {title}') odata = [] for oname in _self.get_object_list(selection): osele = '(%s) & ?%s' % (selection, oname) first = last = state if multistate: if state < 0: first = last = _self.get_object_state(oname) if first == 0: first = 1 last = _self.count_states('%' + oname) for ostate in range(first, last + 1): odata.append((oname, osele, ostate)) # pad {state} and {num} with zeros swidth = len(str(max(v[2] for v in odata))) nwidth = len(str(len(odata))) filename = filename.replace('{state}', '{state:0%d}' % swidth) filename = filename.replace('{num}', '{num:0%d}' % nwidth) for num, (oname, osele, ostate) in enumerate(odata, 1): title = _self.get_title(oname, ostate) if multistate else '' fname = filename.format(oname, ostate, name=oname, state=ostate, num=num, title=title) yield fname, osele, ostate def save(filename, selection='(all)', state=-1, format='', ref='', ref_state=-1, quiet=1, partial=0, *, _self=cmd): ''' DESCRIPTION "save" writes content to a file. USAGE save filename [, selection [, state [, format ]]] ARGUMENTS filename = string: file path to be written selection = string: atoms to save {default: (all)} state = integer: state to save {default: -1 (current state)} PYMOL API cmd.save(string file, string selection, int state, string format) NOTES The file format is automatically chosen if the extesion is one of the supported output formats: pdb, pqr, mol, sdf, pkl, pkla, mmd, out, dat, mmod, cif, pov, png, pse, psw, aln, fasta, obj, mtl, wrl, dae, idtf, or mol2. If the file format is not recognized, then a PDB file is written by default. For molecular files and where applicable and supported: * if state = -1 (default), then only the current state is written. * if state = 0, then a multi-state output file is written. SEE ALSO load, get_model ''' quiet = int(quiet) # preprocess selection selection = selector.process(selection) # r = DEFAULT_ERROR # analyze filename from pymol.importing import filename_to_format, _eval_func _, _, format_guessed, zipped = filename_to_format(filename) filename = _self.exp_path(filename) # file format if not format: if not format_guessed: raise pymol.CmdException('Unrecognized file format') format = format_guessed # PyMOL session if format in ('pse', 'psw',): _self.set("session_file", # always use unix-like path separators filename.replace("\\", "/"), quiet=1) if not quiet: print(" Save: Please wait -- writing session file...") func_type4 = { 'mmod': io.mmd.toFile, 'pkl': io.pkl.toFile, # binary pickle 'pkla': lambda model, filename: io.pkl.toFile(model, filename, bin=0), # ascii pickle } contents = None if format in savefunctions: # generic forwarding to format specific save functions func = savefunctions[format] func = _eval_func(func) kw_all = { 'filename': filename, 'selection': selection, 'name': selection, # alt (get_ccp4str) 'state': state, 'format': format, 'ref': ref, 'ref_state': ref_state, 'quiet': quiet, 'partial': partial, '_self': _self, } import inspect sig = inspect.signature(func, follow_wrapped=False) kw = {} for n, param in sig.parameters.items(): if param.kind == inspect.Parameter.VAR_KEYWORD: kw = kw_all break if param.kind == inspect.Parameter.VAR_POSITIONAL: print('FIXME: savefunctions[%s]: *args' % (format)) elif param.kind == inspect.Parameter.POSITIONAL_ONLY: raise Exception('positional-only arguments not supported') elif n in kw_all: kw[n] = kw_all[n] contents = func(**kw) if 'filename' in sig.parameters: # assume function wrote directly to file and returned a status return contents elif format in func_type4: func_type4[format](_self.get_model(selection, state, ref, ref_state), filename) r = DEFAULT_SUCCESS else: raise pymol.CmdException('File format not supported for export') # function returned sequence of strings or bytes if isinstance(contents, (tuple, list)) and contents: contents = contents[0][:0].join(contents) if cmd.is_string(contents): if not isinstance(contents, bytes): contents = contents.encode() if zipped == 'gz': import gzip fopen = gzip.open else: fopen = open if zipped == 'bz2': import bz2 contents = bz2.compress(contents) with fopen(filename, 'wb') as handle: handle.write(contents) r = DEFAULT_SUCCESS if _self._raising(r): raise QuietException if not quiet: if r == DEFAULT_SUCCESS: print(' Save: wrote "' + filename + '".') else: print(' Save-Error: no file written') return r def get_cifstr(selection="all", state=-1, quiet=1, *, _self=cmd): ''' DESCRIPTION API-only function which returns a mmCIF string. SEE ALSO get_pdbstr ''' return _self.get_str('cif', selection, state, '', -1, -1, quiet) def get_xyzstr(selection, state=-1, quiet=1, *, _self=cmd): return _self.get_str('xyz', selection, state, '', -1, -1, quiet) def get_sdfstr(selection, state=-1, ref='', ref_state=-1, quiet=1, *, _self=cmd): return _self.get_str('sdf', selection, state, ref, ref_state, -1, quiet) def get_mol2str(selection, state=-1, ref='', ref_state=-1, quiet=1, *, _self=cmd): return _self.get_str('mol2', selection, state, ref, ref_state, -1, quiet) def get_alnstr(selection, state=-1, quiet=1, *, _self=cmd): with _self.lockcm: return _cmd.get_seq_align_str(_self._COb, str(selection), int(state)-1, 0, int(quiet)) def get_pqrstr(selection, state=-1, ref='', ref_state=-1, quiet=1, *, _self=cmd): return _self.get_str('pqr', selection, state, ref, ref_state, -1, quiet) def get_maestr(selection, state=-1, ref='', ref_state=-1, quiet=1, *, _self=cmd): return _self.get_str('mae', selection, state, ref, ref_state, -1, quiet) def get_ccp4str(name, state=1, quiet=1, format='ccp4', *, _self=cmd): ftype = getattr(loadable, format, -1) with _self.lockcm: return _cmd.get_ccp4str(_self._COb, str(name), int(state) - 1, int(quiet), ftype) def get_psestr(selection, partial, quiet, _self): if '(' in selection: # ignore selections selection = '' session = _self.get_session(selection, partial, quiet) return cPickle.dumps(session, 1) def _get_mtl_obj(format, _self): # TODO mtl not implemented, always returns empty string if format == 'mtl': raise pymol.CmdException('.MTL export not implemented') i = {'mtl': 0, 'obj': 1}.get(format) return _self.get_mtl_obj()[i] savefunctions = { 'cif': get_str, # mmCIF 'xyz': get_str, 'pdb': get_str, 'pqr': get_str, 'sdf': get_str, 'mol2': get_str, 'mae': get_str, 'mol': get_str, 'mmtf': get_bytes, 'pse': get_psestr, 'psw': get_psestr, 'fasta': get_fastastr, 'aln': get_alnstr, 'ccp4': get_ccp4str, 'mrc': get_ccp4str, 'map': get_ccp4str, 'png': png, # no arguments (some have a "version" argument) 'dae': 'pymol.querying:get_collada', 'gltf': 'pymol.querying:get_gltf', 'wrl': 'pymol.querying:get_vrml', 'pov': 'pymol.querying:get_povray', 'idtf': 'pymol.querying:get_idtf', 'mtl': _get_mtl_obj, # TODO not implemented 'obj': _get_mtl_obj, 'stl': 'pymol.lazyio:get_stlstr', }