modules/pymol/cmd.py (229 lines of code) (raw):

#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* ------------------------------------------------------------------- # cmd.py # Python interface module for PyMol # # **This is the only module which should be/need be imported by # ** PyMol API Based Programs # NEW CALL RETURN CONVENTIONS for _cmd.so C-layer # # (1) Calls into C (_cmd) should return results/status and print # errors and feedback (according to mask) BUT NEVER RAISE EXCEPTIONS # from within the C code itself. # (2) Effective with version 0.99, standard Python return conventions # apply, but haven't yet been fully implemented. In summary: # Unless explicitly specified in the function: # ==> Success with no information should return None # ==> Failure should return a negative number as follows: # -1 = a general, unspecified failure # Upon an error, exceptions will be raised by the Python wrapper # layer if the "raise_exceptions" setting is on. # ==> Boolean queries should return 1 for true/yes and 0 for false/no. # ==> Count queries should return 0 or a positive number # (3) If _cmd produces a specific return result, be sure to include an # error result as one of the possibilities outside the range of the # expected return value. For example, a negative distance # # (4) cmd.py API wrappers can then raise exceptions and return values. # # NOTE: Output tweaking via the "quiet" parameter of API functions. # # Many PyMOL API functions have a "quiet" parameter which is used to # customize output depending on when and where the routine was called. # # As defined, quiet should be 1. Called from an external module, output # to the console should be minimal. # # However, when a command is run through the parser (often manually) the # user expects a little more feedback. The parser will automatically # set "quiet" to zero # # In rare cases, certain nonserious error or warning output should # also be suppressed. Set "quiet" to 2 for this behavior. from __future__ import print_function def _deferred_init_pymol_internals(_pymol): # set up some global session tasks if viewing.session_restore_views not in _pymol._session_restore_tasks: _pymol._session_restore_tasks.append(viewing.session_restore_views) if viewing.session_save_views not in _pymol._session_save_tasks: _pymol._session_save_tasks.append(viewing.session_save_views) if viewing.session_restore_scenes not in _pymol._session_restore_tasks: _pymol._session_restore_tasks.append(viewing.session_restore_scenes) if wizarding.session_restore_wizard not in _pymol._session_restore_tasks: _pymol._session_restore_tasks.append(wizarding.session_restore_wizard) if wizarding.session_save_wizard not in _pymol._session_save_tasks: _pymol._session_save_tasks.append(wizarding.session_save_wizard) # take care of some deferred initialization _pymol._view_dict_sc = Shortcut({}) _pymol._scene_dict_sc = Shortcut({}) # if __name__=='pymol.cmd': import traceback import sys # pymol2.cmd2 exposes a weak reference, this is not possible (and not # necessary) on the module level, so we simply make a self reference. _weakrefproxy = sys.modules[__name__] try: import re from pymol import _cmd import string import threading import pymol import os from . import parsing import time _pymol = pymol from .shortcut import Shortcut from chempy import io ####################################################################### # symbols for early export ####################################################################### from .constants import * from .constants import _load2str fb_debug = sys.stderr # can redirect python debugging output elsewhere if desred... #-------------------------------------------------------------------- # convenient type and result checking from .checking import * from .checking import _raising #------------------------------------------------------------------- # path expansion, including our fixes for Win32 def _nt_expandvars(path): # allow for //share/folder$/file path = nt_hidden_path_re.sub(r"$$\\",path) return os.path.expandvars(path) if "nt" in sys.builtin_module_names: _expandvars = _nt_expandvars else: _expandvars = os.path.expandvars def exp_path(path): path = as_pathstr(path) return _expandvars(os.path.expanduser(path)) def as_pathstr(path): # On Windows, always work with unicode file names. On Unix, # UTF-8 byte strings seem to be fine, so keep them for now. if isinstance(path, bytes) and sys.platform == 'win32': for encoding in ('utf-8', 'mbcs'): try: return path.decode(encoding) except UnicodeError: pass return path #-------------------------------------------------------------------- # locks and threading reaper = None # the following locks are used by both C and Python to insure that no more than # one active thread enters PyMOL at a given time. lock_api = pymol.lock_api lock_api_c = pymol.lock_api_c lock_api_status = pymol.lock_api_status lock_api_glut = pymol.lock_api_glut lock_api_data = pymol.lock_api_data lock_api_allow_flush = 1 from .locking import * lockcm = LockCM() #-------------------------------------------------------------------- # status monitoring from .monitoring import * #-------------------------------------------------------------------- # Feedback from .feedingback import * from .feedingback import _feedback #-------------------------------------------------------------------- # internal API routines from . import internal _alt = internal._alt _coordset_update_spawn = internal._coordset_update_spawn _coordset_update_thread = internal._coordset_update_thread _copy_image = internal._copy_image _ctrl = internal._ctrl _ctsh = internal._ctsh _do = internal._do _dump_floats = internal._dump_floats _dump_ufloats = internal._dump_ufloats _fake_drag = internal._fake_drag _get_color_sc = internal._get_color_sc _get_feedback = internal._get_feedback _interpret_color = internal._interpret_color _invalidate_color_sc = internal._invalidate_color_sc _load = internal._load _mpng = internal._mpng _object_update_spawn = internal._object_update_spawn _object_update_thread = internal._object_update_thread _png = internal._png _quit = internal._quit _ray_anti_spawn = internal._ray_anti_spawn _ray_hash_spawn = internal._ray_hash_spawn _ray_spawn = internal._ray_spawn _refresh = internal._refresh _sgi_stereo = internal._sgi_stereo _special = internal._special _validate_color_sc = internal._validate_color_sc _cache_get = internal._cache_get _cache_set = internal._cache_set _cache_clear = internal._cache_clear _cache_purge = internal._cache_purge _cache_mark = internal._cache_mark _sdof = internal._sdof # when adding, remember to also edit cmd2.py get_feedback = _get_feedback # legacy ####################################################################### # now import modules which depend on the above ####################################################################### from . import editor ####################################################################### # cmd module functions... ####################################################################### # for extending the language from .commanding import extend, extendaa, alias # for documentation etc from .helping import python_help def write_html_ref(file): '''Write the PyMOL Command Reference to an HTML file''' f=open(file,'w') kees = [a for a in keywords.get_command_keywords() if not a.startswith('_') and keyword[a][0] != python_help] kees.sort() title = 'PyMOL Command Reference' f.write('''<html> <head> <title>%s</title> <style type='text/css'> body, p, h1, h2 { font-family: sans-serif; } p.api { font:small monospace; color:#999; } pre.example { background-color: #ccc; padding: 5px; } li { display: block; width: 10em; float: left; } </style> </head> <body> <h1>%s</h1> <p>This is the list of all PyMOL commands which can be used in the PyMOL command line and in PML scripts. The command descriptions found in this file can also be printed to the PyMOL text buffer with the <a href="#help">help</a> command. Example:</p> <pre class="example">PyMOL&gt;help color ...</pre> <p>The list of arguments for a command (the "usage") can be queried on the command line with a questionmark. Example:</p> <pre class="example">PyMOL&gt;color ? Usage: color color [, selection [, quiet [, flags ]]]</pre> <p>The square brackets ("[" and "]") indicate optional arguments and are not part of the syntax.</p> <p>If the PyMOL command interpreter doesn't understand some input, it passes it to the Python interpreter. This means that single-line Python expressions can be put into PML scripts or typed into the command line. Prefixing a line with a slash (/) forces the interpreter to pass it to Python. See also the <a href="#python">python</a> command to input multi-line Python scripts.</p> <p>This file can be generated on the PyMOL command line:</p> <pre class="example">PyMOL&gt;cmd.write_html_ref('pymol-command-ref.html')</pre> <hr size=1> <ul> ''' % (title, title)) for a in kees: f.write("<li><a href='#%s'>%s</a></li>" % (a, a)) f.write('</ul><br style="clear: both">') def make_see_also_link(m): w = m.group() if w in kees: return "<a href='#%s'>%s</a>" % (w, w) return w for a in kees: func = keyword[a][0] doc = (getattr(func, '__doc__') or 'UNDOCUMENTED').strip(). \ replace("<", "&lt;"). \ replace(">", "&gt;").splitlines() # attemt to do some HTML formatting isseealso = False for i, line in enumerate(doc): if not line.strip(): continue isindented = line[:1].isspace() if isindented: if isseealso: doc[i] = re.sub(r'\w+', make_see_also_link, line) elif line.isupper(): isseealso = line.startswith('SEE ALSO') doc[i] = '<b>' + line + '</b>' f.write("<hr size=1><h2 id='%s'>%s</h2>" % (a, a)) f.write("<pre>%s</pre>" % ('\n'.join(doc))) f.write("<p class='api'>api: %s.%s</p>" % (func.__module__, func.__name__)) f.write("</BODY></HTML>") f.close() print("PyMOL Command Reference written to %s" % (os.path.abspath(file))) ##################################################################### # Here is where the PyMOL Command Language and API are built. ##################################################################### # first we need to import a set of symbols into the local namespace from .api import * # deferred initialization _deferred_init_pymol_internals(pymol) # now we create the command langauge from . import keywords keyword = keywords.get_command_keywords() kw_list = list(keyword.keys()) keywords.fix_list(kw_list) kwhash = Shortcut(kw_list) keywords.fix_dict(keyword) # informational or API-only functions which don't exist in the # PyMOL command language namespace help_only = keywords.get_help_only_keywords() help_sc = Shortcut(list(keyword.keys())+list(help_only.keys())) # keyboard configuration from . import keyboard key_mappings = keyboard.get_default_keys() selection_sc = lambda sc=Shortcut,gn=get_names:sc(gn('public')+[ 'not ', 'and ', 'or ', 'first ', 'last ', 'in ', 'like ', 'byobject ', 'bysegi ', 'bychain ', 'byres ', 'bycalpha ', 'bymolecule ', 'bound_to ', 'neighbor ', 'extend ', 'within ', 'around ', 'expand ', 'gap ', 'near_to ', 'beyond ', 'model ', 'chain ', 'segi ', 'resn ', 'resi ', 'name ', 'alt ', 'index ', 'id ', 'rank ', 'partial_charge ', 'formal_charge ', 'b ', 'q ', 'ss ', 'elem ', 'rep ', 'color ', 'pepseq ', 'all', 'enabled', 'visible', 'bonded', 'protected', 'masked', 'organic', 'inorganic', 'solvent', 'polymer', 'guide', 'hetatm', 'hydrogens', 'backbone', 'sidechain', 'metals', 'donors', 'acceptors', 'polymer.protein', 'polymer.nucleic', 'center', 'origin', ]) object_sc = lambda sc=Shortcut,gn=get_names:sc(gn('objects')) map_sc = lambda sc=Shortcut,gnot=get_names_of_type:sc(gnot('object:map')) contour_sc = lambda sc=Shortcut,gnot=get_names_of_type:sc(gnot('object:mesh')+gnot('object:surface')) group_sc = lambda sc=Shortcut,gnot=get_names_of_type:sc(gnot('object:group')) # Table for argument autocompletion from . import completing auto_arg = completing.get_auto_arg_list() color_sc = None raw_image_callback = None except: print("Error: unable to initalize the pymol.cmd module") traceback.print_exc() sys.exit(0) else: from pymol.cmd import *