Source code for schrodinger.trajectory.trajectory_gui_dir.playback_settings

from enum import Enum

from schrodinger.Qt import QtCore
from schrodinger.Qt import QtGui
from schrodinger.Qt import QtWidgets
from schrodinger.trajectory.trajectory_gui_dir import advanced_settings
from schrodinger.trajectory.trajectory_gui_dir import display_settings_manager
from schrodinger.trajectory.trajectory_gui_dir.display_settings_data import \
    DisplayOnly
from schrodinger.trajectory.trajectory_gui_dir.playback_settings_data import \
    AVPAslOption
from schrodinger.trajectory.trajectory_gui_dir.playback_settings_data import \
    Direction
from schrodinger.trajectory.trajectory_gui_dir.playback_settings_data import \
    Loop
from schrodinger.ui import maestro_ui
from schrodinger.ui.qt import atomselector

from . import playback_settings_ui
from . import stylesheet


[docs]class Tab(Enum): """ Enums for Playback Setting tabs """ BASIC = 0 VIEWPOSITION = 1 ADVANCED = 2
[docs]class FrameIntValidator(QtGui.QIntValidator): """ Frame integer validator to fixup invalid input. """
[docs] def __init__(self, minimum, maximum, parent, default): """ :param default: Default value to be set when invalid value is encountered. :type default: int See PyQt documentation for other argument documentation. """ super().__init__(minimum, maximum, parent) self._default = default
[docs] def fixup(self, text): """ If the frame integer input is not acceptable (e.g. empty value), then replace it with default value. See PyQt documentation for argument documentation. """ return str(self._default)
[docs]class PlaybackSettings(QtWidgets.QWidget): """ Playback settings class for trajectory viewer :cvar closed: A signal emitted when the PlaybackSettings is closed/hidden. :vartype closed: `QtCore.pyqtSignal` :cvar frameDurationChanged: A signal emitted when frame duration changes. - Changed 'Speed' value :vartype frameDurationChanged: `QtCore.pyqtSignal` :cvar stepChanged: A signal emitted when 'Step' changes. - Changed 'Step' value :vartype stepChanged: `QtCore.pyqtSignal` :cvar smoothingChanged: A signal emitted when 'Smoothing' changes. - Changed 'Smoothing' value :vartype smoothingChanged: `QtCore.pyqtSignal` :cvar playDirectionChanged: A signal emitted when 'Play Direction' changes. - Changed 'Play Direction' value :vartype playDirectionChanged: `QtCore.pyqtSignal` :cvar playDirectionChanged: A signal emitted when 'Play Direction' changes. - Changed 'Play Direction' value :vartype playDirectionChanged: `QtCore.pyqtSignal` :cvar loopChanged: A signal emitted when 'Loop' changes. - Changed 'Loop' value :vartype loopChanged: `QtCore.pyqtSignal` :cvar beyondBindingSiteChanged: A signal emitted when 'Hide atoms' 'Beyond Binding Site' changes. - Changed 'Beyond Binding Site' value :vartype beyondBindingSiteChanged: `QtCore.pyqtSignal` :cvar solventsOnlyChanged: A signal emitted when 'Hide atoms' 'Solvents Only' changes. - Changed 'Solvents Only' value :vartype solventsOnlyChanged: `QtCore.pyqtSignal` :cvar nonpolarHydrogensChanged: A signal emitted when 'Hide atoms' 'Nonpolar Hydrogens' changes. - Changed 'Nonpolar Hydrogens' value :vartype nonpolarHydrogensChanged: `QtCore.pyqtSignal` :cvar proteinOnlyChanged: A signal emitted when 'Hide atoms' 'Protein Only' changes. - Changed 'Protein Only' value :vartype proteinOnlyChanged: `QtCore.pyqtSignal` :cvar viewPositioningChanged: A signal emitted when 'View Position' settings change. :vartype viewPositioningChanged: `QtCore.pyqtSignal` :cvar translateToFirstUnitCellChanged: A signal emitted when 'Translate to first unit cell' setting changes. :vartype translateToFirstUnitCellChanged: `QtCore.pyqtSignal` :cvar allSettingsChanged: A signal emitted when settings are reset. :vartype allSettingsChanged: `QtCore.pyqtSignal` :cvar aboutToShowAdvancedSettings(): A signal emitted before showing AdvancedSettings dialog. :vartype aboutToShowAdvancedSettings: `QtCore.pyqtSignal` :cvar advancedSettingsDismissed(): A signal emitted after dismissing AdvancedSettings dialog. :vartype advancedSettingsDismissed: `QtCore.pyqtSignal` :cvar advancedSettingsChanged(): A signal emitted when advanced settings are changed. :vartype advancedSettingsChanged: `QtCore.pyqtSignal` """ closed = QtCore.pyqtSignal() frameDurationChanged = QtCore.pyqtSignal(float) stepChanged = QtCore.pyqtSignal(int) smoothingChanged = QtCore.pyqtSignal(int) playDirectionChanged = QtCore.pyqtSignal(Direction) loopChanged = QtCore.pyqtSignal(Loop) beyondBindingSiteChanged = QtCore.pyqtSignal(bool) solventsOnlyChanged = QtCore.pyqtSignal(bool) nonpolarHydrogensChanged = QtCore.pyqtSignal(bool) proteinOnlyChanged = QtCore.pyqtSignal(bool) translateToFirstUnitCellChanged = QtCore.pyqtSignal() viewPositioningChanged = QtCore.pyqtSignal() allSettingsChanged = QtCore.pyqtSignal() aboutToShowAdvancedSettings = QtCore.pyqtSignal() advancedSettingsDismissed = QtCore.pyqtSignal() advancedSettingsChanged = QtCore.pyqtSignal() FRAME_DURATION_STEP = 0.299 HIDE_ATOM_WIDGETS = ('hideatoms_label', 'beyond_checkbox', 'solvents_only_button', 'nonpolar_checkbox', 'protein_only_button')
[docs] def __init__(self, matsci_profile=False, parent=None): """ :param matsci_profile: A flag indicating if it is a matsci profile. It is used to configure default setting in the playback setting data and ui. :type matsci_profile: bool :param parent: The Qt parent :type parent: QWidget """ super(PlaybackSettings, self).__init__(parent) self.ui = playback_settings_ui.Ui_Form() self.ui.setupUi(self) self.setStyleSheet(stylesheet.PLAYBACK_SETTINGS_STYLESHEET) self.setWindowFlags(QtCore.Qt.Popup | QtCore.Qt.FramelessWindowHint) self.ui.settings_tabwidget.tabBarClicked.connect(self.tabBarClicked) self.matsci_profile = matsci_profile self.setupBasicTab() self.setupViewPositionTab() # Connect to 'Basic' GUI components to update data self.connectToBasicTabForUpdates() # Connect to 'View Position' GUI components to update data self.connectToViewPositionTabForUpdates() # Create AdvancedSettings dialog self.advanced_settings_dlg = advanced_settings.AdvancedSettings( self.matsci_profile, None) self.advanced_settings_dlg.advancedSettingsChanged.connect( self._handleAdvancedSettingsChange) self.advanced_settings_dlg.advancedSettingsDismissed.connect( self.advancedSettingsDismissed) self.adjustSize() self.showing_first_time = True self.data = None self.ui.step_spinbox.setToolTip( "Set the step size to define frame sampling \n(e.g., 1 shows all frames; 10 shows every 10th)" ) self.ui.smoothing_spinbox.setToolTip( "Specify number of frames to use in smoothing calculations") self.ui.translate_to_first_unit_cell.setToolTip( "Translate structures to remain within the unit cell of the first frame" ) self.ws_hub = maestro_ui.WorkspaceHub.instance()
[docs] def setPlaybackSettingsData(self, settings_data, has_pbsettings_data, fsys_atom_total=0): """ Set the playback settings data to the current entry trajectory. If the entry trajectory has saved placback settings, the same will be used to show in UI. Otherwise, populate the latest values from UI and override the values in settings_data :param settings_data: Playback settings data stored in PlaybackSettings object :type settings_data: PlaybackSettingsData Object :param has_pbsettings_data: True if the current entry trajectory has saved playback setings data :type has_pbsettings_data: bool :param fsys_atom_total: Total number of atoms in the system :type fsys_atom_total: int """ # Create PlaybackSettingsData for the given entry self.data = settings_data if not has_pbsettings_data and not self.showing_first_time: # Updates basic tab settings self.updateBasicDataFromUI() # Update 'Hide Atoms' settings self.updateHideAtomsDataFromUI() # Update View Position settings self.updateViewPositionDataFromUI() self.display_settings_manager = display_settings_manager.DisplaySettingsManager( self.data) # Populate 'Basic' GUI with data self.updateBasicTab() # Populate 'View Position' GUI with data self.updateViewPositionTab() # Set validator for reference frame self.setRefFrameValidator() # Advanced settings self.advanced_settings_dlg.setPlaybackSettingsData( self.data, has_pbsettings_data, fsys_atom_total) self.current_tab = Tab.BASIC
[docs] def updateBasicDataFromUI(self): """ Update the basic tab related data from UI """ if self.data is None: return self.data.frame_duration = self.recent_frame_duration self.data.step = self.ui.step_spinbox.value() self.data.smoothing = self.ui.smoothing_spinbox.value() self.data.direction = Direction.BACKWARD if self.ui.play_button.isChecked( ) else Direction.FORWARD if self.ui.single_button.isChecked(): self.data.loop = Loop.SINGLE elif self.ui.oscilate_button.isChecked(): self.data.loop = Loop.OSCILLATE elif self.ui.off_button.isChecked(): self.data.loop = Loop.NONE
[docs] def updateHideAtomsDataFromUI(self): """ Update the hide atoms related data from UI """ if self.data is None: return self.data.ha_beyond_binding_site = self.ui.beyond_checkbox.checkState( ) == QtCore.Qt.Checked self.data.ha_solvents_only = self.ui.solvents_only_button.isChecked() self.data.ha_nonpolar_hydrogens = self.ui.nonpolar_checkbox.checkState( ) == QtCore.Qt.Checked self.data.ha_protein_only = self.ui.protein_only_button.isChecked()
[docs] def updateViewPositionDataFromUI(self): """ Update the view position related data from UI """ if self.data is None: return self.data.adjust_view_position = self.ui.adjust_checkbox.checkState( ) == QtCore.Qt.Checked self.ui.atomselector_widget.setEnabled(self.data.adjust_view_position) self.data.avp_align_on_frame = self.ui.align_radiobutton.isChecked() self.data.avp_center_molecules = not self.data.avp_align_on_frame try: self.data.avp_ref_frame = int(self.ui.frame_lineedit.text()) except ValueError: self.data.avp_ref_frame = 1 self.data.avp_asl_option = AVPAslOption( self.ui.asl_combobox.currentIndex()) self.data.avp_asl = self.getAVPAsl() self.data.translate_to_first_unit_cell = self.ui.translate_to_first_unit_cell.isChecked( )
[docs] def setupBasicTab(self): """ Setup 'Basic' Tab e.g: tooltips, visibility, enable state, etc """ self.ui.reset_button.setToolTip( "Reset all Playback Settings options to defaults") self.ui.beyond_checkbox.toggled.connect( self.ui.solvents_only_button.setVisible) self.ui.solvents_only_button.setVisible(False) self.ui.nonpolar_checkbox.toggled.connect( self.ui.protein_only_button.setVisible) self.ui.protein_only_button.setVisible(False) # Hide hideatoms ui in the matsci profile. self.ui.hideatoms_widget.setVisible(not self.matsci_profile)
[docs] def setupViewPositionTab(self): """ Setup 'View Position' Tab e.g: tooltips, visibility, enable state, etc """ self.atom_selector = atomselector.AtomSelector(self, show_pick=False, show_selection=False, show_plus=True) self.atom_selector.setDarkStyle() self.atom_selector.main_layout.setContentsMargins(2, 2, 2, 2) layout = self.ui.atomselector_widget.layout() layout.insertWidget(0, self.atom_selector) self.ui.load_sel_pushbutton.clicked.connect( self.atom_selector.loadWorkspaceSelection) self.atom_selector.atomSelectionDialogDismissed.connect(self.show) self.ui.adjust_checkbox.toggled.connect( self.ui.align_radiobutton.setEnabled) self.ui.adjust_checkbox.toggled.connect( self.ui.center_radiobutton.setEnabled) self.ui.adjust_checkbox.toggled.connect(self.ui.asl_label.setEnabled) self.ui.adjust_checkbox.toggled.connect(self.ui.align_frame.setEnabled) self.ui.adjust_checkbox.toggled.connect(self.ui.asl_combobox.setEnabled) self.ui.adjust_checkbox.toggled.connect( self.ui.atomselector_widget.setEnabled) self.updateAdjustPositionCheckBox(True) self.updateTranslateToFirstUnitCellCheckBox(False) self.ui.align_radiobutton.toggled.connect( self.ui.frame_lineedit.setEnabled) self.ui.align_radiobutton.setChecked(True) self.ui.atomselector_widget.setVisible(False)
[docs] def updateBasicTab(self): """ Updates 'Basic' Tab with data """ self.updateSpeedIcons() self.ui.step_spinbox.setValue(self.data.step) self.ui.step_spinbox.setMaximum(self.data.getMaxStep()) self.ui.smoothing_spinbox.setValue(self.data.smoothing) self.ui.play_button.setChecked( self.data.direction == Direction.BACKWARD) self.updatePlayDirectionToolTip() self.ui.single_button.setChecked(self.data.loop == Loop.SINGLE) self.ui.oscilate_button.setChecked(self.data.loop == Loop.OSCILLATE) self.ui.off_button.setChecked(self.data.loop == Loop.NONE) self.updateHideAtoms() self.updateLoopTooltip()
[docs] def updateHideAtoms(self): """ Updates 'Hide atoms:'. In the matsci profile, ui itself is not displayed, so it is a no-op. """ if self.matsci_profile: return # Enable Hide atoms if hide atoms asl has to be honored honor_hideatoms_asl = self.honorHideAtomsAsl() self.ui.hideatoms_widget.setEnabled(honor_hideatoms_asl) if not honor_hideatoms_asl: self.data.ha_beyond_binding_site = False self.data.ha_solvents_only = False self.data.ha_nonpolar_hydrogens = False self.data.ha_protein_only = False self.ui.beyond_checkbox.setChecked(self.data.ha_beyond_binding_site) self.ui.solvents_only_button.setChecked(self.data.ha_solvents_only) self.ui.nonpolar_checkbox.setChecked(self.data.ha_nonpolar_hydrogens) self.ui.protein_only_button.setChecked(self.data.ha_protein_only) self.updateBindingSiteTooltip(self.data.ha_beyond_binding_site) self.updateSolventsTooltip(self.data.ha_solvents_only) self.updateNonpolarHydrogensTooltip(self.data.ha_nonpolar_hydrogens) self.updateProteinTooltip(self.data.ha_protein_only)
[docs] def connectToBasicTabForUpdates(self): """ Connect to Baisc Tab GUI components to update data and emit appropriate signals """ self.ui.reset_button.clicked.connect(self.resetSettings) self.ui.minus_button.clicked.connect(self.decreaseSpeed) self.ui.plus_button.clicked.connect(self.increaseSpeed) self.ui.step_spinbox.valueChanged.connect(self.updateStep) self.ui.smoothing_spinbox.valueChanged.connect(self.updateSmoothing) self.ui.play_button.toggled.connect(self.updatePlayDirection) self.ui.loop_buttongroup.buttonToggled.connect(self.updateLoop) self.ui.beyond_checkbox.toggled.connect(self.updateBeyondBindingSite) self.ui.solvents_only_button.toggled.connect(self.updateSolventsOnly) self.ui.nonpolar_checkbox.toggled.connect(self.updateNonpolarHydrogens) self.ui.protein_only_button.toggled.connect(self.updateProteinOnly)
[docs] def updateViewPositionTab(self): """ Updates 'View Position' Tab with data """ self.updateAdjustPositionCheckBox(self.data.adjust_view_position) self.ui.align_radiobutton.setChecked(self.data.avp_align_on_frame) self.ui.frame_lineedit.setText(str(self.data.avp_ref_frame)) self.ui.center_radiobutton.setChecked(self.data.avp_center_molecules) self.ui.asl_combobox.setCurrentIndex(self.data.avp_asl_option.value) self.ui.atomselector_widget.setVisible( self.data.avp_asl_option == AVPAslOption.CUSTOM_SELECTION) self.updateAVPAslOptionLabel() self.atom_selector.setAsl(self.data.avp_asl) self.updateTranslateToFirstUnitCellCheckBox( self.data.translate_to_first_unit_cell)
[docs] def updateTranslateToFirstUnitCellCheckBox(self, checked: bool): """ Update Translate to first unit cell check box state. :param checked: State to be set. """ self.ui.translate_to_first_unit_cell.setChecked(checked)
[docs] def updateAdjustPositionCheckBox(self, checked): """ Udate adjust positioning check box state. :param checked: State to be set. :type checked: bool """ self.ui.adjust_checkbox.setChecked(checked)
[docs] def connectToViewPositionTabForUpdates(self): """ Connect to View Position Tab GUI components to update data and emit appropriate signals """ self.ui.adjust_checkbox.toggled.connect( self.updateAdjustViewPositioning) self.ui.translate_to_first_unit_cell.toggled.connect( self.updateTranslateToFirstUnitCellPosition) self.ui.avp_buttongroup.buttonToggled.connect(self.updateAVPOption) self.ui.frame_lineedit.editingFinished.connect(self.updateRefFrame) self.ui.asl_combobox.currentIndexChanged.connect( self.updateAVPAslOption) self.atom_selector.aslModified.connect(self.updateAVPAsl)
[docs] def setRefFrameValidator(self): """ Sets reference frame validator according to total frame """ self.ui.frame_lineedit.setValidator( FrameIntValidator(1, self.data.frame_total, self, self.data.MIN_REF_FRAME))
[docs] def resetSettings(self): """ Reset all the Settings """ self.data.resetSettings(show_simbox_default=self.matsci_profile) # Block all the signals while updating the GUI self.blockSignals(True) self.updateBasicTab() self.updateViewPositionTab() self.blockSignals(False) # Notify all settings changed due to reset self.allSettingsChanged.emit()
[docs] def decreaseSpeed(self): """ Decreases 'Speed' """ # Decreasing speed meaning increasing the frame duration self.data.frame_duration += self.FRAME_DURATION_STEP self.frameDurationChanged.emit(self.data.frame_duration) self.updateSpeedIcons()
[docs] def increaseSpeed(self): """ Increases 'Speed' """ # Increasing speed means decreasing the frame duration self.data.frame_duration -= self.FRAME_DURATION_STEP self.frameDurationChanged.emit(self.data.frame_duration) self.updateSpeedIcons()
@property def speed_percentage(self): """ Calculate current speed value in terms of percentage of max frame duration. """ return (round( (self.data.MAX_FRAME_DURATION + self.FRAME_DURATION_STEP - self.data.frame_duration) / self.FRAME_DURATION_STEP) * 10) - 10
[docs] def updateSpeedIcons(self): """ Updates enable state & tooltip of '-' & '+' icons according to their min & max values. """ speed_percentage = self.speed_percentage can_decrease_speed = ( self.data.frame_duration + self.FRAME_DURATION_STEP) <= self.data.MAX_FRAME_DURATION self.ui.speed_percentage_label.setText( f'{speed_percentage}%' if speed_percentage else ' ') self.ui.minus_button.setEnabled(can_decrease_speed) self.ui.minus_button.setToolTip( "Reduce playback speed" if can_decrease_speed else "At minimum speed") can_increase_speed = ( self.data.frame_duration - self.FRAME_DURATION_STEP) >= self.data.MIN_FRAME_DURATION self.ui.plus_button.setEnabled(can_increase_speed) self.ui.plus_button.setToolTip( "Increase playback speed" if can_increase_speed else "At maximum speed") self.recent_frame_duration = self.data.frame_duration
[docs] def updateStep(self, step): """ Updates 'Step' value """ self.data.step = step self.stepChanged.emit(self.data.step)
[docs] def updateSmoothing(self, smoothing): """ Updates 'Smoothing' value """ self.data.smoothing = smoothing self.smoothingChanged.emit(self.data.smoothing)
[docs] def updatePlayDirection(self, checked): """ Updates 'Play Direction' """ self.data.direction = { False: Direction.FORWARD, True: Direction.BACKWARD }[checked] self.updatePlayDirectionToolTip() self.playDirectionChanged.emit(self.data.direction)
[docs] def updatePlayDirectionToolTip(self): """ Updates 'Play Direction' tooltip based on the direction """ self.ui.play_button.setToolTip({ Direction.FORWARD: "Playing trajectory forward. Click to turn on reverse playback.", Direction.BACKWARD: "Playing trajectory backward. Click to return to forward playback." }[self.data.direction])
[docs] def updateLoop(self, button, checked): """ Updates 'Loop' """ # All three options of loop are added into a button group and one must # be always checked. So we are only interested when we recieve button # checked signal. if not checked: return self.data.loop = { self.ui.single_button: Loop.SINGLE, self.ui.oscilate_button: Loop.OSCILLATE, self.ui.off_button: Loop.NONE }[button] self.loopChanged.emit(self.data.loop) self.updateLoopTooltip()
[docs] def updateLoopTooltip(self): """ Updates 'Loop' buttons tooltip """ self.ui.single_button.setToolTip( "Repeating play is on" if self.ui.single_button.isChecked( ) else "Click to turn on repeating play") self.ui.oscilate_button.setToolTip( "Oscillating play is on" if self.ui.oscilate_button.isChecked( ) else "Click to turn on oscillating play") self.ui.off_button.setToolTip( "Looping is off (single-play only)" if self.ui.off_button.isChecked( ) else "Click to end looping")
[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 """ return self.display_settings_manager.getHideAtomsAsl()
[docs] def getHideAtomsBeyondBindingSiteASL(self): """ Returns hide atoms asl based on 'Beyond binding site' settings """ return self.display_settings_manager.getHideAtomsBeyondBindingSiteASL()
[docs] def getHideAtomsNonpolarHydrogensASL(self): """ Returns hide atoms asl based on 'Nonpolar hydrogens' settings """ return self.display_settings_manager.getHideAtomsNonpolarHydrogensASL()
[docs] def honorMatchingAtomsAsl(self): """ Whether to honor 'Atoms matching ASL definition:' option :rtype: bool """ return self.display_settings_manager.honorMatchingAtomsAsl()
[docs] def getMatchingAtomsAsl(self): """ Returns matching atom asl based on 'Display only:' :rtype: str or None """ return self.display_settings_manager.getMatchingAtomsAsl()
[docs] def getDisplayAtomsAsl(self): """ Returns display atom asl based on 'Hide atoms:' & 'Display only:' settings :rtype: str or None """ return self.display_settings_manager.getDisplayAtomsAsl()
[docs] def updateBeyondBindingSite(self, checked): """ Updates 'Hide atoms' 'Beyond Binding Site' """ self.data.ha_beyond_binding_site = checked self.beyondBindingSiteChanged.emit(self.data.ha_beyond_binding_site) self.updateBindingSiteTooltip(checked)
[docs] def updateBindingSiteTooltip(self, checked): """ Updates 'Beyond Binding Site' tooltip """ self.ui.beyond_checkbox.setToolTip( self.display_settings_manager.getBindingSiteTooltip(checked))
[docs] def updateSolventsOnly(self, checked): """ Updates 'Hide atoms' 'Solvents Only' """ self.data.ha_solvents_only = checked self.solventsOnlyChanged.emit(self.data.ha_solvents_only) self.updateSolventsTooltip(checked)
[docs] def updateSolventsTooltip(self, checked): """ Updates 'Solvents Only' tooltip """ self.ui.solvents_only_button.setToolTip( self.display_settings_manager.getSolventsTooltip(checked))
[docs] def updateNonpolarHydrogens(self, checked): """ Updates 'Hide atoms' 'Nonpolar Hydrogens' """ self.data.ha_nonpolar_hydrogens = checked self.nonpolarHydrogensChanged.emit(self.data.ha_nonpolar_hydrogens) self.updateNonpolarHydrogensTooltip(checked)
[docs] def updateNonpolarHydrogensTooltip(self, checked): """ Updates 'Nonpolar Hydrogens' tooltip """ self.ui.nonpolar_checkbox.setToolTip( self.display_settings_manager.getNonpolarHydrogensTooltip(checked))
[docs] def updateProteinOnly(self, checked): """ Update 'Hide atoms' 'Protein Only' """ self.data.ha_protein_only = checked self.proteinOnlyChanged.emit(self.data.ha_protein_only) self.updateProteinTooltip(checked)
[docs] def updateProteinTooltip(self, checked): """ Updates 'Protein Only' tooltip """ self.ui.protein_only_button.setToolTip( self.display_settings_manager.getProteinTooltip(checked))
[docs] def updateTranslateToFirstUnitCellPosition(self, checked: bool): """ Update trajectory to first unit cell option and notify about view positioning change. """ self.data.translate_to_first_unit_cell = checked if checked: self.data.show_simulation_box = True self.translateToFirstUnitCellChanged.emit() self.viewPositioningChanged.emit()
[docs] def updateAdjustViewPositioning(self, checked): """ Updates adjust view positioning """ self.ui.frame_lineedit.setEnabled(checked and self.ui.align_radiobutton.isChecked()) self.ui.atomselector_widget.setEnabled(checked) self.data.adjust_view_position = checked self.viewPositioningChanged.emit()
[docs] def updateAVPOption(self, button, checked): """ Updates below exclusive radio options in 'View Position' - Align on atoms from frame - Center molecules in Workspace """ if not checked: return self.data.avp_align_on_frame = (button == self.ui.align_radiobutton) self.data.avp_center_molecules = not self.data.avp_align_on_frame self.updateAVPAslOptionLabel() self.viewPositioningChanged.emit()
[docs] def updateRefFrame(self): """ Updates reference frame """ self.data.avp_ref_frame = int(self.ui.frame_lineedit.text()) self.viewPositioningChanged.emit()
[docs] def updateAVPAslOption(self, index): """ Updates 'Align on:'/'Center on:' """ self.ui.atomselector_widget.setVisible( index == AVPAslOption.CUSTOM_SELECTION.value) self.data.avp_asl_option = AVPAslOption(index) self.viewPositioningChanged.emit()
[docs] def updateAVPAslOptionLabel(self): """ Updates label to 'Align on:', if 'Align on atoms from frame' is checked, otherwise to 'Center on:', which indicates 'Center molecules in Workspace' checked. """ self.ui.asl_label.setText( 'Align on:' if self.data.avp_align_on_frame else 'Center on:')
[docs] def updateAVPAsl(self, asl): """ Updates 'Adjust view positioning' ASL """ self.data.avp_asl = asl self.viewPositioningChanged.emit()
[docs] def getAVPAsl(self): """ Return 'Adjust view positioning' Asl based on 'View Position' settings. """ AVP_OPTION_TO_ASL = { AVPAslOption.PROTEIN: '(protein)', AVPAslOption.LIGAND_PLUS_BINDING_SITE: 'fillres within %d (ligand)' % (self.data.binding_site_radius), AVPAslOption.LIGAND: '(ligand)', AVPAslOption.MOLECULE_1: 'mol.num 1', AVPAslOption.CUSTOM_SELECTION: self.data.avp_asl, } return AVP_OPTION_TO_ASL[self.data.avp_asl_option]
[docs] def closeEvent(self, event): """ Emits closed() signal. See Qt documentation for additional method documentation. """ self.closed.emit() return super().closeEvent(event)
[docs] def showEvent(self, event): """ Calls positionPopup() method to place the popup above the parent. See Qt documentation for additional method documentation. """ self.ui.settings_tabwidget.setCurrentIndex(self.current_tab.value) # Enable 'Use Workspace Selection' only if workspace has selection self.ui.load_sel_pushbutton.setEnabled( self.ws_hub.getSelectedAtomCount() > 0) # Popup width & height are not known for the first time before showing # the popup, so for the first time we show the popup and then position # it with a single shot timer. if self.showing_first_time: self.showing_first_time = False QtCore.QTimer.singleShot(0, self.positionPopup) else: self.positionPopup() return super().showEvent(event)
[docs] def positionPopup(self): """ Positions the 'PlaybackSettings' above parent in right to left direction. """ parent = self.parent() if parent: parentpos = parent.mapToGlobal(QtCore.QPoint(0, 0)) x = parentpos.x() + parent.width() - self.width() y = parentpos.y() - self.height() self.move(QtCore.QPoint(x, y))
[docs] def tabBarClicked(self, index): """ This method will be triggered when any tab is clicked. If the tab is 'Advanced...' then we hide the popup and call 'showAdvancedSettings' slot, otherwise store the current tab index. """ if index == Tab.ADVANCED.value: self.close() self.showAdvancedSettings() else: self.current_tab = Tab(index)
[docs] def resetMaxStepSize(self): """ This will be called when slider value changes. Based on the new start and end frame settings, reset the max value for step size spin box """ if not self.data.isValidStep(): self.data.setToMinStep() QtWidgets.QMessageBox.warning( None, "Trajectory Player - Step Size / Range Mismatch", "The current step size is too large for the current range. Player will revert to the default step size - all frames will be shown." ) self.ui.step_spinbox.setValue(self.data.step) self.ui.step_spinbox.setMaximum(self.data.getMaxStep())
[docs] def showAdvancedSettings(self): """ Show 'Advanced Playback Settings' dialog """ self.aboutToShowAdvancedSettings.emit() self.advanced_settings_dlg.showDlg()
def _handleAdvancedSettingsChange(self): """ Handle advaced settings change, update hide atoms and emit advancedSettingsChanged() signal """ # Block hide atom signals, and emit only one signal when there is # change in advanced settings self.blockSignals(True) self.updateHideAtoms() self.blockSignals(False) self.advancedSettingsChanged.emit()