Source code for schrodinger.application.msv.gui.menu
from schrodinger import get_maestro
from schrodinger import in_dev_env
from schrodinger.application.msv.gui import gui_models
from schrodinger.application.msv.gui import stylesheets
from schrodinger.application.msv.gui.viewconstants import \
MULTI_ALIGN_DISABLED_TT
from schrodinger.application.msv.gui.viewconstants import MULTI_ALIGN_ENABLED_TT
from schrodinger.application.msv.gui.viewconstants import PROF_ALIGN_DISABLED_TT
from schrodinger.application.msv.gui.viewconstants import Autosave
from schrodinger.models import mappers
from schrodinger.Qt import QtCore
from schrodinger.Qt import QtGui
from schrodinger.Qt import QtWidgets
from schrodinger.ui.qt.mapperwidgets import MappableActionGroup
maestro = get_maestro()
TUTORIAL_BASE_PATH = 'https://www.schrodinger.com/sites/default/files/s3/mkt/Tutorials/current/'
MSV_GUIDE = 'https://www.schrodinger.com/system/files/msv_guide_r3.pdf'
url = TUTORIAL_BASE_PATH + "{}.pdf"
BIOLUMINATE_INTRO = url.format('intro_bioluminate')
CHIMERIC_HOMOLGY_MODELING = url.format('chimeric_homology_building')
BATCH_HOMOLOGY_MODELING = url.format('batch_homology')
ANTIBODY_ANNOTATION = url.format('antibody_annotation')
[docs]class MenuAction(QtGui.QAction):
[docs] def __init__(self,
label,
tooltip=None,
shortcut=None,
checkable=False,
icon_path=None,
data=None):
super().__init__(label)
if tooltip:
self.setToolTip(tooltip)
if shortcut:
self.setShortcut(shortcut)
self.setCheckable(checkable)
if icon_path:
icon = QtGui.QIcon(icon_path)
self.setIcon(icon)
if data:
self.setData(data)
# We do this temporarily to indicate that the feature is not yet
# implemented
self.setImplemented(False)
[docs] def setImplemented(self, has_been_implemented):
"""
Sets whether a feature has been implemented yet
:param has_been_implemented: Whether action has been implemented
:type has_been_implemented: bool
"""
font = self.font()
font.setStrikeOut(not has_been_implemented)
self.setFont(font)
self.setEnabled(has_been_implemented)
[docs]class ToggleTextAction(mappers.TargetMixin, MenuAction):
"""
Menu action that toggles a bool every time it's triggered and updates the
text based on the value of the bool
"""
[docs] def __init__(self, true_text, false_text):
super().__init__("")
self._texts = [false_text, true_text]
self.targetSetValue(False) # Initialize internal state and text
self.triggered.connect(self._toggleValue, QtCore.Qt.QueuedConnection)
self.setImplemented(True) # Override `MenuAction` default
[docs] def targetSetValue(self, value: bool):
self._value = value
self.setText(self._texts[int(self._value)])
def _toggleValue(self):
self.targetSetValue(not self.targetGetValue())
self.targetValueChanged.emit()
[docs]class MenuBarActions(object):
"""
MenuBarActions provides a namespace for all the actions on the menu bar
"""
[docs] def __init__(self):
MA = MenuAction
# File
# New Submenu - Currently has no contents
self.close_project = MA("Close MSV Project")
self.new_project = MA("New MSV Project...")
self.open_project = MA("Open MSV Project...",
tooltip="Load project from file",
shortcut="Ctrl+Alt+O")
self.import_project = MA("Import MSV Project...",
tooltip="Load project and add its contents to "
"the current project.")
self.save_project = MA("Save",
tooltip="Save current project",
icon_path=":/msv/icons/save_file.png")
self.save_as = MA("Save As...",
tooltip="Save current project to a specified file",
icon_path=":/msv/icons/save_file.png")
self.get_pdb = MA("Get PDB...")
self.get_sequences = MA("Fetch Sequences...")
self.import_sequences = MA("Import Sequences from File...",
tooltip="Import sequences from a file",
shortcut="Ctrl+O",
icon_path=":/msv/icons/import_sequences.png")
self.paste_sequences = MA("Paste in New Sequence Text...")
self.import_from_maestro = submenu_action("Load from Maestro")
self.import_from_maestro_workspace = MA("Workspace...")
self.import_from_maestro_selected = MA("Selected Entries...")
self.export_sequences = MA("&Export Sequences...",
tooltip="Export the sequences to file",
shortcut="Ctrl+S")
self.save_image = MA("&Save Image...",
tooltip="Save Image...",
shortcut="Ctrl+I")
self.close = MA("E&xit", tooltip="Close Panel", shortcut="Ctrl+W")
# Edit
self.undo = MA("&Undo",
shortcut="Ctrl+Z",
tooltip="Undo last editing operation",
icon_path=":/msv/icons/undo.png")
self.redo = MA("&Redo",
tooltip="Redo last editing operation",
shortcut="Shift+Ctrl+Z",
icon_path=":/mvs/icons/redo.png")
self.edit_sequence = MA("Edit Sequence In Place",
tooltip="Edit a sequence in place",
checkable=True)
self.edit_sequence.setImplemented(True)
self.copy = MA("Copy Selected Residues", shortcut="Ctrl+C")
self.delete_sub = submenu_action("Delete")
self.delete_sel_residues = MA("Selected Residues", shortcut="Shift+Del")
self.delete_sel_gaps = MA("Selected Gaps")
self.delete_gap_cols = MA("All Gap-Only Columns")
self.delete_sel_seqs = MA("Selected Sequences")
self.delete_redundant_seqs = MA("Redundant Sequences...")
self.delete_all_predictions = MA("All Predictions")
self.delete_this_tab = MA("This Tab")
self.delete_all_view_tabs = MA("All View Tabs")
self.move_seq = submenu_action("Move Sequence")
self.move_to_top = MA("To Top")
self.move_up = MA("Up")
self.move_down = MA("Down")
self.move_to_bottom = MA("To Bottom")
self.move_set_as_ref = MA("Set as Reference")
self.duplicate_seq = submenu_action('Duplicate Sequence')
self.duplicate_in_place = MA("In Place", shortcut="Ctrl+D")
self.duplicate_at_bottom = MA("At Bottom")
self.duplicate_at_top = MA("At Top")
self.duplicate_as_ref = MA("As Reference Sequence")
self.duplicate_into_new_tab = MA("Into New Tab")
self.duplicate_into_existing_tab = MA("Into Existing Tab")
self.set_as_ref_seq = MA("Set as Reference Sequence")
self.rename_seq = MA("Rename Sequence")
self.color_seq_name = MA("Color Sequence Name...")
self.sort_seq = submenu_action("Sort Sequences by")
# Ascending Sort Submenu
self.sort_ascending = submenu_action("Sort Sequences &Ascending")
self.sort_ascending_by_name = MA("Name")
self.sort_ascending_by_chain_id = MA("Chain ID")
self.sort_ascending_by_gaps = MA("Number of Gaps")
self.sort_ascending_by_length = MA("Length")
self.sort_ascending_by_seq_identity = MA("Identity %")
self.sort_ascending_by_seq_similarity = MA("Similarity %")
self.sort_ascending_by_seq_homology = MA("Conservation %")
self.sort_ascending_by_seq_score = MA("Overall Score")
# Descending Sort Submenu
self.sort_descending = submenu_action("Sort Sequences &Descending")
self.sort_descending_by_name = MA("Name")
self.sort_descending_by_chain_id = MA("Chain ID")
self.sort_descending_by_gaps = MA("Number of Gaps")
self.sort_descending_by_length = MA("Length")
self.sort_descending_by_seq_identity = MA("Identity %")
self.sort_descending_by_seq_similarity = MA("Similarity %")
self.sort_descending_by_seq_homology = MA("Conservation %")
self.sort_descending_by_seq_score = MA("Overall Score")
self.sort_by_tree_order = MA("Tree Order", checkable=True)
self.reverse_last_sort = MA("Reverse Last Sort")
self.get_pdb_sts = MA("Get PDB Structures")
self.translate_seq = MA("Translate DNA / RNA Sequence")
self.replace_sel_with_gaps = MA("Replace Selection with Gaps")
self.renumber_residues = MA("Renumber Residues...")
self.edit_as_text = MA("Edit Sequence as Plain Text...")
self.settings = submenu_action("Settings and Defaults")
self.job_settings = MA("Job Settings...")
self.local_server = submenu_action("Use Local Server Only for")
self.sequence_local = MA("Fetching Sequences", checkable=True)
self.sequence_local.setImplemented(True)
self.blast_local = MA("BLAST Searches/Access", checkable=True)
self.blast_local.setImplemented(True)
self.pdb_local = MA("Getting PDB Files", checkable=True)
self.pdb_local.setImplemented(True)
self.reset_remote_server_ask = MA("Reset Remote Server Confirmations")
self.view_job_log = MA("View Job Log...")
self.reset_job_settings = MA("Reset All Job Settings")
self.font_size = MA("Set Default Font Size...")
self.auto_save = submenu_action("Autosave")
self.auto_save_regularly = MA("Regularly and After Edits",
checkable=True)
self.auto_save_after_edit = MA("Only After Edits", checkable=True)
self.auto_save_never = MA("Never", checkable=True)
self.light_mode = MA("Use Light Theme")
self.light_mode.setCheckable(True)
self.light_mode.setImplemented(True)
# View
self.hide_selected_seqs = MA("Hide Selected Sequences")
self.show_workspace_seqs = MA("Show Workspace Sequences Only")
self.show_all_seqs = MA("Show All Sequences")
self.find_seqs_in_list = MA("Find Sequence in List...")
self.expand = submenu_action("Expand")
self.collapse = submenu_action("Collapse")
# Expand/Collapse Menu
self.expand_selected = MA("Selected")
self.expand_unselected = MA("Unselected")
self.expand_all = MA("All")
self.collapse_selected = MA("Selected")
self.collapse_unselected = MA("Unselected")
self.collapse_all = MA("All")
self.hide_sel_columns = MA("Hide Selected Columns")
self.show_all_cols_within_sel = MA("Show All Columns within Selection")
self.show_all_hidden_cols = MA("Show All Hidden Columns")
self.hide_annotations = ToggleTextAction("Hide Annotations",
"Show Annotations")
self.hide_colors = ToggleTextAction("Hide Colors", "Show Colors")
self.configure = submenu_action("Configure")
# Configure Menu
self.configure_annotations = MA("Annotations...")
self.configure_colors = MA("Colors...")
self.configure_view = MA("View...")
self.reset_to_defaults = MA("Reset to Defaults")
# Select
self.select_all_sequences = MA("All Sequences")
self.select_no_sequences = MA("No Sequences")
self.select_sequences_by_feature = submenu_action(
"Sequences by Feature")
self.select_sequence_with_structure = MA("With Structure")
self.select_sequence_by_identity = MA("By Identity...")
self.select_sequence_antibody_heavy = MA("Antibody Heavy Chain")
self.select_sequence_antibody_light = MA("Antibody Light Chain")
self.select_invert_seq_selection = MA("Invert Sequence Selection")
self.select_all_residues = MA("All Residues", shortcut="Ctrl+A")
self.select_no_residues = MA("No Residues", shortcut="Ctrl+U")
self.select_residues_with_structure = MA("Residues with Structure")
self.select_pattern_matching_residues = MA("Pattern-Matching Residues")
self.select_deselect_gaps = MA("Deselect All Gaps")
self.select_invert_res_selection = MA("Invert Residue Selection")
self.select_identities = MA("Identities")
self.select_aligned_residues = MA("Aligned Residues")
self.select_binding_sites = MA("Binding Site Residues")
self.select_protein_interface = MA("Protein Interface")
self.select_antibody_cdr = MA("Antibody CDRs")
self.select_columns_with_structure = MA("Columns with Structure")
self.select_expand_along_cols = MA("Expand Along Columns")
self.select_expand_ref_sel_only = MA("Expand Reference Selection Only")
self.select_update_workspace_selection = MA(
"Update Workspace Selection")
self.select_link_seq_to_entries = MA("Link Sequences to Entries...")
# Alignment
self.auto_align = MA("Auto-Align New Sequences", checkable=True)
self.auto_align.setImplemented(True)
self.align_sequences = submenu_action("Align Sequences")
self.multiple_alignment = MA("Multiple Alignment")
self.pairwise_alignment = MA(
"Pairwise Alignment",
tooltip=("Align selected sequence(s) with the reference sequence "
"using pairwise alignment"))
self.pairwise_ss_alignment = MA(
"Pairwise with Secondary Structure Prediction")
self.align_from_superposition = MA(
"Align Based on Structure Superposition")
self.profile_alignment = MA("Profile Alignment")
self.align_structures = submenu_action("Align Structures")
self.prot_struct_align = MA("Protein Structure Alignment")
self.align_binding_sites = MA("Align Binding Sites")
self.align_based_sequence = MA("Align Based on Sequence Alignment")
self.dendrogram = MA("View Dendrogram", tooltip="Display dendrogram")
self.set_constraints = MA("Set Constraints", checkable=True)
self.set_constraints.setImplemented(True)
self.clear_constraints = MA("Clear Constraints",
tooltip="Clear alignment constraints")
self.reset_align = MA("Reset Alignment Settings")
self.anchor_selection = MA("Anchor Selection")
self.clear_anchoring = MA("Clear Anchoring")
# Help menu
self.msv_help = MA("Multiple Sequence Viewer/Editor...",
data="MSV_MAIN_WINDOW")
self.homology_modeling_help = MA("Homology Modeling...",
data="MSV_BUILD_HOMOLOGY_MODEL")
self.alignment_pane_help = MA("Alignment Pane...",
data="MSV_ALIGN_PANE")
self.getting_started_help = MA("Getting Started Guide...",
data=MSV_GUIDE)
self.bioluminate_intro = MA(
"Structures, Sequences, && Homology Modeling...",
data=BIOLUMINATE_INTRO)
self.chimeric_hm_help = MA("Chimeric Homology Modeling...",
data=CHIMERIC_HOMOLGY_MODELING)
self.batch_hm_help = MA("Batch Homology Modeling...",
data=BATCH_HOMOLOGY_MODELING)
self.antibody_anno_help = MA("Coloring && Annotation of Antibodies...",
data=ANTIBODY_ANNOTATION)
self.tutorials = submenu_action("Tutorials")
# Development tools
self.start_ipython_session = MA("Start IPython Terminal Session")
self.show_debug_gui = MA("Show Debug Gui")
self.show_color_scheme_editor = MA("Show Color Scheme Editor")
self.time_scroll = MA("Time Scrolling")
self.time_scroll_by_page = MA("Time Scrolling By Page")
self.profile_scroll = MA("Profile Scrolling")
self.profile_scroll_by_page = MA("Profile Scrolling By Page")
self.view_history = MA("History", checkable=True)
[docs]class EnabledTargetSpec(mappers.TargetSpec):
"""
A TargetSpec for mapping a BoolParam to the enabled state of a widget
"""
[docs] def __init__(self, widget):
super().__init__(widget,
getter=None,
setter=widget.setEnabled,
signal=None)
[docs]class MsvMenuBar(mappers.MapperMixin, QtWidgets.QMenuBar):
model_class = gui_models.MenuEnabledModel
[docs] def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setNativeMenuBar(False)
self.setStyleSheet(stylesheets.MENU)
self._setMenuActions()
self._makeMenus()
self._setupMapperMixin()
[docs] def defineMappings(self):
ma = self.menu_actions
M = self.model_class
actions = [
(ma.edit_as_text, M.can_edit_as_text),
(ma.copy, M.can_copy_residues),
(ma.delete_sel_seqs, M.can_delete_sequences),
(ma.delete_sel_residues, M.can_delete_residues),
(ma.delete_sel_gaps, M.can_delete_gaps),
(ma.delete_all_predictions, M.can_delete_predictions),
(ma.delete_this_tab, M.can_delete_tab),
(ma.move_seq, M.can_move_sequence),
(ma.set_as_ref_seq, M.can_set_as_ref),
(ma.rename_seq, M.can_rename_seq),
(ma.move_set_as_ref, M.can_set_as_ref),
(ma.duplicate_seq, M.can_duplicate_sequence),
(ma.duplicate_as_ref, M.can_duplicate_as_ref),
(ma.duplicate_in_place, M.can_duplicate_seq_same_tab),
(ma.duplicate_at_bottom, M.can_duplicate_seq_same_tab),
(ma.duplicate_at_top, M.can_duplicate_seq_same_tab),
(ma.replace_sel_with_gaps, M.can_replace_res_with_gaps),
(ma.renumber_residues, M.can_renumber_residues),
(ma.select_all_sequences, M.can_select),
(ma.select_no_sequences, M.can_select),
(ma.select_sequence_with_structure, M.can_select),
(ma.select_sequence_by_identity,M.can_select),
(ma.select_invert_seq_selection, M.can_select),
(ma.select_all_residues, M.can_select),
(ma.select_no_residues, M.can_select),
(ma.select_residues_with_structure, M.can_select),
(ma.select_invert_res_selection, M.can_select),
(ma.select_protein_interface, M.can_select_protein_interface),
(ma.expand, M.can_expand),
(ma.collapse, M.can_expand),
(ma.anchor_selection, M.can_anchor_res),
(ma.clear_anchoring, M.can_unanchor_res),
(ma.hide_sel_columns, M.can_hide_columns),
(ma.set_constraints, M.can_set_constraints),
(ma.clear_constraints, M.can_clear_constraints),
(ma.sort_ascending_by_chain_id, M.can_sort_by_chain),
(ma.sort_descending_by_chain_id, M.can_sort_by_chain),
(ma.select_sequence_antibody_heavy, M.can_select_antibody_chain),
(ma.select_sequence_antibody_light, M.can_select_antibody_chain),
(ma.get_pdb_sts, M.can_get_pdb_sts),
(ma.select_link_seq_to_entries, M.can_link_or_unlink_sequences),
] # yapf: disable
EnabledTS = EnabledTargetSpec
mappings = [(EnabledTS(action), param) for (action, param) in actions]
update_align_tgt = mappers.TargetSpec(slot=self._updateCanAlign)
for param in (M.can_only_multiple_align, M.can_only_profile_align,
M.can_aln_set_align):
mappings.append((update_align_tgt, param))
return mappings
[docs] @QtCore.pyqtSlot(bool)
def canRedoChanged(self, can_redo):
"""
Update the menu state depending on whether redo is available
"""
redo_action = self.menu_actions.redo
if redo_action.isEnabled() != can_redo:
redo_action.setEnabled(can_redo)
[docs] @QtCore.pyqtSlot(bool)
def canUndoChanged(self, can_undo):
"""
Update the menu state depending on whether undo is available
"""
undo_action = self.menu_actions.undo
if undo_action.isEnabled() != can_undo:
undo_action.setEnabled(can_undo)
[docs] @QtCore.pyqtSlot(str)
def onRedoTextChanged(self, redo_text):
"""
Update the Red menu action text to reflect the current redo action.
:param redo_text: Text of the current redo action
:type redo_text: str
"""
redo_action = self.menu_actions.redo
if not redo_text:
redo_action.setText('&Redo')
else:
redo_action.setText('&Redo - {0}'.format(redo_text))
[docs] @QtCore.pyqtSlot(str)
def onUndoTextChanged(self, undo_text):
"""
Update the Undo menu action text to reflect the current undo action.
:param undo_text: Text of the current undo action
:type undo_text: str
"""
undo_action = self.menu_actions.undo
if not undo_text:
undo_action.setText('&Undo')
else:
undo_action.setText("&Undo - {0}".format(undo_text))
def _updateCanAlign(self):
ma = self.menu_actions
align_actions = {
ma.multiple_alignment, ma.pairwise_alignment,
ma.pairwise_ss_alignment, ma.align_from_superposition,
ma.profile_alignment, ma.prot_struct_align, ma.align_binding_sites,
ma.align_based_sequence
}
if not self.model.can_aln_set_align:
allowed_actions = set()
elif self.model.can_only_profile_align:
allowed_actions = {ma.profile_alignment}
elif self.model.can_only_multiple_align:
allowed_actions = {ma.multiple_alignment}
else:
# Profile alignment is only allowed when it's the only allowed align
allowed_actions = align_actions - {ma.profile_alignment}
if not maestro:
allowed_actions.discard(ma.align_based_sequence)
for action in align_actions:
enabled = action in allowed_actions
action.setEnabled(enabled)
prof_align_tooltip = ("" if ma.profile_alignment.isEnabled() else
PROF_ALIGN_DISABLED_TT)
multi_align_tooltop = (MULTI_ALIGN_ENABLED_TT
if ma.multiple_alignment.isEnabled() else
MULTI_ALIGN_DISABLED_TT)
ma.profile_alignment.setToolTip(prof_align_tooltip)
ma.multiple_alignment.setToolTip(multi_align_tooltop)
def _setMenuActions(self):
self.menu_actions = MenuBarActions()
def _makeMenus(self):
self._addFileMenu()
self._addEditMenu()
self._addSelectionMenu()
self._addViewMenu()
self._addAlignmentMenu()
self._addHelpMenu()
self._maybeAddDevelopmentMenu()
def _addActionsToMenu(self, menu, actions):
for action in actions:
self._addActionToMenu(menu, action)
menu.addSeparator()
def _addActionToMenu(self, menu, action):
action.setParent(menu)
menu.addAction(action)
menu.setToolTipsVisible(True)
def _addFileMenu(self):
file_menu = QtWidgets.QMenu("&File", self)
ma = self.menu_actions
add_project_group = [
ma.open_project, ma.import_project, ma.close_project
]
save_or_close_proj_group = [ma.save_project, ma.save_as]
import_group = [
ma.get_pdb, ma.get_sequences, ma.import_sequences,
ma.paste_sequences, ma.import_from_maestro
]
import_from_maestro = [
ma.import_from_maestro_workspace, ma.import_from_maestro_selected
]
export_group = [ma.export_sequences, ma.save_image]
close_group = [ma.close]
for group in [
add_project_group, save_or_close_proj_group, import_group,
export_group, close_group
]:
self._addActionsToMenu(file_menu, group)
maestro_menu = ma.import_from_maestro.menu
self._addActionsToMenu(maestro_menu, import_from_maestro)
self.addMenu(file_menu)
def _addEditMenu(self):
edit_menu = QtWidgets.QMenu("&Edit", self)
ma = self.menu_actions
edit_group = [ma.undo, ma.redo]
copy_del_move_dup_group = [
ma.copy, ma.delete_sub, ma.move_seq, ma.duplicate_seq
]
name_group = [
ma.set_as_ref_seq,
ma.rename_seq,
# MSV-3357: Hiding unimplemented features for beta
#ma.color_seq_name
]
sort_group = [ma.sort_seq, ma.get_pdb_sts, ma.translate_seq]
replace_res_group = [
ma.replace_sel_with_gaps, ma.renumber_residues, ma.edit_as_text
]
for group in [
edit_group,
[ma.edit_sequence],
copy_del_move_dup_group,
name_group,
sort_group,
replace_res_group,
[ma.settings],
]:
self._addActionsToMenu(edit_menu, group)
delete_res_group = [
ma.delete_sel_residues, ma.delete_sel_gaps, ma.delete_gap_cols
]
delete_seq_group = [
ma.delete_sel_seqs, ma.delete_redundant_seqs,
ma.delete_all_predictions
]
delete_tab_group = [ma.delete_this_tab, ma.delete_all_view_tabs]
delete_menu = ma.delete_sub.menu
self._addActionsToMenu(delete_menu, delete_res_group)
self._addActionsToMenu(delete_menu, delete_seq_group)
self._addActionsToMenu(delete_menu, delete_tab_group)
move_group = [
ma.move_to_top, ma.move_up, ma.move_down, ma.move_to_bottom
]
move_ref_group = [ma.move_set_as_ref]
move_menu = ma.move_seq.menu
self._addActionsToMenu(move_menu, move_group)
self._addActionsToMenu(move_menu, move_ref_group)
duplicate_menu = ma.duplicate_seq.menu
duplicate_group = [
ma.duplicate_in_place, ma.duplicate_at_bottom, ma.duplicate_at_top,
ma.duplicate_as_ref
]
duplicate_new_tab_group = [
ma.duplicate_into_new_tab, ma.duplicate_into_existing_tab
]
self._addActionsToMenu(duplicate_menu, duplicate_group)
self._addActionsToMenu(duplicate_menu, duplicate_new_tab_group)
sort_seq = [
# MSV-3357: Hiding unimplemented features for beta
#[ma.sort_by_tree_order],
[ma.sort_ascending, ma.sort_descending],
[ma.reverse_last_sort]
]
sort_ascending = [
ma.sort_ascending_by_name, ma.sort_ascending_by_chain_id,
ma.sort_ascending_by_gaps, ma.sort_ascending_by_length,
ma.sort_ascending_by_seq_identity,
ma.sort_ascending_by_seq_similarity,
ma.sort_ascending_by_seq_homology, ma.sort_ascending_by_seq_score
]
sort_descending = [
ma.sort_descending_by_name, ma.sort_descending_by_chain_id,
ma.sort_descending_by_gaps, ma.sort_descending_by_length,
ma.sort_descending_by_seq_identity,
ma.sort_descending_by_seq_similarity,
ma.sort_descending_by_seq_homology, ma.sort_descending_by_seq_score
]
sort_menu = ma.sort_seq.menu
for group in sort_seq:
self._addActionsToMenu(sort_menu, group)
ascending_menu = ma.sort_ascending.menu
self._addActionsToMenu(ascending_menu, sort_ascending)
descending_menu = ma.sort_descending.menu
self._addActionsToMenu(descending_menu, sort_descending)
local_menu = ma.local_server.menu
local_group = [ma.sequence_local, ma.blast_local, ma.pdb_local]
self._addActionsToMenu(local_menu, local_group)
autosave_menu = ma.auto_save.menu
autosave_menu_items = [
ma.auto_save_regularly, ma.auto_save_after_edit, ma.auto_save_never
]
self._addActionsToMenu(autosave_menu, autosave_menu_items)
for action in autosave_menu_items:
action.setImplemented(True)
menu_action_map = {
ma.auto_save_regularly: Autosave.Regularly,
ma.auto_save_after_edit: Autosave.OnlyAfterEdit,
ma.auto_save_never: Autosave.Never
}
self.auto_save_group = MappableActionGroup(menu_action_map, parent=self)
self.auto_save_group.setExclusive(True)
settings_menu = ma.settings.menu
#job_group = [ma.job_settings, ma.view_job_log]
server_group = [
ma.local_server,
ma.reset_remote_server_ask,
# MSV-3357: Hiding unimplemented features for beta
#ma.reset_job_settings
]
#defaults_group = [ma.font_size]
for group in (
# MSV-3357: Hiding unimplemented features for beta
#job_group,
server_group,
#defaults_group,
[ma.auto_save, ma.light_mode]):
self._addActionsToMenu(settings_menu, group)
self.addMenu(edit_menu)
def _addSelectionMenu(self):
selection_menu = QtWidgets.QMenu("&Select", self)
ma = self.menu_actions
select_antibody_group = [
ma.select_sequence_antibody_heavy, ma.select_sequence_antibody_light
]
select_by_feature_group = [
ma.select_sequence_with_structure, ma.select_sequence_by_identity
]
select_feature_menu = ma.select_sequences_by_feature.menu
for group in (select_by_feature_group, select_antibody_group):
self._addActionsToMenu(select_feature_menu, group)
seq_res_group = [
ma.select_all_sequences, ma.select_no_sequences,
ma.select_sequences_by_feature, ma.select_invert_seq_selection
]
residue_group = [
ma.select_all_residues, ma.select_no_residues,
ma.select_residues_with_structure,
ma.select_pattern_matching_residues, ma.select_deselect_gaps,
ma.select_invert_res_selection
]
misc_group = [
ma.select_identities, ma.select_aligned_residues,
ma.select_binding_sites, ma.select_protein_interface,
ma.select_antibody_cdr, ma.select_columns_with_structure
]
expand_group = [
ma.select_expand_along_cols, ma.select_expand_ref_sel_only
]
for group in [
seq_res_group, residue_group, misc_group, expand_group,
[
ma.select_update_workspace_selection,
ma.select_link_seq_to_entries
]
]:
self._addActionsToMenu(selection_menu, group)
self.addMenu(selection_menu)
def _addViewMenu(self):
view_menu = QtWidgets.QMenu("&View", self)
ma = self.menu_actions
seq_group = [
ma.hide_selected_seqs, ma.show_workspace_seqs, ma.show_all_seqs,
ma.find_seqs_in_list
]
expand_collapse_group = [ma.expand, ma.collapse]
# MSV-3357: Hiding unimplemented features for beta
#cols_group = [
#ma.hide_sel_columns, ma.show_all_cols_within_sel,
#ma.show_all_hidden_cols
#]
annotations_colors_group = [
ma.hide_annotations, ma.hide_colors, ma.configure,
ma.reset_to_defaults
]
expand_menu = ma.expand.menu
collapse_menu = ma.collapse.menu
configure_menu = ma.configure.menu
expand_sel_group = [
ma.expand_selected, ma.expand_unselected, ma.expand_all
]
collapse_sel_group = [
ma.collapse_selected, ma.collapse_unselected, ma.collapse_all
]
config_group = [
ma.configure_annotations, ma.configure_colors, ma.configure_view
]
for group in [expand_sel_group]:
self._addActionsToMenu(expand_menu, group)
for group in [collapse_sel_group]:
self._addActionsToMenu(collapse_menu, group)
for group in [config_group]:
self._addActionsToMenu(configure_menu, group)
for group in [
seq_group,
expand_collapse_group,
# MSV-3357: Hiding unimplemented features for beta
#cols_group,
annotations_colors_group
]:
self._addActionsToMenu(view_menu, group)
self.addMenu(view_menu)
def _addAlignmentMenu(self):
align_menu = QtWidgets.QMenu("&Align", self)
ma = self.menu_actions
align_seq_group = [
ma.multiple_alignment,
ma.pairwise_alignment,
ma.pairwise_ss_alignment,
ma.profile_alignment,
]
align_based_superposition = [ma.align_from_superposition]
align_seq_menu = ma.align_sequences.menu
for group in [align_seq_group, align_based_superposition]:
self._addActionsToMenu(align_seq_menu, group)
align_struct_menu = ma.align_structures.menu
stucture_alignment = [ma.prot_struct_align, ma.align_binding_sites]
align_based_seq = [ma.align_based_sequence]
for group in [stucture_alignment, align_based_seq]:
self._addActionsToMenu(align_struct_menu, group)
seq_align_group = [
ma.align_sequences, ma.align_structures, ma.dendrogram
]
constrain_group = [
ma.set_constraints,
ma.clear_constraints,
]
reset_group = [ma.reset_align]
anchor_group = [ma.anchor_selection, ma.clear_anchoring]
for group in [
[ma.auto_align],
seq_align_group,
constrain_group,
reset_group,
anchor_group,
]:
self._addActionsToMenu(align_menu, group)
self.addMenu(align_menu)
def _maybeAddDevelopmentMenu(self):
"""
Adds the development menu if SCHRODINGER_SRC is set in the user's
environment
"""
if not in_dev_env():
return
dev_menu = QtWidgets.QMenu("&Development", self)
self._addActionsToMenu(dev_menu, [
self.menu_actions.start_ipython_session,
self.menu_actions.show_debug_gui,
self.menu_actions.show_color_scheme_editor,
self.menu_actions.time_scroll,
self.menu_actions.time_scroll_by_page,
self.menu_actions.profile_scroll,
self.menu_actions.profile_scroll_by_page,
self.menu_actions.view_history
])
self.addMenu(dev_menu)
def _addHelpMenu(self):
help_menu = QtWidgets.QMenu("&Help", self)
ma = self.menu_actions
self._addActionsToMenu(help_menu, [
ma.msv_help,
ma.homology_modeling_help,
ma.alignment_pane_help,
])
self._addActionToMenu(help_menu, ma.getting_started_help)
self._addActionToMenu(help_menu, ma.tutorials)
self.addMenu(help_menu)
tutorials_menu = ma.tutorials.menu
for act in (ma.bioluminate_intro, ma.chimeric_hm_help, ma.batch_hm_help,
ma.antibody_anno_help):
self._addActionToMenu(tutorials_menu, act)