def create_label_row(self): """ Row with two labels and a "Remove" button. """ # Create a first residue label that tells which residue has been selected. self.res1_label = QtWidgets.QLabel(self.text1) self.res1_label.setStyleSheet(small_font_style) self.res1_label.setAlignment(QtCore.Qt.AlignCenter) self.parent.loop_selector_frame_layout.addWidget( self.res1_label, self.row, 0) # Second residue label. self.res2_label = QtWidgets.QLabel(self.text2) self.res2_label.setStyleSheet(small_font_style) self.res2_label.setAlignment(QtCore.Qt.AlignCenter) self.parent.loop_selector_frame_layout.addWidget( self.res2_label, self.row, 1) # Adds the "Remove" button. self.remove_loop_button = QtWidgets.QPushButton("Remove") self.remove_loop_button.setStyleSheet(small_font_style) self.remove_loop_button.clicked.connect(self.press_remove_button) self.parent.loop_selector_frame_layout.addWidget( self.remove_loop_button, self.row, 2)
def setupUi(self, Dialog): # Based on auto-generated code from ui file from pymol.Qt import QtCore, QtWidgets Dialog.resize(400, 50) self.gridLayout = QtWidgets.QGridLayout(Dialog) label = QtWidgets.QLabel("Select loaded object:", Dialog) self.gridLayout.addWidget(label, 0, 0, 1, 1) self.select_object_combo_box = QtWidgets.QComboBox(Dialog) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) self.select_object_combo_box.setSizePolicy(sizePolicy) self.select_object_combo_box.setEditable(True) self.gridLayout.addWidget(self.select_object_combo_box, 0, 1, 1, 1) label = QtWidgets.QLabel("Select loaded object:", Dialog) self.gridLayout.addWidget(label, 1, 0, 1, 1) self.select_object_combo_box2 = QtWidgets.QComboBox(Dialog) self.select_object_combo_box2.setSizePolicy(sizePolicy) self.select_object_combo_box2.setEditable(True) self.gridLayout.addWidget(self.select_object_combo_box2, 1, 1, 1, 1) self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok) self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 2) self.buttonBox.accepted.connect(Dialog.accept) self.buttonBox.rejected.connect(Dialog.reject)
def __init__( self, label_text="New scalebar", slider_value=1, slider_from=1, slider_to=10, slider_resoution=1, # slider_digits=3, slider_tickinterval=1, slider_use_float=False, slider_use_float_val=100.0, slider_binding=None, slider_width=None): PyMod_form_item.__init__(self) # Label. self.label = QtWidgets.QLabel(label_text) # Layout for the input widget and its label. self.input = QtWidgets.QHBoxLayout() # Adds a slider. self.slider = QtWidgets.QSlider() self.slider.setOrientation(QtCore.Qt.Horizontal) self.slider.setTickPosition(QtWidgets.QSlider.TicksBelow) self.slider_use_float = slider_use_float self.slider_use_float_val = slider_use_float_val self.slider.slider_resoution = slider_resoution self.slider.setMinimum(self._get_slider_val(slider_from, internal=True)) self.slider.setMaximum(self._get_slider_val(slider_to, internal=True)) self.slider.setValue(self._get_slider_val(slider_value, internal=True)) self.slider.setTickInterval( self._get_slider_val(slider_tickinterval, internal=True)) self.slider.setSingleStep( self._get_slider_val(slider_resoution, internal=True)) self.slider.setPageStep( self._get_slider_val(slider_tickinterval, internal=True)) self.slider.valueChanged.connect(self._on_slider_change) self.slider.sliderPressed.connect(self._on_slider_pressed) self.slider.sliderReleased.connect(self._on_slider_release) self.on_drag = False self.input.addWidget(self.slider) # Add a label on the right of the slider. self.slider_label = QtWidgets.QLabel(str(slider_to)) self.input.addWidget(self.slider_label) if slider_width: self.slider.setFixedWidth(slider_width) self.slider_label.setFixedWidth( self.slider_label.sizeHint().width()) self.slider_label.setText(str(slider_value)) self.slider_binding = slider_binding
def build_modeling_protocol_main_page(self): """ Starts to insert content in the "Main" page. """ # Builds a frame for each modeling_cluster. for (i, modeling_cluster) in enumerate( self.protocol.modeling_clusters_list): # Add a spacer to separate the sections for each modeling cluster. if i != 0 and self.protocol.multiple_chain_mode: spacer_frame = QtWidgets.QFrame() spacer_frame.setFrameShape(QtWidgets.QFrame.HLine) spacer_frame.setFrameShadow(QtWidgets.QFrame.Sunken) self.main_page_interior_layout.addRow(spacer_frame) show_symmetry_restraints_option = False # Widgets necessary to choose the templates for a single target sequence. modeling_option_label = QtWidgets.QLabel( "Modeling options for target: %s" % (modeling_cluster.target_name)) modeling_option_label.setStyleSheet(modeling_window_title_style) self.main_page_interior_layout.addRow(modeling_option_label) if self.protocol.multiple_chain_mode: # Use symmetry restraints option. if modeling_cluster.symmetry_restraints_id != None: show_symmetry_restraints_option = True symmetry_checkbox, symmetry_info = self.build_symmetry_restraints_option( modeling_cluster) if any((show_symmetry_restraints_option, )): # This might include other flags in future releases. additional_options_label = QtWidgets.QLabel( "Restraints options") additional_options_label.setStyleSheet( modeling_options_sections_style) self.main_page_interior_layout.addRow(additional_options_label) if show_symmetry_restraints_option: self.main_page_interior_layout.addRow( symmetry_checkbox, symmetry_info) # Build a series of widgets for loop ranges selection. modeling_option_label = QtWidgets.QLabel("Loop selection") modeling_option_label.setStyleSheet( modeling_options_sections_style) self.main_page_interior_layout.addRow(modeling_option_label) # Build a 'User_loop_selector_frame' object, which will contain information about # user-defined loops for this target. uls = User_loop_selector_frame_qt( parent=None, parent_window=self, modeling_cluster=modeling_cluster) modeling_cluster.user_loop_selector_frame = uls self.main_page_interior_layout.addRow(uls)
def __init__(self, label_text="Input", value=""): PyMod_form_item.__init__(self) # Label. self.label = QtWidgets.QLabel(label_text) # Second Entry. self.right_label = QtWidgets.QLabel(value) self.right_label.setWordWrap(True) self.input = self.right_label
def initUI(self): self.setWindowTitle(self.title) vertical_layout = QtWidgets.QVBoxLayout() self.thread_progressbar = QtWidgets.QProgressBar(self) if self.progress: self.thread_progressbar.setMinimum(0) self.thread_progressbar.setMaximum(0) progressbar_label = "Computing..." # "Wait for the protocol to complete." self.thread_progressbar.setFormat(progressbar_label) self.thread_progressbar.setValue(0) vertical_layout.addWidget(self.thread_progressbar) self.thread_progress_label = QtWidgets.QLabel(self.label_text, self) self.thread_progress_label.setWordWrap(True) vertical_layout.addWidget(self.thread_progress_label) # Button for canceling the execution of the thread. horizontal_layout = QtWidgets.QHBoxLayout() self.cancel_button = QtWidgets.QPushButton('Cancel', self) self.cancel_button.clicked.connect(self.on_cancel_button_click) self.cancel_button.setEnabled(not self.lock) horizontal_layout.addWidget(self.cancel_button) vertical_layout.addLayout(horizontal_layout) self.setLayout(vertical_layout)
def display_options(self, single_tool): """ Displays at list of option in the the target_frame contained in a target widget. Used in the PyMod options window. """ # Check that at least one parameter if not any([p.show_widget for p in single_tool.parameters]): return None self.tools_params_dict[single_tool.name] = {} # Grids a label with the name of the tool. tool_full_name_label = QtWidgets.QLabel(single_tool.full_name) tool_full_name_label.setStyleSheet(options_title_style) # print(dir(tool_full_name_label)) # print(tool_full_name_label.font().size()) self.middle_formlayout.addWidget(tool_full_name_label, self.row_counter, 0) self.row_counter += 1 # Actually grids the parmater widgets. for parameter in single_tool.parameters: if not parameter.show_widget: continue # If the display options return a widget, adds it ot the Tool list of parameter widgets. w = self.display_paramenter_options(parameter) self.row_counter += 1
def initUI(self): self.setWindowTitle('PyMod Directory Selection') self.vertical_layout = QtWidgets.QVBoxLayout() # Main label. self.label = QtWidgets.QLabel( "Select a folder inside which to build the 'PyMod Directory'", self) self.vertical_layout.addWidget(self.label) # Entry and "Browse" button. self.horizontal_layout = QtWidgets.QHBoxLayout() self.main_entry = QtWidgets.QLineEdit(self.pymod.home_directory, self) self.main_entry.setStyleSheet("background-color: white; color: black") self.horizontal_layout.addWidget(self.main_entry) self.browse_button = QtWidgets.QPushButton("BROWSE", self) self.browse_button.clicked.connect(self.pymod_directory_browse_state) self.horizontal_layout.addWidget(self.browse_button) self.vertical_layout.addLayout(self.horizontal_layout) # "Submit" button. self.submit_button = QtWidgets.QPushButton("SUBMIT", self) self.submit_button.setFixedWidth(self.submit_button.sizeHint().width()) self.submit_button.clicked.connect(self.on_submit_button_press) self.vertical_layout.addWidget(self.submit_button) self.vertical_layout.setAlignment(self.submit_button, QtCore.Qt.AlignCenter) # Set the layouts. self.setLayout(self.vertical_layout)
def __init__(self, label_text="Input", buttons=[]): PyMod_form_item.__init__(self) # Label. self.label = QtWidgets.QLabel(label_text) # Buttons. self.input = QtWidgets.QVBoxLayout() if not buttons: raise ValueError("Please provide a list of button names") if len(buttons) != len(set(buttons)): raise ValueError("Please provide a non redundant list of buttons") self.button_group = QtWidgets.QButtonGroup() self.buttons_names = [] self.buttons_dict = {} for button_name in buttons: button = QtWidgets.QPushButton(button_name) button.setCheckable(True) self.input.addWidget(button) self.buttons_names.append(button_name) self.buttons_dict[button_name] = button self.button_group.addButton(button)
def __init__(self, label_text="Input", value="", readonly=False, style=None, enter_command=None, validate={}): PyMod_form_item.__init__(self) # Label. self.label = QtWidgets.QLabel(label_text) # Entry. self.entry = PyMod_entry_qt(value) self.enter_command = enter_command if self.enter_command is not None: self.entry.returnPressed.connect(self.enter_command) if readonly: self.entry.setReadOnly(True) if style is not None: self.entry.setStyleSheet(style) else: self.entry.setStyleSheet(active_entry_style) self.validate = validate if self.validate: self.entry.set_pmw_validator(self.validate) self.input = self.entry
def show_advanced_button(self): self.advance_options_button = QtWidgets.QPushButton( "Show Advanced Options") self.advance_options_button.clicked.connect( self.toggle_advanced_options) self._advanced_options_label = QtWidgets.QLabel("") self.middle_formlayout.addRow(self.advance_options_button, self._advanced_options_label)
def __init__(self, label_text="Input"): PyMod_form_item.__init__(self) # Label. self.label = QtWidgets.QLabel(label_text) # Hbox. self.hbox = QtWidgets.QHBoxLayout() self.input = self.hbox
def _get_scene_image_label(self, scene_pix_map): ''' Takes in the QPixmap from get_scene_png and uses it to create a label displaying the thumbnail. In the future, this function will generate its own QPixmap object from the PNG buffer stored with the scene. ''' scene_image_label = QtWidgets.QLabel(self) scene_image_label.setPixmap(scene_pix_map) return scene_image_label
def initUI(self): self.loop_selector_frame_layout = QtWidgets.QGridLayout() self.setLayout(self.loop_selector_frame_layout) label_text = "Select two residues for a loop" self.modeling_cluster_loop_selection_label = QtWidgets.QLabel( label_text) self.modeling_cluster_loop_selection_label.setStyleSheet( modeling_options_subsections_style) self.loop_selector_frame_layout.addWidget( self.modeling_cluster_loop_selection_label, 0, 0, 1, 3)
def build_alignment_mode_frame(self): """ Builds a frame with some options to choose the alignment mode. """ # Vbox which will store all the widgets for the alignment mode options. self.alignment_mode_vbox = QtWidgets.QVBoxLayout() self.alignment_mode_label = QtWidgets.QLabel("Alignment Mode") self.alignment_mode_vbox.addWidget(self.alignment_mode_label) self.alignment_mode_button_group = QtWidgets.QButtonGroup() self.build_strategy_specific_modes_frames() # Defined in child classes. self.middle_formlayout.addRow(self.alignment_mode_vbox)
def build_protocol_middle_frame(self): # Add the buttons to choose the database in which to search for domain profiles. if self.protocol.father_protocol.domain_search_mode == 'remote': self.hmmer_database_rds = PyMod_radioselect_qt( label_text="Database Selection", buttons=("PFAM", "Gene3D")) for button in self.hmmer_database_rds.get_buttons(): button.clicked.connect(self.database_opt_cmd) elif self.protocol.father_protocol.domain_search_mode == 'local': # Build the list of database names. self.protocol.hmmscan_db_dict = { } # This dictionary associates a database code (displayed in the GUI) to its filename. db_list = [] for db_filename in self.protocol.hmmscan_db_list: db_name = "".join(db_filename.split(".")[0:-2]) db_list.append(db_name) self.protocol.hmmscan_db_dict[db_name] = db_filename # Packs the PHMMER database selection widget. self.hmmer_database_rds = PyMod_radioselect_qt( label_text="Database Selection", buttons=db_list) self.middle_formlayout.add_widget_to_align(self.hmmer_database_rds) # E-value selection. self.e_value_threshold_enf = PyMod_entryfield_qt( label_text="E-value Threshold", value="1.0", validate={ 'validator': 'real', 'min': 0.0, 'max': 1000.0 }) self.middle_formlayout.add_widget_to_align(self.e_value_threshold_enf) # Note about the Gene3D and Evalues. if self.protocol.father_protocol.domain_search_mode == 'remote': info_note = ('Note: The Gene3D online database will\n' 'ignore custom cut-off parameters since\n' 'they use a post processing step that\n' 'involves preset thresholds.') self.notelabel = QtWidgets.QLabel(info_note) self.middle_formlayout.addRow(self.notelabel) self.middle_formlayout.set_input_widgets_width(140)
def _build_table_elements(self, parent): ''' Create the various elements in the table and add them to the proper layout. ''' self.setWindowTitle('Scene Panel') layout = QtWidgets.QVBoxLayout(self) self.setLayout(layout) top_layout = QtWidgets.QGridLayout() layout.addLayout(top_layout) mid_layout = QtWidgets.QGridLayout() layout.addLayout(mid_layout) low_layout = QtWidgets.QGridLayout() layout.addLayout(low_layout) # Top Elements self.instructionLabel = QtWidgets.QLabel(self) self.instructionLabel.setText( 'Double click selected thumbnail to \nload into Workspace.') top_layout.addWidget(self.instructionLabel, 0, 0) self.addSceneButton = QtWidgets.QPushButton(self) self.addSceneButton.setText('Add Scene') top_layout.addWidget(self.addSceneButton, 0, 1) # Mid Elements self.sceneTableWidget = QtWidgets.QTableWidget(self) mid_layout.addWidget(self.sceneTableWidget, 0, 0) self.sceneTableWidget.viewport().installEventFilter(self) self.sceneTableWidget.itemChanged.connect(self._item_changed) self.sceneTableWidget.selectionModel().selectionChanged.connect( self._selection_changed) self.sceneTableWidget.setSelectionBehavior( QtWidgets.QAbstractItemView.SelectRows) self.sceneTableWidget.verticalHeader().setSectionsMovable(True) # Lower Buttom Elements self.deleteButton = QtWidgets.QPushButton(self) self.deleteButton.setText("Delete Scene") low_layout.addWidget(self.deleteButton, 0, 1) self.deleteButton.setEnabled(False) self.updateButton = QtWidgets.QPushButton(self) self.updateButton.setText("Update Scene") low_layout.addWidget(self.updateButton, 0, 0) self.updateButton.setEnabled(False)
def __init__(self, label_text="Input", items=[]): PyMod_form_item.__init__(self) # Label. self.label = QtWidgets.QLabel(label_text) # Combobox. self.combobox = QtWidgets.QComboBox() if not items: raise ValueError("Please provide a list of items for the combobox") self.items = items for item in self.items: self.combobox.addItem(item) self.combobox.setEditable(False) self.input = self.combobox
def initUI(self): self.setWindowTitle('Import PDB Options') vertical_layout = QtWidgets.QVBoxLayout() # Installation options label. info_text = "Please select the 3D structure import mode:" self.fetch_info_label = QtWidgets.QLabel(info_text, self) # self.fetch_info_label.setStyleSheet(label_style_1) vertical_layout.addWidget(self.fetch_info_label) vertical_layout.addStretch(1) # Import options radiobuttons. horizontal_layout = QtWidgets.QHBoxLayout() self.import_all_radiobutton = QtWidgets.QRadioButton( "Import in PyMod the structure of every chain of the PDB files.") # self.import_all_radiobutton.setChecked(True) # self.import_all_radiobutton.setStyleSheet(label_font_1) vertical_layout.addWidget(self.import_all_radiobutton) self.import_fragment_radiobutton = QtWidgets.QRadioButton( "Import in PyMod only the structure of the hit sequences fragments." ) # label_font_1 self.import_fragment_radiobutton.setStyleSheet("margin-bottom: 10px") vertical_layout.addWidget(self.import_fragment_radiobutton) # Import fragments button. self.import_button = QtWidgets.QPushButton("Import 3D Structures", self) # self.import_button.setStyleSheet(label_style_2) self.import_button.clicked.connect(self.on_import_button_click) horizontal_layout.addWidget(self.import_button) horizontal_layout.addStretch(1) # Cancel button. self.cancel_button = QtWidgets.QPushButton('Cancel', self) # self.cancel_button.setStyleSheet(label_style_2) self.cancel_button.clicked.connect(self.on_cancel_button_click) horizontal_layout.addWidget(self.cancel_button) vertical_layout.addLayout(horizontal_layout) self.setLayout(vertical_layout)
def __init__(self, label_text="Input", value=1, spinbox_min=1, spinbox_max=100): PyMod_form_item.__init__(self) # Label. self.label = QtWidgets.QLabel(label_text) # Spinbox. self.spinbox = QtWidgets.QSpinBox() self.spinbox_min = spinbox_min self.spinbox_max = spinbox_max self.spinbox.setRange(self.spinbox_min, self.spinbox_max) self.spinbox.setStyleSheet(active_entry_style) self.input = self.spinbox
def __init__(self, label_text="Input", value="", style=None): PyMod_form_item.__init__(self) # Label. self.label = QtWidgets.QLabel(label_text) # Entry. self.entry = QtWidgets.QPlainTextEdit(value) if style is not None: self.entry.setStyleSheet(style) else: self.entry.setStyleSheet(active_entry_style) self.entry.setWordWrapMode(QtGui.QTextOption.WrapAnywhere) expanding_size_policy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) expanding_size_policy.setVerticalStretch(1) self.entry.setSizePolicy(expanding_size_policy) self.input = self.entry
def add_qt_menu_command(parent, label, command=None, fg_color=None, bg_color=None): """ Adds to a 'parent' QMenu widget a new menu item. """ # Color the label of the menu item. if fg_color != None: action = QtWidgets.QWidgetAction(parent) label_widget = QtWidgets.QLabel(label) s = """QLabel { background-color: %s; color: %s; padding: 3px; } QLabel:hover { background-color: #466e82; color: %s; }""" % (bg_color, fg_color, fg_color) label_widget.setStyleSheet(s) action.setDefaultWidget(label_widget) # Don't color, use a regular 'QAction' object. else: action = QtWidgets.QAction(label, parent) # Associates a command. if command is not None: action.triggered.connect(command) parent.addAction(action) return action
def load_aln_dialog(parent, filename, format): _self = parent.cmd import numpy import difflib import pymol.seqalign as seqalign try: # for fasta format, this only succeeds if all sequences have the # same length, raises ValueError otherwise alignment = seqalign.aln_magic_read(filename) # a single sequence is not an aligment if format == "fasta" and len(alignment) < 2: raise ValueError except ValueError: # fasta files which don't contain alignments will be loaded as # extended structures (fab command) instead _self.load(filename) return # alignment record ids and PyMOL model names ids = [rec.id for rec in alignment] ids_remain = list(ids) models = _self.get_object_list() models_remain = list(models) mapping = {} N = len(ids) M = len(models) # ids -> models similarity matrix similarity = numpy.zeros((N, M)) for i in range(N): for j in range(M): similarity[i, j] = difflib.SequenceMatcher(None, ids[i], models[j], False).ratio() # guess mapping for _ in range(min(N, M)): i, j = numpy.unravel_index(similarity.argmax(), similarity.shape) mapping[ids_remain.pop(i)] = models_remain.pop(j) similarity = numpy.delete(similarity, i, axis=0) similarity = numpy.delete(similarity, j, axis=1) form = parent.load_form('load_aln') comboboxes = {} # mapping GUI for row, rec_id in enumerate(ids, 1): label = QtWidgets.QLabel(rec_id, form._dialog) combobox = QtWidgets.QComboBox(form._dialog) combobox.addItem("") combobox.addItems(models) combobox.setCurrentText(mapping.get(rec_id, "")) form.layout_mapping.addWidget(label, row, 0) form.layout_mapping.addWidget(combobox, row, 1) comboboxes[rec_id] = combobox def run(): mapping = dict((rec_id, combobox.currentText()) for (rec_id, combobox) in comboboxes.items()) seqalign.load_aln_multi(filename, mapping=mapping, _self=_self) form._dialog.close() def cancel(): form._dialog.close() if format == 'fasta' and QtWidgets.QMessageBox.question( parent, "Load as structures?", "Load sequences as extended structures instead?" ) == QtWidgets.QMessageBox.Yes: _self.load(filename) # hook up events form.button_ok.clicked.connect(run) form.button_cancel.clicked.connect(cancel) form._dialog.setModal(True) form._dialog.show()
def load_aln_dialog(parent, filename): _self = parent.cmd import numpy import difflib import pymol.seqalign as seqalign try: alignment = seqalign.aln_magic_read(filename) except ValueError: # fails for fasta files which don't contain alignments _self.load(filename) return # alignment record ids and PyMOL model names ids = [rec.id for rec in alignment] ids_remain = list(ids) models = _self.get_object_list() models_remain = list(models) mapping = {} N = len(ids) M = len(models) # ids -> models similarity matrix similarity = numpy.zeros((N, M)) for i in range(N): for j in range(M): similarity[i, j] = difflib.SequenceMatcher(None, ids[i], models[j], False).ratio() # guess mapping for _ in range(min(N, M)): i, j = numpy.unravel_index(similarity.argmax(), similarity.shape) mapping[ids_remain.pop(i)] = models_remain.pop(j) similarity = numpy.delete(similarity, i, axis=0) similarity = numpy.delete(similarity, j, axis=1) form = parent.load_form('load_aln') comboboxes = {} # mapping GUI for row, rec_id in enumerate(ids, 1): label = QtWidgets.QLabel(rec_id, form._dialog) combobox = QtWidgets.QComboBox(form._dialog) combobox.addItem("") combobox.addItems(models) combobox.setCurrentText(mapping.get(rec_id, "")) form.layout_mapping.addWidget(label, row, 0) form.layout_mapping.addWidget(combobox, row, 1) comboboxes[rec_id] = combobox def run(): mapping = dict((rec_id, combobox.currentText()) for (rec_id, combobox) in comboboxes.items()) seqalign.load_aln_multi(filename, mapping=mapping, _self=_self) form._dialog.close() # hook up events form.button_ok.clicked.connect(run) form.button_cancel.clicked.connect(form._dialog.close) form._dialog.setModal(True) form._dialog.show()
def __init__(self, *args, **kwargs): super(PyMod_plot_window_qt, self).__init__(*args, **kwargs) # Central widget. self.central_widget = QtWidgets.QWidget() self.setCentralWidget(self.central_widget) self.central_widget_layout = QtWidgets.QGridLayout() self.central_widget.setLayout(self.central_widget_layout) #------------------------------------------------ # Upper frame (contains the plot and controls). - #------------------------------------------------ expanding_size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) preferred_size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) # The upper frame contains three frames: info, plot and controls frames. # The infor and controls frames will be displayed only if the 'use_controls' # argument is set to 'True' when calling the 'build_plotting_area' method. self.upper_frame = QtWidgets.QFrame() self.upper_frame.setStyleSheet("background-color: #646464") self.upper_frame_layout = QtWidgets.QGridLayout() self.upper_frame.setLayout(self.upper_frame_layout) self.upper_frame.setSizePolicy(expanding_size_policy) self.central_widget_layout.addWidget(self.upper_frame, 0, 0) # Info frame, it contains the messagebar of the plot. self.info_frame = QtWidgets.QFrame() self.info_frame_layout = QtWidgets.QHBoxLayout() self.info_frame.setLayout(self.info_frame_layout) self.info_frame.setSizePolicy(preferred_size_policy) self.info_label = QtWidgets.QLabel("") self.info_frame_layout.addWidget(self.info_label) # Plot frame. self.plot_frame = QtWidgets.QFrame() # self.plot_frame.setStyleSheet("background-color: red") self.plot_frame_layout = QtWidgets.QGridLayout() self.plot_frame.setLayout(self.plot_frame_layout) self.plot_frame.setSizePolicy(expanding_size_policy) self.build_plot_widget() # Controls frame. self.controls_frame = QtWidgets.QWidget() self.controls_frame.setStyleSheet("background-color: #747474") self.controls_frame_layout = QtWidgets.QGridLayout() self.controls_frame.setLayout(self.controls_frame_layout) self.controls_frame_layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.controls_scrollarea = QtWidgets.QScrollArea() self.controls_scrollarea.setWidgetResizable(True) self.controls_scrollarea.setWidget(self.controls_frame) self.labels_title = QtWidgets.QLabel("Plots list") # Middle splitter. self.middle_splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal) self.middle_splitter.setSizePolicy(expanding_size_policy) #--------------------------------------- # Lower frame (contains some options). - #--------------------------------------- self.lower_frame = QtWidgets.QFrame() self.lower_frame_layout = QtWidgets.QGridLayout() self.lower_frame.setLayout(self.lower_frame_layout) self.central_widget_layout.addWidget(self.lower_frame, 1, 0) # View buttons. self.view_label = QtWidgets.QLabel("View:") self.lower_frame_layout.addWidget(self.view_label, 0, 0) self.home_view_button = QtWidgets.QPushButton("Fit to data") self.home_view_button.clicked.connect(self.on_home_button_click) self.lower_frame_layout.addWidget(self.home_view_button, 0, 1) # On click behaviour. The buttons will be shown later, in the # 'build_plotting_area' metohd. self.interact_buttons_group = QtWidgets.QButtonGroup() self.on_click_label = QtWidgets.QLabel("Interact on click:") self.interact_button = QtWidgets.QPushButton("Yes") self.interact_button.setCheckable(True) self.interact_buttons_group.addButton(self.interact_button) self.interact_button.clicked.connect(self.on_interact_button_click) self.no_interaction_button = QtWidgets.QPushButton("No") self.no_interaction_button.setCheckable(True) self.no_interaction_button.setChecked(True) self.interact_buttons_group.addButton(self.no_interaction_button) self.no_interaction_button.clicked.connect(self.on_no_interaction_button_click) # Show/hide all buttons. They will be shown later, in the 'build_plotting_area' # method. self.show_label = QtWidgets.QLabel("Show:") self.show_all_button = QtWidgets.QPushButton("All") self.show_all_button.clicked.connect(self.show_all_command) self.hide_all_button = QtWidgets.QPushButton("None") self.hide_all_button.clicked.connect(self.hide_all_command) self.lower_frame_layout.setAlignment(QtCore.Qt.AlignLeft) #--------------------- # Build a main menu. - #--------------------- self.save_to_csv_action = QtWidgets.QAction('Save to CSV', self) self.save_to_csv_action.triggered.connect(lambda a=None: self.save_to_csv_event()) self.save_to_png_action = QtWidgets.QAction('Save to PNG', self) self.save_to_png_action.triggered.connect(lambda a=None: self.save_to_png_event()) self.main_menubar = self.menuBar() self.file_menu = self.main_menubar.addMenu('File')
def add_plot(self, x_data, y_data, label=None, additional_data=None): """ Adds a plot to the pyqtgraph PlotWidget. """ # Check and prepare the data. if len(x_data) != len(y_data): raise ValueError(("The x series and the y series do not have the same" " number of elements (%s and %s respectively)" % (len(x_data), len(y_data)))) if additional_data: if not len(x_data) == len(additional_data): raise ValueError(("The 'additional_data' series does not have the" " same number of elements of the data to plot" " (%s and %s respectively)" % (len(x_data), len(additional_data)))) _x_data, _y_data = self.remove_none(x_data, y_data) # Add the plot to the PlotWidget. plot_color = self.plot_colors[self.plot_color_index] self.change_plot_color_index() curve_pen = pyqtgraph.mkPen(width=2, color=plot_color) # Color and width of the curve. plot_item = self.graphWidget.plot(_x_data, _y_data, name=label, connect="finite", pen=curve_pen, clickable=True) plot_item._pymod_id = self.plot_count plot_item.curve._pymod_id = self.plot_count plot_item.curve.setClickable(True) # plot_item.curve.sigClicked.connect(self.on_curve_click) plot_item.sigClicked.connect(self.on_curve_click) # Store information about the plot. self.plot_items[self.plot_count] = {} # The 'plot' key will store the pyqtgraph object for the plot. self.plot_items[self.plot_count]["plot"] = plot_item # The 'state' will be 1 if the plot is shown, and 0 it is hidden. self.plot_items[self.plot_count]["state"] = 1 # Add a label. if label is None: label = "Plot %s" % self.plot_count self.plot_items[self.plot_count]["label"] = label # Data. self.plot_items[self.plot_count]["x_data"] = x_data self.plot_items[self.plot_count]["y_data"] = y_data # Additional data. self.plot_items[self.plot_count]["additional_data"] = additional_data # Stores all the data in a single list. for idx, (xi, yi) in enumerate(zip(x_data, y_data)): if yi is not None: self.all_points.append((xi, yi)) self.all_points_info.append((self.plot_count, idx)) # Add a checkbox in the controls frame. Used for showing/hiding the plot. if self.use_controls: plot_checkbox = QtWidgets.QCheckBox(label) plot_checkbox.setStyleSheet(small_font_style) plot_checkbox.setChecked(True) plot_checkbox.clicked.connect(lambda a=None, i=self.plot_count: self.toggle_plot(i)) plot_color_label = QtWidgets.QLabel("---") # \u2796") # "\u25CF" plot_color_label.setStyleSheet("color: %s; font-weight: bold" % plot_color) self.controls_frame_layout.addWidget(plot_color_label, self.plot_count+1, 0, 1, 1) self.controls_frame_layout.addWidget(plot_checkbox, self.plot_count+1, 1, 1, 1) self.plot_items[self.plot_count]["checkbox"] = plot_checkbox # Increase the plot counter. self.plot_count += 1
def __init__(self): # noqa QtWidgets.QMainWindow.__init__(self) self.setDockOptions(QtWidgets.QMainWindow.AllowTabbedDocks | QtWidgets.QMainWindow.AllowNestedDocks) # resize Window before it is shown options = pymol.invocation.options self.resize(options.win_x + (220 if options.internal_gui else 0), options.win_y + (246 if options.external_gui else 18)) # for thread-safe viewport command self.viewportsignal.connect(self.pymolviewport) # reusable dialogs self.dialog_png = None self.advanced_settings_dialog = None self.props_dialog = None self.builder = None # setting index -> callable self.setting_callbacks = defaultdict(list) # "session_file" setting in window title self.setting_callbacks[440].append(lambda v: self.setWindowTitle( "PyMOL (" + os.path.basename(v) + ")")) # "External" Command Line and Loggin Widget self._setup_history() self.lineedit = CommandLineEdit() self.lineedit.setObjectName("command_line") self.browser = QtWidgets.QPlainTextEdit() self.browser.setObjectName("feedback_browser") self.browser.setReadOnly(True) # convenience: clicking into feedback browser gives focus to command # line. Drawback: Copying with CTRL+C doesn't work in feedback # browser -> clear focus proxy while text selected self.browser.setFocusProxy(self.lineedit) @self.browser.copyAvailable.connect def _(yes): self.browser.setFocusProxy(None if yes else self.lineedit) self.browser.setFocus() # Font self.browser.setFont(getMonospaceFont()) connectFontContextMenu(self.browser) lineeditlayout = QtWidgets.QHBoxLayout() command_label = QtWidgets.QLabel("PyMOL>") command_label.setObjectName("command_label") lineeditlayout.addWidget(command_label) lineeditlayout.addWidget(self.lineedit) self.lineedit.setToolTip('''Command Input Area Get the list of commands by hitting <TAB> Get the list of arguments for one command with a question mark: PyMOL> color ? Read the online help for a command with "help": PyMOL> help color Get autocompletion for many arguments by hitting <TAB> PyMOL> color ye<TAB> (will autocomplete "yellow") ''') layout = QtWidgets.QVBoxLayout() layout.addWidget(self.browser) layout.addLayout(lineeditlayout) quickbuttonslayout = QtWidgets.QVBoxLayout() quickbuttonslayout.setSpacing(2) extguilayout = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.LeftToRight) extguilayout.setContentsMargins(2, 2, 2, 2) extguilayout.addLayout(layout) extguilayout.addLayout(quickbuttonslayout) class ExtGuiFrame(QtWidgets.QFrame): def mouseDoubleClickEvent(_, event): self.toggle_ext_window_dockable(True) _size_hint = QtCore.QSize(options.win_x, options.ext_y) def sizeHint(self): return self._size_hint dockWidgetContents = ExtGuiFrame(self) dockWidgetContents.setLayout(extguilayout) dockWidgetContents.setObjectName("extgui") self.ext_window = \ dockWidget = QtWidgets.QDockWidget(self) dockWidget.setWindowTitle("External GUI") dockWidget.setWidget(dockWidgetContents) if options.external_gui: dockWidget.setTitleBarWidget(QtWidgets.QWidget()) else: dockWidget.hide() self.addDockWidget(Qt.TopDockWidgetArea, dockWidget) # rearrange vertically if docking left or right @dockWidget.dockLocationChanged.connect def _(area): if area == Qt.LeftDockWidgetArea or area == Qt.RightDockWidgetArea: extguilayout.setDirection(QtWidgets.QBoxLayout.BottomToTop) quickbuttonslayout.takeAt(quickbuttons_stretch_index) else: extguilayout.setDirection(QtWidgets.QBoxLayout.LeftToRight) if quickbuttons_stretch_index >= quickbuttonslayout.count(): quickbuttonslayout.addStretch() # OpenGL Widget self.pymolwidget = PyMOLGLWidget(self) self.setCentralWidget(self.pymolwidget) cmd = self.cmd = self.pymolwidget.cmd ''' # command completion completer = QtWidgets.QCompleter(cmd.kwhash.keywords, self) self.lineedit.setCompleter(completer) ''' # overload <Tab> action self.lineedit.installEventFilter(self) self.pymolwidget.installEventFilter(self) # Quick Buttons for row in [ [ ('Reset', cmd.reset), ('Zoom', lambda: cmd.zoom(animate=1.0)), ('Orient', lambda: cmd.orient(animate=1.0)), # render dialog will be constructed when the menu is shown # for the first time. This way it's populated with the current # viewport and settings. Also defers parsing of the ui file. ('Draw/Ray', WidgetMenu(self).setSetupUi(self.render_dialog)), ], [ ('Unpick', cmd.unpick), ('Deselect', cmd.deselect), ('Rock', cmd.rock), ('Get View', self.get_view), ], [ ('|<', cmd.rewind), ('<', cmd.backward), ('Stop', cmd.mstop), ('Play', cmd.mplay), ('>', cmd.forward), ('>|', cmd.ending), ('MClear', cmd.mclear), ], [ ('Builder', self.open_builder_panel), ('Properties', self.open_props_dialog), ('Rebuild', cmd.rebuild), ], ]: hbox = QtWidgets.QHBoxLayout() hbox.setSpacing(2) for name, callback in row: btn = QtWidgets.QPushButton(name) btn.setProperty("quickbutton", True) btn.setAttribute(Qt.WA_LayoutUsesWidgetRect) # OS X workaround hbox.addWidget(btn) if callback is None: btn.setEnabled(False) elif isinstance(callback, QtWidgets.QMenu): btn.setMenu(callback) else: btn.released.connect(callback) quickbuttonslayout.addLayout(hbox) # progress bar hbox = QtWidgets.QHBoxLayout() self.progressbar = QtWidgets.QProgressBar() self.progressbar.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) hbox.addWidget(self.progressbar) self.abortbutton = QtWidgets.QPushButton('Abort') self.abortbutton.setStyleSheet("background: #FF0000; color: #FFFFFF") self.abortbutton.released.connect(cmd.interrupt) hbox.addWidget(self.abortbutton) quickbuttonslayout.addLayout(hbox) quickbuttonslayout.addStretch() quickbuttons_stretch_index = quickbuttonslayout.count() - 1 # menu top level self.menubar = menubar = self.menuBar() # action groups actiongroups = {} def _addmenu(data, menu): '''Fill a menu from "data"''' menu.setTearOffEnabled(True) menu.setWindowTitle(menu.title()) # needed for Windows for item in data: if item[0] == 'separator': menu.addSeparator() elif item[0] == 'menu': _addmenu(item[2], menu.addMenu(item[1].replace('&', '&&'))) elif item[0] == 'command': command = item[2] if command is None: print('warning: skipping', item) else: if isinstance(command, str): command = lambda c=command: cmd.do(c) menu.addAction(item[1], command) elif item[0] == 'check': if len(item) > 4: menu.addAction( SettingAction(self, cmd, item[2], item[1], item[3], item[4])) else: menu.addAction( SettingAction(self, cmd, item[2], item[1])) elif item[0] == 'radio': label, name, value = item[1:4] try: group, type_, values = actiongroups[item[2]] except KeyError: group = QtWidgets.QActionGroup(self) type_, values = cmd.get_setting_tuple(name) actiongroups[item[2]] = group, type_, values action = QtWidgets.QAction(label, self) action.triggered.connect(lambda _=0, args=(name, value): cmd.set(*args, log=1, quiet=0)) self.setting_callbacks[cmd.setting._get_index( name)].append( lambda v, V=value, a=action: a.setChecked(v == V)) group.addAction(action) menu.addAction(action) action.setCheckable(True) if values[0] == value: action.setChecked(True) elif item[0] == 'open_recent_menu': self.open_recent_menu = menu.addMenu('Open Recent...') else: print('error:', item) # recent files menu self.open_recent_menu = None # for plugins self.menudict = {'': menubar} # menu for _, label, data in self.get_menudata(cmd): assert _ == 'menu' menu = menubar.addMenu(label) self.menudict[label] = menu _addmenu(data, menu) # hack for macOS to hide "Edit > Start Dictation" # https://bugreports.qt.io/browse/QTBUG-43217 if pymol.IS_MACOS: self.menudict['Edit'].setTitle('Edit_') QtCore.QTimer.singleShot( 10, lambda: self.menudict['Edit'].setTitle('Edit')) # recent files menu if self.open_recent_menu: @self.open_recent_menu.aboutToShow.connect def _(): self.open_recent_menu.clear() for fname in self.recent_filenames: self.open_recent_menu.addAction( fname if len(fname) < 128 else '...' + fname[-120:], lambda fname=fname: self.load_dialog(fname)) # some experimental window control menu = self.menudict['Display'].addSeparator() menu = self.menudict['Display'].addMenu('External GUI') menu.addAction('Toggle floating', self.toggle_ext_window_dockable, QtGui.QKeySequence('Ctrl+E')) ext_vis_action = self.ext_window.toggleViewAction() ext_vis_action.setText('Visible') menu.addAction(ext_vis_action) # extra key mappings (MacPyMOL compatible) QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl+O'), self).activated.connect(self.file_open) QtWidgets.QShortcut(QtGui.QKeySequence('Ctrl+S'), self).activated.connect(self.session_save) # feedback self.feedback_timer = QtCore.QTimer() self.feedback_timer.setSingleShot(True) self.feedback_timer.timeout.connect(self.update_feedback) self.feedback_timer.start(100) # legacy plugin system self.menudict['Plugin'].addAction('Initialize Plugin System', self.initializePlugins) # focus in command line if options.external_gui: self.lineedit.setFocus() else: self.pymolwidget.setFocus() # Apply PyMOL stylesheet try: with open( cmd.exp_path('$PYMOL_DATA/pmg_qt/styles/pymol.sty')) as f: style = f.read() except IOError: print('Could not read PyMOL stylesheet.') print('DEBUG: PYMOL_DATA=' + repr(os.getenv('PYMOL_DATA'))) style = "" if style: self.setStyleSheet(style)
def create_dialog(): dialog = QtWidgets.QDialog() dialog.setWindowTitle('Lighting Settings') sliders = [ "Diffuse Reflection", ('ambient', 0, 1, None), ('reflect', -1, 1, None), "Direct Light from Front", ('direct (+reflect)', -1, 1, None), # diffuse, coupled with "reflect" ('spec_direct', 0, 1, None), ('spec_direct_power', 0, 100, 1), "Free placeable directed Lights", ('light_count', 1, 8, 1), ('edit_light', 1, 7, 1), "Specular Reflection", ('spec_count', -1, 8, 1), # ('spec_power', -1, 200, 1), # deprecated since v1.5 ('shininess', 0, 100, None), # same as spec_power ('spec_reflect', -0.01, 1, None), ('specular', 0, 1, None), ('specular_intensity (=specular)', 0, 1, None), # same as specular "Ambient Occlusion (Surface only)", ('ambient_occlusion_mode', 0, 2, 1), ('ambient_occlusion_scale', 1.0, 50., None), ('ambient_occlusion_smooth', 1, 20, 1), "Ray trace only", ('power', 1, 10, None), ('reflect_power', 1, 10, None), ] layout = QtWidgets.QVBoxLayout(dialog) button_layout = QtWidgets.QHBoxLayout() layout.addLayout(button_layout) layout.setContentsMargins(5, 0, 5, 0) button_layout.addWidget( QtWidgets.QLabel("<font color=red>Presets:</font>")) presets = [ ("Default", preset_default), ("Metal", preset_metal), ("Plastic", preset_plastic), ("Rubber", preset_rubber), ("X-Ray", preset_xray), ] for name, fun in presets: btn = QtWidgets.QPushButton(name, dialog) btn.pressed.connect(fun) btn.setAutoDefault(False) button_layout.addWidget(btn) form_layout = QtWidgets.QFormLayout() form_layout.setContentsMargins(0, 0, 0, 0) form_layout.setVerticalSpacing(0) form_layout.setLabelAlignment(Qt.AlignLeft) layout.addLayout(form_layout) for i, item in enumerate(sliders, 1): if isinstance(item, str): label = QtWidgets.QLabel("<font color=blue>" + item + "</font>") form_layout.addRow(label) continue name, min, max, res = item if res is None: res = 0.01 if (max - min < 100) else 0.1 line_edit = QtWidgets.QLineEdit(dialog) slider = SettingSlider(dialog, name.split()[0], min, max, res, line_edit) h_layout = QtWidgets.QHBoxLayout() h_layout.addWidget(slider, 3) h_layout.addWidget(line_edit, 1) form_layout.addRow(name, h_layout) return dialog
def initialize_map(self, pymod, data_array, pymod_elements, ref_residues, ref_selectors, title=None, pixel_size=5, feature_type="contact", threshold=8.0, interaction_center="ca"): # Sets the attributes. self.data_array = data_array self.pixel_size = pixel_size self.feature_type = feature_type self.threshold = threshold self.interaction_center = interaction_center if self.feature_type in ("contact", "distance"): self.pymod_elements = pymod_elements self.pymod_element = self.pymod_elements[0] else: self.pymod_elements = pymod_elements # Get the PyMod residues for each residue having an interaction center and the PyMOL selectors # for each residue. self.ref_residues = ref_residues self.ref_selectors = ref_selectors # Assign the methods to get the labels. if self.feature_type == "contact": self.get_value_label = self._get_value_label_contact elif self.feature_type == "distance": self.get_value_label = self._get_value_label_distance elif self.feature_type == "distances_difference": self.get_value_label = self._get_value_label_distance_diff elif self.feature_type == "distances_mean": self.get_value_label = self._get_value_label_distance_mean elif self.feature_type == "distances_std": self.get_value_label = self._get_value_label_distance_std else: raise KeyError(self.feature_type) # Set the canvas size. min_size = 150 h = self.pixel_size * len(self.data_array) win_size = min((910, h)) win_size = max((min_size, win_size)) if title: self.setWindowTitle(title) # Set some appearance parameters. self.controls_padding = 4 if self.feature_type in ("contact", "distance"): self.controls_font = "helvetica 11 bold" else: self.controls_font = "helvetica 10 bold" self.controls_config = { "fg": "black", "font": self.controls_font, "padx": self.controls_padding, "pady": self.controls_padding } self.labels_pack_config = { "side": "left", "pady": (0, 5), "padx": (5, 0) } self.buttons_pack_config = { "side": "left", "pady": (0, 5), "padx": (1, 0) } # Frame of the window containing a row for some control buttons, a row for # the plot and a row for a messagebar. self.plot_frame = QtWidgets.QWidget() self.plot_frame_layout = QtWidgets.QGridLayout() self.plot_frame.setLayout(self.plot_frame_layout) self.setCentralWidget(self.plot_frame) # Control frame. self.controls_frame = QtWidgets.QWidget() self.controls_frame_layout = QtWidgets.QGridLayout() self.controls_frame.setLayout(self.controls_frame_layout) self.plot_frame_layout.addWidget(self.controls_frame) self.delete_distances_button = QtWidgets.QPushButton( "Delete all distances in PyMOL") self.delete_distances_button.setEnabled(False) self.delete_distances_button.clicked.connect( lambda a=None: self.clear_plot()) self.controls_frame_layout.addWidget(self.delete_distances_button, 0, 0) self.scale_factor = 0 self.scale_down_button = QtWidgets.QPushButton("Zoom out") try: self.scale_down_button.setIcon(QtGui.QIcon.fromTheme("go-down")) except: pass self.scale_down_button.clicked.connect( lambda a=None: self.scale_plot_down()) self.controls_frame_layout.addWidget(self.scale_down_button, 0, 1) self.scale_up_button = QtWidgets.QPushButton("Zoom in") try: self.scale_up_button.setIcon(QtGui.QIcon.fromTheme("go-up")) except: pass self.scale_up_button.clicked.connect( lambda a=None: self.scale_plot_up()) self.controls_frame_layout.addWidget(self.scale_up_button, 0, 2) self.controls_frame_layout.setAlignment(QtCore.Qt.AlignLeft) # Frame containing the plot (with a scrollbar). self.canvas_plot_frame = QtWidgets.QWidget() self.canvas_plot_frame.setStyleSheet("background-color: white") self.canvas_plot_frame_layout = QtWidgets.QGridLayout() self.canvas_plot_frame.setLayout(self.canvas_plot_frame_layout) self.canvas_plot_scrollarea = QtWidgets.QScrollArea() self.canvas_plot_scrollarea.setWidgetResizable(True) self.canvas_plot_scrollarea.setWidget(self.canvas_plot_frame) self.plot_frame_layout.addWidget(self.canvas_plot_scrollarea) # Builds the scene where to draw the contact map. self.canvas_plot_scene = QtWidgets.QGraphicsScene() # Builds the graphics view containing the scene above. self.canvas_plot_view = Contact_map_graphics_view( self.canvas_plot_scene) self.canvas_plot_frame_layout.addWidget(self.canvas_plot_view) # A bottom frame fo the window, containing some buttons to interact with the graph. self.message_frame = QtWidgets.QFrame() self.message_frame_layout = QtWidgets.QHBoxLayout() self.message_frame.setLayout(self.message_frame_layout) self.plot_frame_layout.addWidget(self.message_frame) # Label to show which residue/position pair is currently being hovered by the mouse pointer. if self.feature_type in ("contact", "distance"): view_label_text = "Couple:" else: view_label_text = "Alignment positions:" self.view_label = QtWidgets.QLabel(view_label_text) # self.view_label.setStyleSheet(self.controls_config) self.message_frame_layout.addWidget(self.view_label) # Actually draws the contact map. self.draw_map()
def initialize_plot(self, pymod, target_element, residues_tags, plot_title, aa_list): self.pymod = pymod self.target_element = target_element self.residues_tags = residues_tags self.plot_title = plot_title self.setWindowTitle("%s Ramachandran Plot" % self.target_element.my_header) self.aa_list = aa_list # Frame of the window containing a row for some control buttons, a row for # the plot and a row for a messagebar. self.plot_frame = QtWidgets.QWidget() self.plot_frame_layout = QtWidgets.QGridLayout() self.plot_frame.setLayout(self.plot_frame_layout) self.setCentralWidget(self.plot_frame) # Control frame. self.controls_frame = QtWidgets.QWidget() self.controls_frame_layout = QtWidgets.QGridLayout() self.controls_frame.setLayout(self.controls_frame_layout) self.plot_frame_layout.addWidget(self.controls_frame, 0, 0) self.scale_factor = 0 self.scale_down_button = QtWidgets.QPushButton("Zoom out") try: self.scale_down_button.setIcon(QtGui.QIcon.fromTheme("go-down")) except: pass self.scale_down_button.clicked.connect( lambda a=None: self.scale_plot_down()) self.controls_frame_layout.addWidget(self.scale_down_button, 0, 0) self.scale_up_button = QtWidgets.QPushButton("Zoom in") try: self.scale_up_button.setIcon(QtGui.QIcon.fromTheme("go-up")) except: pass self.scale_up_button.clicked.connect( lambda a=None: self.scale_plot_up()) self.controls_frame_layout.addWidget(self.scale_up_button, 0, 1) self.controls_frame_layout.setAlignment(QtCore.Qt.AlignLeft) # Frame containing the plot (with a scrollbar). self.canvas_plot_frame = QtWidgets.QWidget() self.canvas_plot_frame.setStyleSheet("background-color: white") self.canvas_plot_frame_layout = QtWidgets.QGridLayout() self.canvas_plot_frame.setLayout(self.canvas_plot_frame_layout) self.canvas_plot_scrollarea = QtWidgets.QScrollArea() self.canvas_plot_scrollarea.setWidgetResizable(True) self.canvas_plot_scrollarea.setWidget(self.canvas_plot_frame) self.plot_frame_layout.addWidget(self.canvas_plot_scrollarea, 1, 0) self.default_pen = QtGui.QPen(QtGui.QColor(0, 0, 0, 255), 1) self.default_brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 230)) self.highlight_brush = QtGui.QBrush(QtGui.QColor(255, 0, 255)) self.highlight_region_brush = QtGui.QBrush(QtGui.QColor(0, 255, 255)) # Builds the scene where to draw the Ramachandran plot. self.canvas_plot_scene = QtWidgets.QGraphicsScene() # Builds the graphics view containing the scene above. self.canvas_plot_view = QtWidgets.QGraphicsView(self.canvas_plot_scene) self.canvas_plot_frame_layout.addWidget(self.canvas_plot_view) # A bottom frame fo the window, containing some buttons to interact with the graph. self.message_frame = QtWidgets.QFrame() self.message_frame_layout = QtWidgets.QFormLayout() self.message_frame.setLayout(self.message_frame_layout) self.plot_frame_layout.addWidget(self.message_frame, 1, 1) # Label to show which residue/position pair is currently being hovered by the mouse pointer. self.view_label_prefix = "Showing: " self.default_message = "Hover dots to color residues of the same type" # Hover over title. self.message_label = QtWidgets.QLabel(self.default_message) self.message_label.setStyleSheet(small_font_style) self.message_frame_layout.addRow(self.message_label) # Actually draws the plot. self.draw_plot() # Shows some data about the type of residues and their dihedral angles. self.regions_labels_dict = {} tot_regular_res = float(self.residues_count["T"]) label_params = [ ("F", "Residues in the most favoured regions", "residues in most favoured regions", True, True), ("A", "Residues in additional allowed regions", "residues in additional allowed regions", True, True), ("G", "Residues in generously allowed regions", "residues in generously allowed regions", True, True), ("D", "Residues in disallowed regions", "residues in disallowed regions", True, True), ("T", "Non-gly and non-pro residues (circles)", "non-glycine and non-proline residues", True, True), ("end_res", "End-residues", "end residues", False, False), ("gly", "Gly residues (triangles)", "glycine residues", True, False), ("pro", "Pro residues (squares)", "proline residues", True, False), ("total", "Total number of residues", "all residues", True, False) ] for region, label, message, active, use_ratio in label_params: region_label = Ramachandran_plot_info_labels( label, message, region, active, self) region_label.setStyleSheet(small_font_style) if use_ratio: text = "%s (%s%%)" % (self.residues_count[region], round( self.residues_count[region] / tot_regular_res * 100, 1)) else: text = str(self.residues_count[region]) region_label_count = QtWidgets.QLabel(text) region_label_count.setStyleSheet(small_font_style) self.message_frame_layout.addRow(region_label, region_label_count) self.regions_labels_dict[region] = { "info": region_label, "data": region_label_count }