Files
PlantAI-dev/tools/pymol-open-source/modules/pymol/setting.py
T
2026-08-03 18:42:47 +08:00

568 lines
17 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* -------------------------------------------------------------------
# must match layer1/Setting.h
cSetting_tuple = -1
cSetting_blank = 0
cSetting_boolean = 1
cSetting_int = 2
cSetting_float = 3
cSetting_float3 = 4
cSetting_color = 5
cSetting_string = 6
if True:
import traceback
from . import selector
from .shortcut import Shortcut
cmd = __import__("sys").modules["pymol.cmd"]
from .cmd import _cmd,lock,lock_attempt,unlock,QuietException, \
is_string, \
_feedback,fb_module,fb_mask, \
DEFAULT_ERROR, DEFAULT_SUCCESS, _raising, is_ok, is_error
# name -> index mapping
index_dict = _cmd.get_setting_indices()
# index -> name mapping
name_dict = dict((v,k) for (k,v) in index_dict.items())
name_list = list(index_dict.keys())
setting_sc = Shortcut(name_list)
# legacy
index_dict['ray_shadows'] = index_dict['ray_shadow']
boolean_dict = {
"true" : 1,
"false": 0,
"on" : 1,
"off" : 0,
"1" : 1,
"0" : 0,
"1.0" : 1,
"0.0" : 0,
}
boolean_sc = Shortcut(boolean_dict.keys())
def _get_index(name):
'''Get setting index for given name. `name` may be abbreviated.
Raises QuietException for unknown names or ambiguous abbreviations.'''
if isinstance(name, int) or name.isdigit():
return int(name)
if name not in index_dict:
name = setting_sc.auto_err(name, 'Setting')
return index_dict[name]
def _get_name(index):
# legacy, in case someone used that in a script
return name_dict.get(index, "")
def get_index_list():
# legacy, in case someone used that in a script (e.g. grepset)
return list(name_dict.keys())
def get_name_list():
return name_list
def _validate_value(type, value):
if type == cSetting_boolean: # (also support non-zero float for truth)
try: # number, non-zero, then interpret as TRUE
return 1 if float(value) else 0
except:
pass
return boolean_dict[boolean_sc.auto_err(str(value), "boolean")]
if type in (cSetting_int, cSetting_float):
if is_string(value) and boolean_sc.has_key(value):
value = boolean_dict[boolean_sc.auto_err(str(value), "boolean")]
if type == cSetting_int:
return int(value)
return float(value)
if type == cSetting_float3: # some legacy handling req.
if not is_string(value):
v = value
elif ',' in value:
v = cmd.safe_eval(value)
else:
v = value.split()
return (float(v[0]), float(v[1]), float(v[2]))
if type == cSetting_color:
return str(value)
if type == cSetting_string:
v = str(value)
# strip outermost quotes (cheesy approach)
if len(v) > 1 and v[0] == v[-1] and v[0] in ('"', "'"):
v = v[1:-1]
return v
raise Exception
###### API functions
def set_bond(name, value, selection1, selection2=None,
state=0, updates=1, log=0, quiet=1, _self=cmd):
'''
DESCRIPTION
"set_bond" changes per-bond settings for all bonds which exist
between two selections of atoms.
USAGE
set_bond name, value, selection1 [, selection2 ]
ARGUMENTS
name = string: name of the setting
value = string: new value to use
selection1 = string: first set of atoms
selection2 = string: seconds set of atoms {default: (selection1)}
EXAMPLE
set_bond stick_transparency, 0.7, */n+c+ca+o
NOTES
The following per-bond settings are currently implemented. Others
may seem to be recognized but will currently have no effect when
set at the per-bond level.
* valence
* line_width
* line_color
* stick_radius
* stick_color
* stick_transparency
Note that if you attempt to use the "set" command with a per-bond
setting over a selection of atoms, the setting change will appear
to take, but no change will be observed.
PYMOL API
cmd.set_bond ( string name, string value,
string selection1,
string selection2,
int state, int updates, log=0, quiet=1)
'''
selection1 = selector.process(selection1)
selection2 = selector.process(selection2) if selection2 else selection1
index = _get_index(str(name))
type = _cmd.get_setting_type(index)
v = (type, _validate_value(type, value))
if log:
name = name_dict.get(index, name)
_self.log(
'',
f"cmd.set_bond({name!r},{value!r},{selection1!r},{selection2!r},{state})\n"
)
with _self.lockcm:
r = _cmd.set_bond(_self._COb, index, v, selection1, selection2,
int(state) - 1, int(quiet), int(updates))
return r
def set(name, value=1, selection='', state=0, updates=1, log=0,
quiet=1,_self=cmd):
'''
DESCRIPTION
"set" changes global, object, object-state, or per-atom settings.
USAGE
set name [,value [,selection [,state ]]]
ARGUMENTS
name = string: setting name
value = string: a setting value {default: 1}
selection = string: name-pattern or selection-expression
{default:'' (global)}
state = a state number {default: 0 (per-object setting)}
EXAMPLES
set orthoscopic
set line_width, 3
set surface_color, white, 1hpv
set sphere_scale, 0.5, elem C
NOTES
The default behavior (with a blank selection) is global. If the
selection is "all", then the setting entry in each individual
object will be changed. Likewise, for a given object, if state is
zero, then the object setting will be modified. Otherwise, the
setting for the indicated state within the object will be
modified.
If a selection is provided as opposed to an object name, then the
atomic setting entries are modified.
The following per-atom settings are currently implemented. Others
may seem to be recognized but will have no effect when set on a
per-atom basis.
* sphere_color
* surface_color
* mesh_color
* label_color
* dot_color
* cartoon_color
* ribbon_color
* transparency (for surfaces)
* sphere_transparency
Note that if you attempt to use the "set" command with a per-bond
setting over a selection of atoms, the setting change will appear
to take, but no change will be observed. Please use the
"set_bond" command for per-bond settings.
PYMOL API
cmd.set(string name, string value, string selection, int state,
int updates, int quiet)
SEE ALSO
get, set_bond
'''
selection = selector.process(selection)
index = _get_index(name)
type = _cmd.get_setting_type(index)
v = (type, _validate_value(type, value))
if log:
name = name_dict.get(index, name)
_self.log('',
f"cmd.set({name!r},{value!r},{selection!r},{state})\n")
with _self.lockcm:
r = _cmd.set(_self._COb, index, v, selection,
int(state) - 1, int(quiet), int(updates))
return r
def unset(name, selection='', state=0, updates=1, log=0, quiet=1, _self=cmd):
'''
DESCRIPTION
"unset" clears a setting and restores its default value.
WARNING: The behavior for global settings changed in PyMOL 2.5.
Previously, "unset settingname" would set the global value of
"settingname" to zero/off instead of the default value.
To set a setting to zero, do "set settingname, 0".
USAGE
unset name [,selection [,state ]]
EXAMPLE
unset orthoscopic
unset surface_color, 1hpv
unset sphere_scale, elem C
NOTES
If selection is not provided, unset changes the named global
setting to its default value.
If a selection is provided, then "unset" undefines per-object,
per-state, or per-atom settings.
PYMOL API
cmd.unset(string name, string selection, int state, int updates,
int log)
SEE ALSO
unset_deep, set, set_bond
'''
selection = selector.process(selection)
index = _get_index(str(name))
if log:
name = name_dict.get(index, name)
_self.log('', f"cmd.unset({name!r},{selection!r},{state})\n")
with _self.lockcm:
r = _cmd.unset(_self._COb, index, selection,
int(state) - 1, int(quiet), int(updates))
return r
def unset_bond(name,selection1,selection2=None,state=0,updates=1,log=0,quiet=1,_self=cmd):
'''
DESCRIPTION
"unset_bond" removes a per-bond setting for a given set of bonds.
USAGE
unset name [,selection [, selection [,state ]]]
'''
selection1 = selector.process(selection1)
selection2 = selector.process(selection2) if selection2 else selection1
index = _get_index(str(name))
if log:
name = name_dict.get(index, name)
_self.log(
'',
f"cmd.unset_bond({name!r},{selection1!r},{selection2!r},{state})\n"
)
with _self.lockcm:
r = _cmd.unset_bond(_self._COb,int(index),selection1,selection2,
int(state)-1,int(quiet),
int(updates))
return r
def get_setting(name,object='',state=0,_self=cmd): # INTERNAL
return get_setting_tuple_new(name, object, state, _self)[1]
def get(name, selection='', state=0, quiet=1, _self=cmd):
'''
DESCRIPTION
"get" prints out the current value of a setting.
USAGE
get name [, selection [, state ]]
EXAMPLE
get line_width
ARGUMENTS
name = string: setting name
selection = string: object name (selections not yet supported)
state = integer: state number
NOTES
"get" currently only works with global, per-object, and per-state
settings. Atom level settings get be queried with "iterate" (e.g.
iterate all, print s.line_width)
PYMOL API
cmd.get(string name, string object, int state, int quiet)
SEE ALSO
set, set_bond, get_bond
'''
state = int(state)
i = _get_index(name)
r = get_setting_text(i, str(selection), state, _self)
if is_ok(r) and (r is not None):
if not int(quiet):
name = name_dict.get(i, name)
r_str = str(r)
if len(r_str) > 200:
r_str = r_str[:185] + '... (truncated)'
if(selection==''):
print(" get: %s = %s"%(name,r_str))
elif state<=0:
print(" get: %s = %s in object %s"%(name,r_str,selection))
else:
print(" get: %s = %s in object %s state %d"%(name,r_str,selection,state))
return r
def get_setting_tuple_new(name,object='',state=0,_self=cmd): # INTERNAL
i = _get_index(name)
with _self.lockcm:
return _cmd.get_setting_of_type(_self._COb, i, str(object), int(state) - 1, cSetting_tuple)
def get_setting_tuple(name,object='',state=0,_self=cmd): # INTERNAL
r = get_setting_tuple_new(name, object, state, _self)
if r[0] != cSetting_float3:
# legacy API
r = (r[0], (r[1],))
return r
def get_setting_boolean(name,object='',state=0,_self=cmd): # INTERNAL
i = _get_index(name)
with _self.lockcm:
return _cmd.get_setting_of_type(_self._COb, i, str(object), int(state) - 1, cSetting_boolean)
def get_setting_int(name,object='',state=0,_self=cmd): # INTERNAL
i = _get_index(name)
with _self.lockcm:
return _cmd.get_setting_of_type(_self._COb, i, str(object), int(state) - 1, cSetting_int)
def get_setting_float(name,object='',state=0,_self=cmd): # INTERNAL
i = _get_index(name)
with _self.lockcm:
return _cmd.get_setting_of_type(_self._COb, i, str(object), int(state) - 1, cSetting_float)
def get_setting_text(name,object='',state=0,_self=cmd): # INTERNAL
i = _get_index(name)
with _self.lockcm:
return _cmd.get_setting_of_type(_self._COb, i, str(object), int(state) - 1, cSetting_string)
def get_setting_updates(object='', state=0, _self=cmd): # INTERNAL
r = []
if lock_attempt(_self):
try:
r = _cmd.get_setting_updates(_self._COb, object, state-1)
finally:
_self.unlock(r,_self)
return r
def get_bond(name, selection1, selection2=None,
state=0, updates=1, quiet=1, _self=cmd):
'''
DESCRIPTION
"get_bond" gets per-bond settings for all bonds which exist
between two selections of atoms.
USAGE
get_bond name, selection1 [, selection2 ]
ARGUMENTS
name = string: name of the setting
selection1 = string: first set of atoms
selection2 = string: seconds set of atoms {default: (selection1)}
EXAMPLE
get_bond stick_transparency, */n+c+ca+o
NOTES
The following per-bond settings are currently implemented. Others
may seem to be recognized but will currently have no effect when
set at the per-bond level.
* valence
* line_width
* line_color
* stick_radius
* stick_color
* stick_transparency
PYMOL API
cmd.get_bond ( string name,
string selection1,
string selection2,
int state, int updates, quiet=1)
'''
state, quiet = int(state), int(quiet)
selection1 = selector.process(selection1)
selection2 = selector.process(selection2) if selection2 else selection1
index = _get_index(str(name))
with _self.lockcm:
r = _cmd.get_bond(_self._COb, index, selection1, selection2,
state - 1, quiet, int(updates))
if not quiet:
name = name_dict.get(index, name)
suffix = ' state %d' % state if state > 0 else ''
for model, vlist in r:
print(' %s = %s for object %s' % (name, _self.get(name, model), model))
for idx1, idx2, value in vlist:
if value is None:
continue
print(' %s = %s between (%s`%d)-(%s`%d%s)' % (name,
value, model, idx1, model, idx2, suffix))
return r
def unset_deep(settings='', object='*', updates=1, quiet=1, _self=cmd):
'''
DESCRIPTION
Unset all object, object-state, atom, and bond level settings.
Note: Does currently NOT unset atom-state level settings. Check for
atom-state level settings with:
PyMOL> iterate_state 1, *, print(list(s))
Unset e.g. atom-state level "label_screen_point" (index 728) with:
PyMOL> alter_state 1, *, del s[728]
ARGUMENTS
settings = str: space separated list of setting names or empty string
for all settings {default: }
object = str: name of one object or * for all objects {default: *}
'''
quiet = int(quiet)
kwargs = {'quiet': quiet, 'updates': 0, '_self': _self}
if not settings:
settings = iter(name_dict) # index iterator
elif _self.is_string(settings):
settings = settings.split()
if object in ['all', '*']:
object = '*'
selection = '(*)'
else:
selection = None
try:
if _self.get_type(object) in (
'object:group', 'object:molecule'):
selection = '(' + object + ')'
except:
pass
# 0 (object-level) and 1-N (object-state-level)
states = range(_self.count_states(object) + 1)
for setting in settings:
try:
for state in states:
unset(setting, object, state=state, **kwargs)
if selection:
unset(setting, selection, **kwargs)
except:
if not quiet:
print(' Setting: %s unset failed' % setting)
if int(updates):
_self.rebuild(object)