533 lines
22 KiB
Python
533 lines
22 KiB
Python
#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* -------------------------------------------------------------------
|
|
|
|
# invocation.py
|
|
#
|
|
# This module unifies argument handling for embedded and modular PyMOL
|
|
#
|
|
|
|
helptext1 = '''Copyright (C) Schrodinger, LLC
|
|
|
|
Usage: pymol [OPTIONS]... [FILES]... [-- CUSTOM SCRIPT ARGUMENTS]
|
|
|
|
Options
|
|
|
|
--help display this help and exit
|
|
--version display PyMOL version and exit
|
|
--gldebug use glDebugMessageCallback for GL debugging
|
|
--testing run pymol testing
|
|
--diagnostics dump system diagnostics
|
|
|
|
-1 config_mouse one_button
|
|
-2 config_mouse two_button
|
|
-a N alias for -A
|
|
-A N application configuration:
|
|
-A1 simple viewer window (-qxiF -X 68 -Y 100)
|
|
-A3 internal GUI only, no splash (-qx -X 68 -Y 100)
|
|
-A4 used by PYMOLVIEWER (-X 68 -Y 100)
|
|
-A5 helper application (-QxiICUF -X 68 -Y 100)
|
|
-A6 full screen presentation (-qxieICUPF)
|
|
-b[N] benchmark wizard
|
|
-B (DEPRECATED)
|
|
-c launch in command-line only mode for batch processing
|
|
-C don't terminate on Ctrl-C
|
|
-d cmd execute PyMOL command
|
|
-D N defer_builds_mode=N
|
|
-e full screen
|
|
-E N multisampling (GL_MULTISAMPLE_ARB)
|
|
-f N internal_feedback=N
|
|
-F internal_feedback=0
|
|
-g file save image (png) or movie (mpg)
|
|
-G game mode (DEPRECATED)
|
|
-h generic helper application (no controls, no feedback)
|
|
-H N window height in pixels
|
|
-i internal_gui=0
|
|
-I auto_reinitialize=1 (Mac only)
|
|
-j side-by-side stereo (stereo_mode=4)
|
|
-J cd to user's home directory
|
|
-k don't load pymolrc or plugins
|
|
-K keep alive: when running without a GUI, don't quit after the input
|
|
is exhausted
|
|
-l file run python script in thread (spawn)
|
|
-L file load file after everything else (only if something was loaded before)
|
|
-m INTERNAL - do not use (mac external GUI)
|
|
-M force mono
|
|
-n INTERNAL - do not use (incentive_product=1)
|
|
-N name UNSUPPORTED - external gui type (pmg_qt or pmg_tk) (same as -w)
|
|
-o disable security protections
|
|
-O N sphere_mode=N
|
|
-p read commands from STDIN
|
|
-P handle scenes as if the session were opened in presentation mode
|
|
-q supress startup message
|
|
-Q quiet, suppress all text output
|
|
-r file run python script
|
|
-R launch RPC Server
|
|
-s file log to file
|
|
-S force stereo
|
|
-t N stereo_mode=N
|
|
-T name UNSUPPORTED - Tcl/Tk GUI skin
|
|
-u file resume log file (execute existing content and append new log output)
|
|
-U UNSUPPORTED reuse the helper application
|
|
-v use openvr stub instead of a real hardware
|
|
-V N external GUI window height in pixels
|
|
-w name UNSUPPORTED - external gui type (pmg_qt or pmg_tk) (same as -N)
|
|
-W N window width in pixels
|
|
-x no external gui
|
|
-X N window x position on screen
|
|
-y exit on error
|
|
-Y N window y position on screen
|
|
-z N window_visible=N
|
|
-Z N zoom_mode=N
|
|
|
|
File Extensions
|
|
|
|
pdb,sdf,... molecular structure files
|
|
ccp4,dx,... map files
|
|
|
|
py,pym,pyc python script
|
|
pml PyMOL command script
|
|
|
|
p5m implies -A5 (PDB File)
|
|
psw implies -A6 (PyMOL Show File)
|
|
pwg PyMOL web GUI
|
|
|
|
Active "pymolrc" Files
|
|
'''
|
|
|
|
helptext2 = '''
|
|
Mail bug reports to https://lists.sourceforge.net/lists/listinfo/pymol-users
|
|
'''
|
|
|
|
if True:
|
|
|
|
import copy
|
|
import re
|
|
import os
|
|
import glob
|
|
import sys
|
|
import traceback
|
|
|
|
pymolrc_pat1 = '.pymolrc*'
|
|
pymolrc_pat2 = 'pymolrc*'
|
|
|
|
ros_pat = 'run_on_startup*'
|
|
|
|
class generic:
|
|
pass
|
|
|
|
global_options = generic();
|
|
|
|
options = global_options
|
|
|
|
options.deferred = []
|
|
options.no_gui = 0
|
|
options.internal_gui = 1
|
|
options.internal_feedback = 1
|
|
options.external_gui = 1
|
|
options.force_stereo = -1 if sys.platform == 'darwin' else 0
|
|
options.game_mode = 0
|
|
options.gui = 'pmg_qt'
|
|
options.skin = 'normal'
|
|
options.show_splash = 1
|
|
options.read_stdin = 0
|
|
options.win_x = 640
|
|
options.win_y = 480
|
|
options.win_xy_set = False
|
|
options.win_px = 4
|
|
options.sigint_handler = 1 # terminate on Ctrl-C?
|
|
options.reuse_helper = 0
|
|
options.auto_reinitialize = 0
|
|
options.keep_thread_alive = 0
|
|
options.after_load_script = ""
|
|
options.quiet = 0
|
|
options.multisample = 0
|
|
options.incentive_product = 0
|
|
options.window_visible = 1
|
|
options.presentation = 0
|
|
options.defer_builds_mode = 0
|
|
options.full_screen = 0
|
|
options.sphere_mode = -1
|
|
options.stereo_capable = 0
|
|
options.stereo_mode = 0
|
|
options.zoom_mode = -1
|
|
options.no_quit = 0
|
|
options.plugins = 2
|
|
options.exit_on_error = 0
|
|
options.pymolrc = None
|
|
options.no_spacenav = 0
|
|
options.launch_status = 0
|
|
options.gldebug = 0
|
|
options.testing = 0
|
|
options.openvr_stub = False
|
|
|
|
options.win_py = { 'irix':240,
|
|
'darwin': 214, # hmm...need to set to 192 for Leopard?...
|
|
'linux2': 220,
|
|
'win32' : 230}.get(sys.platform,200)
|
|
|
|
options.ext_y = 168 # external gui height (eg. for Tcl/Tk top bar)
|
|
|
|
options.blue_line = 0
|
|
|
|
# Greg Landrum
|
|
options.rpcServer = 0
|
|
# end
|
|
options.security = 1
|
|
|
|
script_re = re.compile(r"pymolrc$|\.pml$|\.PML$|\.p1m$|\.P1M$")
|
|
py_re = re.compile(r"\.py$|\.pym$|\.PY$|\.PYM$")
|
|
|
|
def get_pwg_options(filename):
|
|
for line in open(filename, 'r'):
|
|
a = line.split()
|
|
if not a or a[0].startswith('#'):
|
|
continue
|
|
if a[0].lower() == 'options':
|
|
return a[1:]
|
|
return []
|
|
|
|
def get_personal_folder():
|
|
if sys.platform.startswith('win'):
|
|
try:
|
|
import winreg
|
|
with winreg.OpenKey(winreg.HKEY_CURRENT_USER,
|
|
r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders') as key:
|
|
return winreg.QueryValueEx(key, "Personal")[0]
|
|
except:
|
|
print(' Warning: failed to query "My Documents" from registry')
|
|
return os.path.expanduser('~')
|
|
|
|
def get_user_config():
|
|
for d in [os.getcwd(), '$HOME', '$HOMEDRIVE$HOMEPATH', '$PYMOL_PATH', '{}/pymol'.format(os.environ.get('XDG_CONFIG_HOME', '$HOME/.config'))]:
|
|
d = os.path.expandvars(d)
|
|
for pat in [pymolrc_pat1, pymolrc_pat2]:
|
|
lst = glob.glob(d + os.sep + pat)
|
|
if lst:
|
|
break
|
|
if lst:
|
|
break
|
|
# global run_on_startup script (not overridden by pymolrc files, but is disabled by "-k")
|
|
if "PYMOL_PATH" in os.environ:
|
|
first = glob.glob(os.environ['PYMOL_PATH']+"/"+ros_pat)
|
|
else:
|
|
first = []
|
|
second = []
|
|
for a in lst:
|
|
if py_re.search(a):
|
|
first.append(a) # preceeding "_ " cloaks
|
|
elif script_re.search(a):
|
|
second.append(a) # preceeding "_ " cloaks
|
|
|
|
first.sort()
|
|
second.sort()
|
|
return first+second
|
|
|
|
def parse_args(argv, _pymol=None, options=None, restricted=0):
|
|
if not restricted:
|
|
global _argv
|
|
_argv = copy.deepcopy(argv) # pymol.invocation._argv
|
|
global global_options
|
|
if options is None:
|
|
if _pymol is None:
|
|
options = global_options
|
|
else:
|
|
options = _pymol.invocation.options
|
|
av = copy.deepcopy(argv)
|
|
av = av[1:] # throw out the executable path
|
|
av.reverse()
|
|
once_dict = {}
|
|
options.deferred = []
|
|
final_actions = []
|
|
loaded_something = 0
|
|
python_script = None
|
|
# append user settings file as an option
|
|
pymolrc = get_user_config()
|
|
while 1:
|
|
if not len(av):
|
|
break
|
|
a = av.pop()
|
|
a = re.sub(r'''^"|"$|^'|'$''','',a) # strip extra quotes
|
|
if a[0:1]=='-':
|
|
if (a[1:2]=='-'):
|
|
if a in ('--version', '--help'):
|
|
import pymol
|
|
print(pymol.get_version_message())
|
|
if a == '--help':
|
|
print(helptext1)
|
|
if pymolrc:
|
|
for filename in pymolrc:
|
|
print(' ' + filename)
|
|
else:
|
|
print(' (no pymolrc file found)')
|
|
print(helptext2)
|
|
sys.exit()
|
|
elif a == "--retina":
|
|
print("Warning: --retina option has been removed")
|
|
elif a == "--nospnav":
|
|
print(' Warning: --nospnav not available in Open-Source PyMOL')
|
|
elif a == "--gldebug":
|
|
options.gldebug = 1
|
|
elif a == "--testing":
|
|
options.testing = 1
|
|
elif a == "--diagnostics":
|
|
# same as: -cd diagnostics
|
|
options.no_gui=1
|
|
options.deferred.append("_do_diagnostics")
|
|
else:
|
|
# double hypen signals end of PyMOL arguments
|
|
if python_script is None:
|
|
python_script = argv[0]
|
|
rev_av = copy.deepcopy(av)
|
|
rev_av.reverse()
|
|
if len(a)>2:
|
|
sys.argv = [python_script] + [a] + rev_av
|
|
else:
|
|
sys.argv = [python_script] + rev_av
|
|
break
|
|
continue
|
|
if ("A" in a) or ("a" in a): # application configuration
|
|
new_args = []
|
|
# ====== mode 1 - simple viewer window ======
|
|
if a[2:3] == "1":
|
|
if 'A1' not in once_dict:
|
|
once_dict['A1'] = 1
|
|
new_args = ["-qxiF",
|
|
"-X","68",
|
|
"-Y","100",
|
|
]
|
|
# ====== mode 2 - not available -- clashes with -2 =======
|
|
# ====== mode 3 - internal GUI only no splash ======
|
|
if a[2:3] == "3":
|
|
if 'A3' not in once_dict:
|
|
once_dict['A3'] = 1
|
|
new_args = ["-qx",
|
|
"-X","68",
|
|
"-Y","100",
|
|
]
|
|
# ====== mode 4 - internal GUI only with splash ======
|
|
if a[2:3] == "4": # used by PYMOLVIEWER
|
|
if 'A4' not in once_dict:
|
|
once_dict['A4'] = 1
|
|
new_args = [
|
|
"-X","68",
|
|
"-Y","100",
|
|
]
|
|
# ====== mode 5 - mode 5 helper application ======
|
|
if a[2:3] == "5":
|
|
if 'A5' not in once_dict:
|
|
once_dict['A5'] = 1
|
|
new_args = ["-QxiICUF",
|
|
"-X","68",
|
|
"-Y","100",
|
|
]
|
|
# ====== mode 6 - mode 6 presentation (no GUI) ======
|
|
if a[2:3] == "6":
|
|
if 'A6' not in once_dict:
|
|
once_dict['A6'] = 1
|
|
new_args = ["-qxieICUPF",
|
|
]
|
|
# ===============================================
|
|
new_args.reverse()
|
|
av = av + new_args
|
|
if "1" in a[1:2]:
|
|
options.deferred.append("_do__ config_mouse one_button")
|
|
if "2" in a[1:2]:
|
|
options.deferred.append("_do__ config_mouse two_button")
|
|
if "q" in a:
|
|
options.show_splash = 0
|
|
if "i" in a:
|
|
options.internal_gui = 0
|
|
if "f" in a:
|
|
options.internal_feedback = int(av.pop())
|
|
if "F" in a:
|
|
options.internal_feedback = 0
|
|
if "B" in a:
|
|
options.blue_line = 1
|
|
if "E" in a:
|
|
options.multisample = int(av.pop())
|
|
if "P" in a:
|
|
options.presentation = 1
|
|
if "W" in a:
|
|
options.win_x = int(av.pop())
|
|
options.win_xy_set = True
|
|
if "H" in a:
|
|
options.win_y = int(av.pop())
|
|
options.win_xy_set = True
|
|
if "X" in a:
|
|
options.win_px = int(av.pop())
|
|
if "y" in a:
|
|
options.exit_on_error = 1
|
|
if "Y" in a:
|
|
options.win_py = int(av.pop())
|
|
if "D" in a:
|
|
options.defer_builds_mode = int(av.pop())
|
|
if "v" in a:
|
|
options.openvr_stub = True
|
|
if "V" in a:
|
|
options.ext_y = int(av.pop())
|
|
if "N" in a: # external gui name...
|
|
options.gui = av.pop()
|
|
if "x" in a:
|
|
options.external_gui = 0
|
|
if "n" in a:
|
|
options.incentive_product = 1
|
|
if "t" in a: # type of stereo to use
|
|
options.stereo_mode = int(av.pop())
|
|
if "T" in a: # what skin to use?
|
|
options.skin = str(av.pop())
|
|
if "w" in a: # what gui to use
|
|
options.gui = str(av.pop())
|
|
if "O" in a:
|
|
options.sphere_mode = int(av.pop())
|
|
if "z" in a:
|
|
options.window_visible = 0
|
|
if "Z" in a:
|
|
options.zoom_mode = int(av.pop())
|
|
if options.zoom_mode==5:
|
|
final_actions.append("_do__ zoom")
|
|
if not restricted:
|
|
if "c" in a:
|
|
options.no_gui=1
|
|
options.external_gui=0
|
|
if "m" in a: # mac external GUI
|
|
if options.external_gui == 2:
|
|
options.external_gui = 3
|
|
if options.win_py == 184: # mac external GUI default
|
|
options.win_py = 216
|
|
else:
|
|
options.external_gui = 2
|
|
options.win_py = 184
|
|
|
|
if "e" in a:
|
|
options.full_screen = 1
|
|
if "G" in a: # Game mode (reqd for Mac stereo)
|
|
options.game_mode = 1
|
|
options.win_x = 1024
|
|
options.win_y = 768
|
|
if "S" in a: # Force stereo context on stereo-capable hardware
|
|
options.force_stereo = 1
|
|
if options.stereo_mode == 0:
|
|
options.stereo_mode = 1 # quadbuffer
|
|
if sys.platform=='darwin':
|
|
options.deferred.append(
|
|
"_do__ set stereo_double_pump_mono,1,quiet=1")
|
|
if "M" in a: # Force mono on stereo hardware (all)
|
|
options.force_stereo = -1
|
|
if "j" in a: # Geowall: two side-by-side images
|
|
options.stereo_mode = 4
|
|
options.deferred.append("_do__ stereo on")
|
|
if ("d" in a):
|
|
options.deferred.append(
|
|
"_do_" + av.pop().replace('%',' '))
|
|
if ("J" in a): # cd to user's home directory on startup (if possible)
|
|
path = get_personal_folder()
|
|
try:
|
|
# immediatly chdir (was: options.deferred.append(...))
|
|
os.chdir(path)
|
|
# clear PYMOL_WD, which may be set by MacPyMOL
|
|
os.environ.pop('PYMOL_WD', None)
|
|
except OSError:
|
|
print(" Error: could not chdir to", repr(path))
|
|
if ("l" in a):
|
|
options.deferred.append("_do_spawn %s"%av.pop())
|
|
if ("r" in a):
|
|
options.deferred.append("_do_run %s,main"%av.pop())
|
|
if ("u" in a):
|
|
options.deferred.append("_do_resume %s"%av.pop())
|
|
if ("s" in a):
|
|
options.deferred.append("_do_log_open %s"%av.pop())
|
|
if ("o" in a):
|
|
options.security = 0
|
|
if ("R" in a):
|
|
options.rpcServer = 1
|
|
if ("g" in a):
|
|
filename = av.pop()
|
|
if '.png' in filename:
|
|
options.deferred.append("_do__ cmd.png('''%s''')"%filename)
|
|
elif '.mpg' in filename:
|
|
options.deferred.append("_do__ movie.produce('''%s''')"%filename)
|
|
if ("C" in a):
|
|
options.sigint_handler = 0
|
|
if ("L" in a):
|
|
options.after_load_script = av.pop()
|
|
if ("b" in a): # CPU benchmark
|
|
options.deferred.append("_do__ feedback disable,all,everything")
|
|
options.deferred.append("_do__ feedback enable,python,output")
|
|
options.deferred.append("_do_wizard benchmark")
|
|
if a[2:]=='':
|
|
options.deferred.append("_do__ cmd.get_wizard().run_cpu()")
|
|
if a[2:]=='0':
|
|
options.deferred.append("_do__ cmd.get_wizard().ray_trace0()")
|
|
if a[2:]=='1':
|
|
options.deferred.append("_do__ cmd.get_wizard().ray_trace1()")
|
|
if a[2:]=='2':
|
|
options.deferred.append("_do__ cmd.get_wizard().ray_trace2()")
|
|
|
|
if "p" in a:
|
|
options.read_stdin = 1
|
|
if "K" in a:
|
|
options.keep_thread_alive = 1
|
|
if "k" in a: # suppress reading of .pymolrc and related files
|
|
pymolrc = None
|
|
options.plugins = 0
|
|
if "U" in a: #
|
|
options.reuse_helper = 1
|
|
if "Q" in a:
|
|
options.quiet = 1
|
|
options.show_splash = 0
|
|
if "I" in a:
|
|
options.auto_reinitialize = 1
|
|
if "h" in a: # generic helper application
|
|
options.internal_gui = 0
|
|
options.external_gui = 0
|
|
options.internal_feedback = 0
|
|
options.show_splash = 1
|
|
elif a in ('+1', '+2', '+3', '+4'):
|
|
print('ignoring PyMOLWin.exe argument', a)
|
|
elif not restricted:
|
|
suffix = a[-4:].lower().split('.')[-1]
|
|
if suffix == "p5m":
|
|
# mode 5 helper application
|
|
av.append("-A5")
|
|
elif suffix == "psw":
|
|
# presentation mode
|
|
av.append("-A6")
|
|
elif suffix in [ 'pym' ,'py', 'pyc' ]:
|
|
python_script = a
|
|
elif suffix in [ 'pwg' ]:
|
|
try:
|
|
pwg_options = get_pwg_options(a)
|
|
if pwg_options:
|
|
parse_args(['pymol'] + pwg_options, _pymol, options, 1)
|
|
except:
|
|
traceback.print_exc()
|
|
options.deferred.append(a)
|
|
loaded_something = 1
|
|
if pymolrc is not None:
|
|
options.deferred = [('_do__ @' + a) if script_re.search(a) else a
|
|
for a in pymolrc] + options.deferred
|
|
options.pymolrc = pymolrc
|
|
if options.rpcServer:
|
|
options.deferred.append('_do__ /import pymol.rpc;pymol.rpc.launch_XMLRPC()')
|
|
if options.plugins == 1:
|
|
# Load plugins independent of PMGApp (will not add menu items)
|
|
options.deferred.append('_do__ /import pymol.plugins;pymol.plugins.initialize(-1)')
|
|
if loaded_something and (options.after_load_script!=""):
|
|
options.deferred.append(options.after_load_script)
|
|
options.deferred.extend(final_actions)
|
|
if options.show_splash and not options.no_gui and not restricted:
|
|
options.deferred.insert(0,"_do__ cmd.splash(1)")
|
|
if options.full_screen:
|
|
options.deferred.append("_do__ full_screen on")
|