Source code for schrodinger.trajectory.trajectory_gui_dir.display_settings_manager
from schrodinger import structure
from schrodinger.infra import mm
from schrodinger.structutils import analyze
from schrodinger.trajectory.trajectory_gui_dir.display_settings_data import \
DisplayOnly
from schrodinger.ui import maestro_ui
[docs]class DisplaySettingsManager:
"""
This class makes use of
schrodinger.trajectory.trajectory_gui_dir.display_settings_data.DisplaySettingsData
or schrodinger.trajectory.trajectory_gui_dir.playback_settings_data.PlaybackSettingsData
class objects and generates appropriate asl based display settings.
It also provides ability to get dynamic tooltip based on display settings.
Provides ability to update atoms visibility in the structure based on
display settings.
"""
[docs] def __init__(self, data):
"""
:param data: Display settings
:type data: DisplaySettingsData or PlaybackSettingsData
"""
self.data = data
self._display_atoms_asl_changed = True
self._display_atoms_asl_is_valid = False
# Default is True to indicate that ASL is always dynamic, unless
# we are assured by mmasl_is_dynamic_expression API check.
self._display_atoms_asl_is_dynamic = True
[docs] def honorHideAtomsAsl(self):
"""
Whether to honor 'Hide atoms:' or not.
"""
return not (self.data.display_only and
(self.data.display_only_option == DisplayOnly.CURRENT))
[docs] def getHideAtomsAsl(self):
"""
Returns hide atom asl based on current 'Hide atoms:' settings
"""
if not self.honorHideAtomsAsl():
return None
beyond_asl = self.getHideAtomsBeyondBindingSiteASL()
nonpolar_asl = self.getHideAtomsNonpolarHydrogensASL()
if beyond_asl and nonpolar_asl:
return '(%s OR %s)' % (beyond_asl, nonpolar_asl)
elif beyond_asl:
return beyond_asl
elif nonpolar_asl:
return nonpolar_asl
else:
return None
[docs] def getHideAtomsBeyondBindingSiteASL(self):
"""
Returns hide atoms asl based on 'Beyond binding site' settings
"""
radius = self.data.binding_site_radius
if self.data.ha_beyond_binding_site and self.data.ha_solvents_only:
return '(NOT(fillres within %d (ligand) ) AND (solvent))' % radius
elif self.data.ha_beyond_binding_site:
return '(NOT( fillres within %d ((ligand) ) ))' % radius
else:
return None
[docs] def getHideAtomsNonpolarHydrogensASL(self):
"""
Returns hide atoms asl based on 'Nonpolar hydrogens' settings
"""
if self.data.ha_nonpolar_hydrogens and self.data.ha_protein_only:
return '(( atom.ele H and /C0-H0/ ) AND (( backbone ) OR ( sidechain ) ))'
elif self.data.ha_nonpolar_hydrogens:
return '( atom.ele H and /C0-H0/ )'
else:
return None
[docs] def honorMatchingAtomsAsl(self):
"""
Whether to honor 'Atoms matching ASL definition:' option
:rtype: bool
"""
return self.data.display_only and (self.data.display_only_option
== DisplayOnly.MATCHING)
[docs] def getMatchingAtomsAsl(self):
"""
Returns matching atom asl based on 'Display only:'
:rtype: str or None
"""
if self.honorMatchingAtomsAsl():
return self.data.matching_asl
[docs] def getDisplayAtomsAsl(self):
"""
Returns display atom asl based on 'Hide atoms:' & 'Display only:'
settings
:rtype: str or None
"""
matching_asl = self.getMatchingAtomsAsl()
hide_asl = self.getHideAtomsAsl()
if hide_asl is None:
return matching_asl
display_asl = '(NOT (%s))' % hide_asl
if matching_asl is None:
return display_asl
return '((%s) AND (%s))' % (matching_asl, display_asl)
[docs] def applyShowHideAtomsAsl(self, st: structure.Structure,
varying_atoms_frame: bool):
"""
Display or hide atoms in the st based on stored atoms asl.
ASL acts as display only asl if display_only is set, otherwise
acts as hide specified atoms.
:param varying_atoms_frame: True if method is called for varying atoms
frame.
:param st : The structure to be updated.
"""
display_atoms_asl_changed = self._display_atoms_asl_changed
# Optimization trick to ensure that we don't reevaluate and apply asl if
# there is no change in the asl.
self._display_atoms_asl_changed = False
if not self._display_atoms_asl_is_valid:
return
# Visibility does not depend on atom coordinate.
# If ASL did not change, so set of visible atoms should not have changed
# since the last call of this function.
# This check is intended for optimization purpose to avoid evaluating
# and applying asl for each frame.
if (not self.needVisibilityUpdate(varying_atoms_frame) and
(not display_atoms_asl_changed)):
return
display_only = self.data.display_only
visible = display_only
if display_only:
asl = self.getDisplayAtomsAsl()
else:
asl = self.getHideAtomsAsl()
# If user selected currently displayed atoms option, then returned ASL
# is None.
if asl:
self.applyVisibilityAsl(st, asl, display_only, visible)
[docs] def applyVisibilityAsl(self, st: structure.Structure, asl: str,
display_only: bool, visible: bool):
"""
Apply visibility asl according to evaluated asl on structure.
:param st: Structure to be updated.
:param asl: ASL to be evaluated for this structure.
:param visible: Visibility value of atoms matching the asl.
"""
maestro_ui.update_atoms_visibility_by_asl(st.handle, asl, display_only,
visible)
[docs] def setDisplayAtomsASL(self):
"""
Set matching atoms asl. This ASL acts as display only
asl if Display Only turned on. Otherwise acts as hide specified atoms.
"""
display_only = self.data.display_only
if display_only:
asl = self.getDisplayAtomsAsl()
else:
asl = self.getHideAtomsAsl()
self._display_atoms_asl_changed = True
self._display_atoms_asl_is_valid = False
# Default is True to indicate that ASL is always dynamic, unless
# we are assured by mmasl_is_dynamic_expression API check.
self._display_atoms_asl_is_dynamic = asl is not None
if asl:
self._display_atoms_asl_is_valid = analyze.validate_asl(asl)
self._display_atoms_asl_is_dynamic = (
self._display_atoms_asl_is_valid and
mm.mmasl_is_dynamic_expression(asl) == mm.TRUE)
[docs] def shouldUpdateVisibility(self, varying_atoms_frame: bool):
"""
Check if visibility should be updated or not. Applicable in both
restoring original visibility and apply asl based visibility.
:param varying_atoms_frame: True if method is called for varying atoms
frame.
:rtype: bool
:return: True if visibility should be updated.
"""
# If ASL is dynamic, we have to evaluate ASL every time because distance
# can vary between atoms frame to frame.
# If varying atoms frame, we have to restore because new atoms might
# have been added.
return self._display_atoms_asl_is_dynamic or varying_atoms_frame
[docs] def shouldRestoreVisibility(self, varying_atoms_frame: bool):
"""
Determine if frame visibility should be restored or not.
:param varying_atoms_frame: True if method is called for varying atoms
frame.
:rtype: bool
:return: True if visibility should be restored.
"""
# If asl changed, we have to restore to start from scratch.
return (self._display_atoms_asl_changed or
self.shouldUpdateVisibility(varying_atoms_frame))
[docs] def needVisibilityUpdate(self, varying_atoms_frame: bool):
"""
Determine if frame visibility should be updated or not.
:param varying_atoms_frame: True if method is called for varying atoms
frame.
:rtype: bool
:return: True if visibility should be updated.
"""
return (self._display_atoms_asl_is_valid and
self.shouldUpdateVisibility(varying_atoms_frame))
[docs] def restoreDefaultVisibility(self, ref_st: structure.Structure,
frame_st: structure.Structure):
"""
Set ref_st atoms visibility in the frame_st.
:param ref_st: Reference structure to be used to update frame structure.
:param frame_st: Frame structure to be updated.
"""
ref_st_atom_total = ref_st.atom_total
frame_st_atom_total = frame_st.atom_total
maestro_ui.clone_atoms_visibility(ref_st.handle, frame_st.handle)