Source code for schrodinger.application.bioluminate.ssv.toolbars

"""
Toolbars for the `SimplifiedSequenceViewer`

"""
# Contributors: Joshua Williams, Matvey Adzhigirey

#- Imports -------------------------------------------------------------------

from schrodinger.Qt import QtWidgets
from schrodinger.Qt.QtCore import Qt

from ..actions import configs as action_config
from ..actions import factory
from ..actions import icons
from ..protein import Consensus

try:
    from schrodinger.maestro import maestro
except ImportError:
    maestro = None  # For testing outside of Maestro

#- Classes -------------------------------------------------------------------


[docs]class ImportToolBar(QtWidgets.QToolBar): """ Get the toolbar that has the import dialogs. This toolbar has a single action, that when clicked opens a menu of different import options. """
[docs] def __init__(self, parent, title=None, action_order=None, text=True): """ :param title: The title of the toolbar. Used in right-click menu in a main window's toolbar area. :type title: str :param action_order: Order of the actions displayed in the popup menu :see: schrodinger.application.bioluminate.actions.config.IMPORT_STRUCTURES """ self._parent = parent super(ImportToolBar, self).__init__(parent) self.setMovable(False) # Keep this to offer same constructors as QToolBar if title: self.setWindowTitle(self.tr(title)) # Set up the actions action_factory = factory.Factory(parent) import_params = { 'default_order': ['import'], 'import': { 'icon': icons.MSV_OPEN_FILE, 'tooltip': 'Import homologs from structure or sequence', 'slot': self.openMenu, } } action_factory.setActions(import_params) import_action = action_factory.getAction('import') import_action.setIconText('Import homologs') action_factory.setActions(action_config.IMPORT_STRUCTURES, action_order=action_order) self.import_menu = action_factory.getMenu() self.addAction(import_action) self.addSeparator() self.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
[docs] def openMenu(self): """ Opens the import pull-down menu """ self.import_menu.exec(self._parent.mapToGlobal(self.pos()))
[docs]class FindToolBar(QtWidgets.QToolBar): """ Create an instance of the "Find Pattern" toolbar from the MSV. """
[docs] def __init__(self, parent, title=None): """ Construct toolbar. Here the `parent` should be an instance of a `schrodinger.ui.sequencealignment.sequence_viewer.SequenceViewer`. If it is not the parent will need a `findPattern` method. """ if not hasattr(parent, 'findPattern'): raise RuntimeError('Invalid parent, needs findPattern method.') self.parent = parent super(FindToolBar, self).__init__(parent) self.setMovable(False) # Keep this to offer same constructors as QToolBar if title: self.setWindowTitle(self.tr(title)) # Create the label and line edit label = QtWidgets.QLabel(self.tr("Find Pattern: ")) self.line_edit = QtWidgets.QLineEdit() self.line_edit.setToolTip( "Type PROSITE pattern to search the sequences:\n\n" "[AIL] - find any occurence of A, I, or L\n" "{ED} - exclude all occurences of E and D\n" "a - acidic residue [DE]\n" "b - basic residue [KR]\n" "o - hydrophobic residue [WILYFVPCA]\n" "p - aromatic residue [WYF]\n" "x or . or ? - any amino acid") self.line_edit.textChanged.connect(self.findTextChanged) # Get the "Previous" and "Next" actions action_factory = factory.Factory(parent) action_factory.setActions(action_config.FIND_PATTERN_ACTIONS) # Add the widgets and actions self.addWidget(label) self.addWidget(self.line_edit) self.addActions(action_factory.actions)
[docs] def findTextChanged(self, string): """ Called whenever text in "Find pattern" widget has changed. :type string: str :param string: pattern string """ self.parent.findPattern(str(string))
[docs]class ConsensusToolBar(QtWidgets.QToolBar): """ A toolbar associated with the viewer that will handle display options. These actions will be available through the toolbar: - Display the first protein in the sequence viewer - Display all proteins in the sequence viewer, superimposed - Toggle waters between visible/hidden - Toggle counterions between visible/hidden - Toggle ligands between visible/hidden - Display consensus waters - Display consensus counterions - Display consensus ligands """ ASL_WATER = '(water AND (NOT atom.ele H))' ASL_IONS = 'ions' ASL_LIGAND = '(((m.atoms 5-130)) and not ((ions) or ' ASL_LIGAND += '(res.pt ACE ACT ACY BCT BME BOG CAC CIT CO3 DMS EDO EGL EPE ' ASL_LIGAND += 'FES FMT FS3 FS4 GOL HEC HED HEM IOD IPA MES MO6 MPD MYR NAG ' ASL_LIGAND += 'NCO NH2 NH3 NO3 PG4 PO4 POP SEO SO4 SPD SPM SUC SUL TRS )))'
[docs] def __init__(self, parent): """ The parent needs to be an instance of the `SimplifiedSequenceViewer`. """ self.parent = parent super(ConsensusToolBar, self).__init__(parent) self.setWindowTitle('Consensus Display Toolbar') self.factory = factory.Factory(self) self.factory.setActions(action_config.CONSENSUS_DISPLAY) self.addActions(self.factory.actions)
[docs] def initActionStates(self): """ Called when a set of structures are imported. This will: - Include all structures in the WS - Hide waters - Hide ions - Show all ligands """ self._undisplayInWorkspace('water') self._undisplayInWorkspace(self.ASL_IONS) self.ligand_action.setChecked(True)
@property def water_action(self): """ Get the toggle_water action for the corresponding toolbar button :rtype: `action<schrodinger.application.bioluminate.action.SAction>` """ return self.factory.getAction('toggle_waters') @property def ion_action(self): """ Get the toggle_counterions action for the corresponding toolbar button :rtype: `action<schrodinger.application.bioluminate.action.SAction>` """ return self.factory.getAction('toggle_counterions') @property def ligand_action(self): """ Get the toggle_ligands action for the corresponding toolbar button :rtype: `action<schrodinger.application.bioluminate.action.SAction>` """ return self.factory.getAction('toggle_ligands') def _displayInWorkspace(self, asl): """ Displays all atoms with `asl` in the workspace """ if maestro: maestro.command('displayatom %s' % asl) def _undisplayInWorkspace(self, asl): """ Hides all atoms with `asl` in the workspace """ if maestro: maestro.command('undisplayatom %s' % asl) def _toggleView(self, asl): """ Private method to display/hide atoms based on ASL. This method must be called by a toggle slot method. """ toggle = self.sender() if toggle.isChecked(): self._displayInWorkspace(asl) else: self._undisplayInWorkspace(asl) def _viewConsensus(self, asl): """ Private method to display/hide consensus atoms based on ASL. """ # If we dont have a reference don't do anything ref_entry_id = self.getReferenceEntryId() if not ref_entry_id: return None # Show all proteins since we need to display the consensus atoms self.viewAllProteins() ref_st = self.parent.getReferenceStructure() mol_dict = {ref_entry_id: []} # Loop over all PT rows associated with the SV rows, except the # reference row. Then get the consensus atoms for each reference and # query st. for row in self.parent.generateSeqProjectRows(include_reference=False): mol_dict[row.entry_id] = [] mobile_st = row.getStructure() consensus = Consensus(ref_st, mobile_st, asl) mol_index_map = consensus.molecule_indices mol_dict[ref_entry_id].extend(list(mol_index_map)) mol_dict[row.entry_id].extend(list(mol_index_map.values())) # Use the stored entry ids and their consensus molnums to display # all atoms for entry_id, mols in mol_dict.items(): if not mols: continue molnums = set(str(m) for m in mols) asl = '((entry.id "%s")) AND (mol.entry %s)' % (entry_id, ','.join(molnums)) self._displayInWorkspace(asl) if maestro: maestro.command('fit all')
[docs] def getReferenceEntryId(self): """ Gets the PT entry ID for the reference structure. :returns: Reference entry id :rtype: int """ reference = self.parent.sequence_group.reference return reference.maestro_entry_id
[docs] def viewFirstProtein(self): """ Displays only the reference st in the workspace """ entry_id = self.getReferenceEntryId() maestro.command('entrywsincludeonly entry "%s"' % entry_id)
[docs] def viewAllProteins(self): """ Includes all structures in the sequence viewer in the Workspace """ maestro.command('delete atom all') for seq in self.parent.structure_sequences: if seq.maestro_entry_id is not None: # If this sequence is in the PT maestro.command('entrywsinclude entry "%s"' % seq.maestro_entry_id)
[docs] def toggleWaters(self): """ Slot to show/hide all waters """ self._toggleView('water')
[docs] def consensusWaters(self): """ Slot to show all consensus waters """ # Turn off all waters self.water_action.setChecked(False) self._viewConsensus(self.ASL_WATER)
[docs] def toggleCounterions(self): """ Slot to show/hide all ions """ self._toggleView(self.ASL_IONS)
[docs] def consensusCounterions(self): """ Slot to show all consensus ions """ # Turn off all ions self.ion_action.setChecked(False) self._viewConsensus(self.ASL_IONS)
[docs] def toggleLigands(self): """ Slot to show/hide all ligands """ self._toggleView(self.ASL_LIGAND)
[docs] def consensusLigands(self): """ Slot to show all consensus ligands """ # Turn off all ligands self.ligand_action.setChecked(False) self._viewConsensus(self.ASL_LIGAND)
[docs]class AntibodyNumberingToolBar(QtWidgets.QToolBar): """ Get the toolbar that has the combobox with the antibody numering schemes. This toolbar has a single action. When the combobox's index is changed the numbering scheme chosen is applied to the `SimplifiedSequenceViewer` """ SCHEMES = [('Chothia', 'Chothia'), ('EnhancedChothia', 'Enhanced Chothia'), ('Kabat', 'Kabat'), ('IMGT', 'IMGT'), ('AHo', 'AHo')] """ Antibody numbering schemes to choose from. Each item in the list is a tuple of: (<backend name>, <display name>). """
[docs] def __init__(self, parent, title='Antibody numbering scheme'): """ :param title: The title of the toolbar. Used in right-click menu in a main window's toolbar area. :type title: str """ self._parent = parent super(AntibodyNumberingToolBar, self).__init__(parent) #self.setMovable(False) # Keep this to offer same constructors as QToolBar if title: self.setWindowTitle(self.tr(title)) self._setup()
def _setup(self): """ Private method to set up the combobox. """ # Create the label and combobox label = QtWidgets.QLabel(self.tr("Antibody numbering scheme: ")) self.combo = QtWidgets.QComboBox(self._parent) self.combo.addItems([d_name for b_name, d_name in self.SCHEMES]) self.combo.currentIndexChanged.connect(self.indexChanged) # Add the widgets self.addWidget(label) self.addWidget(self.combo)
[docs] def currentScheme(self, idx=None): """ Returns the backend name of the scheme matching the specified index or the current index on the combobox, if no index is supplied. :param idx: The index of the scheme :type idx: int :rtype: str :return: The name of the requested backend scheme """ if not idx: idx = self.combo.currentIndex() backend_name, display_name = self.SCHEMES[idx] return backend_name
[docs] def showScheme(self, scheme=None): """ Shows the specified scheme in the viewer, or, if no scheme is specified, shows the scheme currently selected in the combobox. :param scheme: The scheme to show :type scheme: str """ if not scheme: scheme = self.currentScheme() self._parent.assignAntibodyScheme(scheme=scheme) self._parent.antibody_scheme = scheme
[docs] def hideScheme(self): """ Removes the antibody scheme from the viewer altogether """ scheme = self.currentScheme() self._parent.assignAntibodyScheme(scheme=scheme, remove=True)
[docs] def indexChanged(self, idx): """ Slot called when the combobox's index is changed. This will change the `SimplifiedSequenceViewer` antibody numbering scheme. """ scheme = self.currentScheme(idx) self.showScheme(scheme)