def show_simple_dialog(message, title=""): msg_box = QMessageBox() msg_box.setIcon(QMessageBox.Information) msg_box.setText(message) msg_box.setWindowTitle(title) msg_box.setStandardButtons(QMessageBox.Ok) msg_box.exec()
def show_about(self): """Show About dialog.""" msg_box = QMessageBox(self) text = (f"<img src='{image_path('mnelab_logo.png')}'>" f"<p>MNELAB {__version__}</p>") msg_box.setText(text) mnelab_url = "github.com/cbrnr/mnelab" mne_url = "github.com/mne-tools/mne-python" pkgs = [] for key, value in have.items(): if value: pkgs.append(f"{key} ({value})") else: pkgs.append(f"{key} (not installed)") text = (f'<nobr><p>This program uses Python ' f'{".".join(str(k) for k in version_info[:3])} and the ' f'following packages:</p></nobr>' f'<p>{", ".join(pkgs)}</p>' f'<nobr><p>MNELAB repository: ' f'<a href=https://{mnelab_url}>{mnelab_url}</a></p></nobr>' f'<nobr><p>MNE repository: ' f'<a href=https://{mne_url}>{mne_url}</a></p></nobr>' f'<p>Licensed under the BSD 3-clause license.</p>' f'<p>Copyright 2017-2020 by Clemens Brunner.</p>') msg_box.setInformativeText(text) msg_box.exec_()
def closeEvent(self, event): # do stuff message_box = QMessageBox() message_box.setText("Save changes and exit?") vals = [ "{} → {}".format(x, self.core.config[x]) for x in self.core.config ] message_box.setInformativeText( "Mapper has unsaved mappings: {val}. Do you want to save the " "current mappings?".format(val=', '.join(vals))) message_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) user_message_box_response = message_box.exec() if user_message_box_response == QMessageBox.Yes: print("Registration process completed.") print("Registered mappings are : ", self.core.config) print("Writing configuration file...") self.core.create_configuration() print("Mapper completed successfully!") event.accept() elif user_message_box_response == QMessageBox.No: print("Not saving mapper configuration to json file") event.accept() else: event.ignore()
def _on_export_data(self): """ Handler function that is called when the Export Data button is pressed """ all_filters = ";;".join(['*.ecsv']) path, fmt = compat.getsavefilename(filters=all_filters) if path and fmt: try: plot_data_item = self.current_item self.export_data_item(plot_data_item, path, fmt) message_box = QMessageBox() message_box.setText("Data exported successfully.") message_box.setIcon(QMessageBox.Information) message_box.setInformativeText( "Data set '{}' has been exported to '{}'".format( plot_data_item.data_item.name, path)) message_box.exec() except Exception as e: logging.error(e) message_box = QMessageBox() message_box.setText("Error exporting data set.") message_box.setIcon(QMessageBox.Critical) message_box.setInformativeText( "{}\n{}".format( sys.exc_info()[0], sys.exc_info()[1].__repr__()[:100]) ) message_box.exec()
def _show_about_dialog(self): msg_box = QMessageBox() msg_box.setIcon(QMessageBox.Information) msg_box.setText("Pybonacci app v -37.3") msg_box.setWindowTitle("Ejemplo de Slot") msg_box.setStandardButtons(QMessageBox.Close) msg_box.exec_()
def handle_capture(window, capture): email, ok = QInputDialog.getText( window, 'Email', 'Enter your employee ID or email:', flags=Qt.FramelessWindowHint | Qt.Popup) while ok and not get_email(email): email, ok = QInputDialog.getText( window, 'Email', 'Enter a valid employee ID or email:', flags=Qt.FramelessWindowHint | Qt.Popup) if ok: print('Send email to %s' % email) pb = None try: pb = QProgressDialog("Sending...", "", 0, 0, window, Qt.FramelessWindowHint | Qt.Popup) pb.setWindowModality(Qt.WindowModal) pb.setRange(0, 0) pb.setMinimumDuration(0) pb.setCancelButton(None) pb.show() nongui(send_image)(email, capture, cache_dir=IMAGE_CACHE_DIR) except Exception: import traceback traceback.print_exc() msg = QMessageBox(window) msg.setIcon(QMessageBox.Critical) msg.setText('Error sending email.') msg.setWindowFlags(Qt.FramelessWindowHint | Qt.Popup) msg.exec_() finally: if pb: pb.close()
def raise_to_operator(exc, execute=True): """ Utility function to show a Python Exception in QMessageBox The type and representation of the Exception are shown in a pop-up QMessageBox. The entire traceback is available via a drop-down detailed text box in the QMessageBox Parameters ---------- exc: Exception execute: bool, optional Whether to execute the QMessageBox """ # Assemble QMessageBox with Exception details err_msg = QMessageBox() err_msg.setText(f'{exc.__class__.__name__}: {exc}') err_msg.setWindowTitle(type(exc).__name__) err_msg.setIcon(QMessageBox.Critical) # Format traceback as detailed text with io.StringIO() as handle: traceback.print_tb(exc.__traceback__, file=handle) handle.seek(0) err_msg.setDetailedText(handle.read()) if execute: # Execute err_msg.exec_() return err_msg
def _report_empty_target(self): msg = QMessageBox() msg.setWindowTitle("Invalid Target") msg.setIcon(QMessageBox.Warning) msg.setText("Target case can not be empty") msg.setStandardButtons(QMessageBox.Ok) msg.exec_()
def delete_patches(self): if self.mainwin.selection.hasSelection(): rows = sorted( [r.row() for r in self.mainwin.selection.selectedRows()]) patches = tuple(self.patches.get_row(r).displayname for r in rows) msg_box = QMessageBox() if len(rows) == 1: msg_box.setText( self.tr("Delete patch '{}'?").format(patches[0])) else: msg_box.setText( self.tr("Delete {} patches?").format(len(rows))) msg_box.setDetailedText('\n'.join(patches)) msg_box.setInformativeText( self.tr("Patches can only be restored by re-importing them.")) msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel) msg_box.setDefaultButton(QMessageBox.Cancel) msg_box.setIcon(QMessageBox.Warning) if msg_box.exec_() == QMessageBox.Yes: with self.session.begin(): for n, row in enumerate(rows): self.patches.removeRows(row - n)
def save_register_new_loader(self, filename): filename = "{}.py".format( filename) if not filename.endswith(".py") else filename string = self.as_new_loader() with open(filename, 'w') as f: f.write(string) # If a loader by this name exists, delete it if self.new_loader_dict['name'] in registry.get_formats()['Format']: registry.unregister_reader(self.new_loader_dict['name'], Spectrum1D) registry.unregister_identifier(self.new_loader_dict['name'], Spectrum1D) # Add new loader to registry spec = importlib.util.spec_from_file_location( os.path.basename(filename)[:-3], filename) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) message_box = QMessageBox() message_box.setText("Loader saved successful.") message_box.setIcon(QMessageBox.Information) message_box.setInformativeText("Custom loader was saved successfully.") message_box.exec()
def show_error(self): """This class create error dialog and show it""" if self.error is None: return from PartSeg.common_gui.error_report import ErrorDialog if isinstance(self.error, TiffFileException): mess = QMessageBox() mess.setIcon(QMessageBox.Critical) mess.setText("During read file there is an error: " + self.error.args[0]) mess.setWindowTitle("Tiff error") mess.exec() return if isinstance(self.error, SegmentationLimitException): mess = QMessageBox() mess.setIcon(QMessageBox.Critical) mess.setText( "During segmentation process algorithm meet limitations:\n" + "\n".join(self.error.args)) mess.setWindowTitle("Segmentation limitations") mess.exec() return dial = ErrorDialog(self.error, "Exception during program run") # TODO check # dial.moveToThread(QApplication.instance().thread()) dial.exec()
def restart_failed_realizations(self): msg = QMessageBox(self) msg.setIcon(QMessageBox.Information) msg.setText( "Note that workflows will only be executed on the restarted realizations and that this might have unexpected consequences." ) msg.setWindowTitle("Restart Failed Realizations") msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) result = msg.exec_() if result == QMessageBox.Ok: self.restart_button.setVisible(False) self.kill_button.setVisible(True) self.done_button.setVisible(False) active_realizations = self.create_mask_from_failed_realizations() self._simulations_argments[ 'active_realizations'] = active_realizations self._simulations_argments[ 'prev_successful_realizations'] = self._simulations_argments.get( 'prev_successful_realizations', 0) self._simulations_argments[ 'prev_successful_realizations'] += self.count_successful_realizations( ) self.startSimulation()
def load_from_file(self, fname): try: self.I_meas, self.sigma = np.loadtxt( fname, skiprows=2, unpack=True) except (ValueError, TypeError): msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setText("Could not Load File") msg.setInformativeText( "The chosen file does not match the formatting.") msg.setWindowTitle("Warning") msg.resize(900, 300) msg.exec_() return with open(fname, 'r') as f: self.plane_meas = f.readline().split()[-1] if self.plane_meas == 'x': self.line_sigmax.set_xdata(self.I_meas) self.line_sigmax.set_ydata(np.array(self.sigma)*1e3) else: self.line_sigmay.set_xdata(self.I_meas) self.line_sigmay.set_ydata(np.array(self.sigma)*1e3) self.fig_sigma.figure.axes[0].set_xlim( [min(self.I_meas)*(1-DT*10), max(self.I_meas)*(1+DT*10)]) self.fig_sigma.figure.axes[0].set_ylim( [min(self.sigma)*(1-DT)*1e3, max(self.sigma)*(1+DT)*1e3]) self.fig_sigma.figure.canvas.draw()
def copyCellsToClipboard(self): """Concatenate the text content of all cells into a string using tabulations and newlines to keep the table structure. Put this text into the clipboard. """ data_model = self.table.model() copied_text = "" for row in range(data_model.rowCount()): for col in range(data_model.columnCount()): index = data_model.index(row, col) cell_text = data_model.data(index) flags = data_model.flags(index) if cell_text is not None: try: copied_text += cell_text except: # Only works for text cells msgBox = QMessageBox(parent=self.table) msgBox.setText(_NONTEXTCELL) msgBox.exec_() return False return if self.cut and (flags & Qt.ItemIsEditable): data_model.setData(index, "") copied_text += col_separator # remove the right-most tabulation copied_text = copied_text[:-len(col_separator)] # add a newline copied_text += row_separator # remove final newline copied_text = copied_text[:-len(row_separator)] # put this text into clipboard qapp = QApplication.instance() qapp.clipboard().setText(copied_text)
def __concat_images(self, format, output_file): ''' cats 2 images vertically ''' im_image = Image.open(self.image.text()) mp_image = Image.open(output_file) more_args = {} convert_to_rgb = False if format.lower() == 'jpg' or format.lower() == 'jpeg': more_args['subsampling'] = 0 more_args['quality'] = 95 if im_image.format.lower() != 'jpg' and im_image.format.lower() != 'jpeg': msg_box = QMessageBox() msg_box.setText( f"Image format is {im_image.format}/{im_image.mode} but the desired output format is JPG<p/><p/>The image must be converted to RGB in order to proceed.") msg_box.setIcon(QMessageBox.Warning) msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg_box.setWindowTitle('Do you want to convert?') decision = msg_box.exec() if decision == QMessageBox.Yes: convert_to_rgb = True else: return False if im_image.size[0] != mp_image.size[0]: new_height = round(im_image.size[1] * (mp_image.size[0] / im_image.size[0])) logger.debug(f"Resizing from {im_image.size} to match {mp_image.size}, new height {new_height}") im_image = im_image.resize((mp_image.size[0], new_height), Image.LANCZOS) if convert_to_rgb: im_image = im_image.convert('RGB') final_image = Image.new(im_image.mode, (im_image.size[0], im_image.size[1] + mp_image.size[1])) final_image.paste(im_image, (0, 0)) final_image.paste(mp_image, (0, im_image.size[1])) final_image.save(output_file, **more_args) return True
def dialog(title, text, icon, setting=None, default=None): if not getattr(settings, setting.upper()): return True check = QCheckBox() check.setText('Dont show this message again (can be reset via the preferences)') info = QMessageBox() info.setIcon(icon) info.setText(title) info.setInformativeText(text) info.setCheckBox(check) info.setStandardButtons(info.Cancel | info.Ok) if default == 'Cancel': info.setDefaultButton(info.Cancel) result = info.exec_() if result == info.Cancel: return False if check.isChecked(): setattr(settings, setting.upper(), False) save_settings() return True
def validate_password(self): """ If the widget is ```passwordProtected```, this method will propmt the user for the correct password. Returns ------- bool True in case the password was correct of if the widget is not password protected. """ if not self._password_protected: return True pwd, ok = QInputDialog().getText(None, "Authentication", "Please enter your password:"******"") pwd = str(pwd) if not ok or pwd == "": return False sha = hashlib.sha256() sha.update(pwd.encode()) pwd_encrypted = sha.hexdigest() if pwd_encrypted != self._protected_password: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("Invalid password.") msg.setWindowTitle("Error") msg.setStandardButtons(QMessageBox.Ok) msg.setDefaultButton(QMessageBox.Ok) msg.setEscapeButton(QMessageBox.Ok) msg.exec_() return False return True
def alert_on_change(self, title, text='Change will not take effect until the application is restarted', icon=QMessageBox.Warning): msg_box = QMessageBox() msg_box.setText(text) msg_box.setIcon(icon) msg_box.setWindowTitle(title) msg_box.exec()
def run(self): target = self._run_widget.target_case() source = self._run_widget.source_case() if len(target) == 0: self._report_empty_target() return success = analyse(target, source) msg = QMessageBox() msg.setWindowTitle("Run Analysis") msg.setStandardButtons(QMessageBox.Ok) if success: msg.setIcon(QMessageBox.Information) msg.setText( "Successfully ran analysis for case '{}'.".format(source)) msg.exec_() else: msg.setIcon(QMessageBox.Warning) msg.setText("Unable to run analysis for case '{}'.".format(source)) msg.exec_() return ert_shared.ERT.ertChanged.emit() self._dialog.accept()
def load_fod_input(self): _current_folder = self.parent.parent.current_folder [_table_file, _] = QFileDialog.getOpenFileName( parent=self.parent, caption="Input inp File", directory=_current_folder, filter=("inp files (*.inp);; All Files (*.*)")) if not _table_file: return try: fod_inputs = open(_table_file, "r") except IOError: self.err_messenger("Permission denied! Choose another input file!") return lines = fod_inputs.readlines() fod_inputs.close() for line in lines: try: if line.strip(): self.parameters[line.split('#')[1].strip()]=line.split('#')[0].strip() except IndexError: pass try: self.parent.ui.sample_1_title.setText(self.parameters['sample_1_title']) self.parent.ui.sample_2_title.setText(self.parameters['sample_2_title']) self.parent.ui.bkg_title.setText(self.parameters['background_title']) self.parent.ui.bkg_scans.setText(self.parameters['background scannrs']) self.parent.ui.sample_1_scans.setText(self.parameters['sample_1_scannrs']) self.parent.ui.sample_2_scans.setText(self.parameters['sample_2_scannrs']) self.parent.ui.secondary_scattering_ratio.setText(self.parameters['secondary_scattering_ratio']) self.parent.ui.plazcek_fit_range_min.setText(self.parameters['pla_range'].split(',')[0].strip()) self.parent.ui.plazcek_fit_range_max.setText(self.parameters['pla_range'].split(',')[1].strip()) if ',' in self.parameters['substitution_type']: self.parent.ui.subs_init.setText(self.parameters['substitution_type'].split(',')[0].strip()) self.parent.ui.subs_rep.setText(self.parameters['substitution_type'].split(',')[1].strip()) elif '/' in self.parameters['substitution_type']: self.parent.ui.subs_init.setText(self.parameters['substitution_type'].split('/')[0].strip()) self.parent.ui.subs_rep.setText(self.parameters['substitution_type'].split('/')[1].strip()) self.parent.ui.ft_qrange.setText(self.parameters['qrangeft']) self.parent.ui.ff_rrange.setText(self.parameters['fourier_range_r']) try: self.parent.ui.ff_qrange.setText(self.parameters['fourier_range_q']) except KeyError: self.parent.ui.ff_qrange.setText(self.parameters['fourier_range_Q']) except (IndexError, KeyError): msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Critical) msgBox.setText("Error in FOD input file!") msgBox.setWindowTitle("Error") msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_() return return
def display_warning(self): m = QMessageBox(self.parent()) m.setText( 'You need to restart the server for the changes to take effect') m.setWindowTitle('Warning') m.setIcon(QMessageBox.Information) m.show()
def create_error_dlg(self, message, info=None, detail=None, ignore_buttons=True): dlg = QMessageBox() dlg.setText(message) if info: dlg.setInformativeText(info) if detail: dlg.setDetailedText(detail) dlg.setWindowTitle(self.name + self.tr(" - Error")) dlg.setIcon(QMessageBox.Critical) if ignore_buttons: dlg.setStandardButtons(QMessageBox.Abort | QMessageBox.Ignore) dlg.btn_ignoreall = dlg.addButton(self.tr("Ignore A&ll"), QMessageBox.ActionRole) dlg.setDefaultButton(QMessageBox.Ignore) else: dlg.setDefaultButton(QMessageBox.NoButton) return dlg
def _on_export_data(self): """ Handler function that is called when the Export Data button is pressed """ all_filters = ";;".join(['*.ecsv']) path, fmt = compat.getsavefilename(filters=all_filters) if path and fmt: try: plot_data_item = self.current_item self.export_data_item(plot_data_item, path, fmt) message_box = QMessageBox() message_box.setText("Data exported successfully.") message_box.setIcon(QMessageBox.Information) message_box.setInformativeText( "Data set '{}' has been exported to '{}'".format( plot_data_item.data_item.name, path)) message_box.exec() except Exception as e: logging.error(e) message_box = QMessageBox() message_box.setText("Error exporting data set.") message_box.setIcon(QMessageBox.Critical) message_box.setInformativeText("{}\n{}".format( sys.exc_info()[0], sys.exc_info()[1].__repr__()[:100])) message_box.exec()
def __save_report(self): ''' writes the figure to the specified format ''' formats = "Report Files (*.png *.jpg *.jpeg)" file_name = QFileDialog.getSaveFileName(parent=self, caption='Export Report', filter=formats) if file_name: output_file = str(file_name[0]).strip() if len(output_file) == 0: return else: format = os.path.splitext(output_file)[1][1:].strip() if format in VALID_IMG_FORMATS: scale_factor = self.widthPixels.value() / self.__x from app import wait_cursor with wait_cursor(): self.__status_bar.showMessage( f"Saving report to {output_file}", 5000) self.preview.canvas.figure.savefig(output_file, format=format, dpi=self.__dpi * scale_factor, pad_inches=0, bbox_inches='tight') self.__status_bar.showMessage( f"Saved report to {output_file}", 5000) else: msg_box = QMessageBox() msg_box.setText( f"Invalid output file format - {output_file} is not one of {VALID_IMG_FORMATS}" ) msg_box.setIcon(QMessageBox.Critical) msg_box.setWindowTitle('Unexpected Error') msg_box.exec()
def _select_spectra_to_load(self, specs_by_name): selection_dialog = SpectrumSelection(self) selection_dialog.populate(specs_by_name.keys()) selection_dialog.exec_() names_to_keep = selection_dialog.get_selected() if not names_to_keep: logging.warning('No spectra selected') message_box = QMessageBox() message_box.setText("No spectra were selected.") message_box.setIcon(QMessageBox.Warning) message_box.setInformativeText('No data has been loaded.') message_box.exec() return {} to_load = OrderedDict() for name, spectrum in specs_by_name.items(): if name in names_to_keep: to_load[name] = spectrum return to_load
def _save_and_run_dialog(self): mb = QMessageBox(self.main_window) mb.setWindowTitle(_(u'Unsaved changes')) mb.setText( u'You have unsaved changes. What do you want to do?' ) mb.addButton( QPushButton( self.theme.qicon(u'os-run'), _(u'Save and run') ), QMessageBox.AcceptRole ) mb.addButton( QPushButton( self.theme.qicon(u'os-run'), _(u'Save, run, and don\'t ask again') ), QMessageBox.AcceptRole ) mb.addButton( QPushButton( self.theme.qicon(u'dialog-cancel'), _(u'Cancel') ), QMessageBox.AcceptRole ) return mb.exec_()
def load_data(self, file_path, file_loader, display=False): """ Load spectral data given file path and loader. Parameters ---------- file_path : str Path to location of the spectrum file. file_loader : str Format specified for the astropy io interface. display : bool Automatically add the loaded spectral data to the plot. Returns ------- : :class:`~specviz.core.items.DataItem` The `DataItem` instance that has been added to the internal model. """ try: spec = Spectrum1D.read(file_path, format=file_loader) name = file_path.split('/')[-1].split('.')[0] data_item = self.model.add_data(spec, name=name) return data_item except: message_box = QMessageBox() message_box.setText("Error loading data set.") message_box.setIcon(QMessageBox.Critical) message_box.setInformativeText("{}\n{}".format( sys.exc_info()[0], sys.exc_info()[1])) message_box.exec()
def __create_signals(self): ''' Creates signals from the output file just created. :return: True if we created the signals. ''' loader = AutoWavLoader(self.__preferences) output_file = self.__executor.get_output_path() if os.path.exists(output_file): from app import wait_cursor with wait_cursor(f"Creating signals for {output_file}"): logger.info(f"Creating signals for {output_file}") name_provider = lambda channel, channel_count: get_channel_name( self.signalName.text(), channel, channel_count, channel_layout_name=self.__executor.channel_layout_name) loader.load(output_file) signal = loader.auto_load(name_provider, self.decimateAudio.isChecked()) self.__signal_model.add(signal) return True else: msg_box = QMessageBox() msg_box.setText( f"Extracted audio file does not exist at: \n\n {output_file}") msg_box.setIcon(QMessageBox.Critical) msg_box.setWindowTitle('Unexpected Error') msg_box.exec() return False
def get_boolean_from_dialog(window_title, message): """ pop out a dialog showing a message to user. User will choose OK or Cancel :param window_title :param message: :return: """ def msgbtn(i): # debugging output print("Button pressed is:", i.text()) message_box = QMessageBox() message_box.setIcon(QMessageBox.Information) message_box.setText(message) if window_title is not None: message_box.setWindowTitle(window_title) message_box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) message_box.buttonClicked.connect(msgbtn) # get the message executed return_value = message_box.exec_() # identify output if return_value == 4194304: return_value = True elif return_value == 1024: return_value = False else: raise RuntimeError('Return value {} of type {} is not recognized.' ''.format(return_value, type(return_value))) return return_value
def warn(self, title, text, buttons=QMessageBox.Yes): msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setWindowTitle(title) msg.setText(text) msg.setStandardButtons(buttons) return msg.exec_()
def dialog(title, text, icon, setting=None, default=None): if not getattr(settings, setting.upper()): return True check = QCheckBox() check.setText( 'Dont show this message again (can be reset via the preferences)') info = QMessageBox() info.setIcon(icon) info.setText(title) info.setInformativeText(text) info.setCheckBox(check) info.setStandardButtons(info.Cancel | info.Ok) if default == 'Cancel': info.setDefaultButton(info.Cancel) result = info.exec_() if result == info.Cancel: return False if check.isChecked(): setattr(settings, setting.upper(), False) save_settings() return True
def handle_timeout(self): """ Handles the timeout event for the timer. Decreases the time remaining counter until 0 and when it is time, cleans up the event filter and closes the window. """ if is_qt_designer(): return # Decrease remaining time self._time_rem_ms -= self._timer.interval() # Update screen label with new remaining time self._update_label() if self._time_rem_ms > 0: self.start() return QApplication.instance().removeEventFilter(self) if self._window: logger.debug('Time to close the window') self._window.close() msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setText( "Your window was closed due to inactivity for {}.".format( self._get_time_text(self.timeout))) msg.setStandardButtons(QMessageBox.Ok) msg.setDefaultButton(QMessageBox.Ok) msg.exec_()
def show_error_message(message, title, parent=None): box = QMessageBox(parent=parent) box.setIcon(QMessageBox.Warning) box.setText(message) box.setWindowTitle(title) box.setStandardButtons(QMessageBox.Ok) box.exec_()
def show_compatibility_message(self, message): """Show compatibility message.""" messageBox = QMessageBox(self) messageBox.setWindowModality(Qt.NonModal) messageBox.setAttribute(Qt.WA_DeleteOnClose) messageBox.setWindowTitle('Compatibility Check') messageBox.setText(message) messageBox.setStandardButtons(QMessageBox.Ok) messageBox.show()
def display_message_box(self, title, message, details): msg = QMessageBox(self) msg.setIcon(QMessageBox.Warning) msg.setText(message) msg.setWindowTitle(title) msg.setDetailedText(details) msg.setStandardButtons(QMessageBox.Ok) msg.setDefaultButton(QMessageBox.Ok) msg.setEscapeButton(QMessageBox.Ok) msg.exec_()
def permission_box_to_prepend_import(): msg_box = QMessageBox() msg_box.setWindowTitle("Mantid Workbench") msg_box.setWindowIcon(QIcon(':/images/MantidIcon.ico')) msg_box.setText("It looks like this python file uses a Mantid " "algorithm but does not import the Mantid API.") msg_box.setInformativeText("Would you like to add a line to import " "the Mantid API?") msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg_box.setDefaultButton(QMessageBox.Yes) permission = msg_box.exec_() if permission == QMessageBox.Yes: return True return False
def display_load_data_error(self, exp): """ Display error message box when attempting to load a data set. Parameters ---------- exp : str Error text. """ message_box = QMessageBox() message_box.setText("Error loading data set.") message_box.setIcon(QMessageBox.Critical) message_box.setInformativeText(str(exp)) message_box.exec()
def show_mongo_query_help(self): "Launch a Message Box with instructions for custom queries." msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("For advanced search capability, enter a valid Mongo query.") msg.setInformativeText(""" Examples: {'plan_name': 'scan'} {'proposal': 1234}, {'$and': ['proposal': 1234, 'sample_name': 'Ni']} """) msg.setWindowTitle("Custom Mongo Query") msg.setStandardButtons(QMessageBox.Ok) msg.exec_()
def save_list_to_file(self): filename, filters = QFileDialog.getSaveFileName(self, "Save connection list", "", "Text Files (*.txt)") try: with open(filename, "w") as f: for conn in self.table_view.model().connections: f.write( "{p}://{a}\n".format(p=conn.protocol, a=conn.address)) self.save_status_label.setText("File saved to {}".format(filename)) except Exception as e: msgBox = QMessageBox() msgBox.setText("Couldn't save connection list to file.") msgBox.setInformativeText("Error: {}".format(str(e))) msgBox.setStandardButtons(QMessageBox.Ok) msgBox.exec_()
def on_exception(self, exception): """ Called when the `QThread` runs into an exception. Parameters ---------- exception : Exception The Exception that interrupted the `QThread`. """ self.smooth_button.setEnabled(True) self.cancel_button.setEnabled(True) info_box = QMessageBox(parent=self) info_box.setWindowTitle("Smoothing Error") info_box.setIcon(QMessageBox.Critical) info_box.setText(str(exception)) info_box.setStandardButtons(QMessageBox.Ok) info_box.show()
def _on_change_color(self): """ Listens for color changed events in plot windows, gets the currently selected item in the data list view, and changes the stored color value. """ # If there is no currently selected rows, raise an error if self.current_item is None: message_box = QMessageBox() message_box.setText("No item selected, cannot change color.") message_box.setIcon(QMessageBox.Warning) message_box.setInformativeText( "There is currently no item selected. Please select an item " "before changing its plot color.") message_box.exec() return color = QColorDialog.getColor(options=QColorDialog.ShowAlphaChannel) if color.isValid(): self.current_item.color = color.toRgb() self.color_changed.emit(self.current_item, self.current_item.color)
def confirm_dialog(self): """ Show the confirmation dialog with the proper message in case ```showConfirmMessage``` is True. Returns ------- bool True if the message was confirmed or if ```showCofirmMessage``` is False. """ if self._show_confirm_dialog: if self._confirm_message == "": self._confirm_message = PyDMPushButton.DEFAULT_CONFIRM_MESSAGE msg = QMessageBox() msg.setIcon(QMessageBox.Question) msg.setText(self._confirm_message) msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg.setDefaultButton(QMessageBox.No) ret = msg.exec_() if ret == QMessageBox.No: return False return True
def show(self): """ Parses the current plot window information and displays the unit change dialog with the appropriate available units to which the current plot's units can be changed. """ # If there is no plot item, don't even try to process unit info if self.hub.plot_item is None or len(self.hub.visible_plot_items) == 0: message_box = QMessageBox() message_box.setText("No item plotted, cannot parse unit information.") message_box.setIcon(QMessageBox.Warning) message_box.setInformativeText( "There is currently no items plotted. Please plot an item " "before changing unit.") message_box.exec_() return # Prevents duplicate units from showing up each time this is executed self.ui.comboBox_units.clear() self.ui.comboBox_spectral.clear() # If the units in PlotWidget are not set, do not allow the user to click the OK button if not self.hub.plot_widget.data_unit: self.ui.comboBox_units.setEnabled(False) if not self.hub.plot_widget.spectral_axis_unit: self.ui.comboBox_spectral.setEnabled(False) if not (self.hub.plot_widget.data_unit or self.hub.plot_widget.spectral_axis_unit): self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) # Gets all possible conversions from current spectral_axis_unit self.spectral_axis_unit_equivalencies = u.Unit( self.hub.data_item.spectral_axis.unit).find_equivalent_units( equivalencies=u.spectral()) # Gets all possible conversions for flux from current spectral axis and corresponding units # np.sum for spectral_axis so that it does not return a Quantity with zero scale self.data_unit_equivalencies = u.Unit( self.hub.plot_widget.data_unit).find_equivalent_units( equivalencies=u.spectral_density(np.sum(self.hub.data_item.spectral_axis)), include_prefix_units=False) # Current data unit and spectral axis unit self.current_data_unit = self.hub.plot_widget.data_unit self.current_spectral_axis_unit = self.hub.plot_widget.spectral_axis_unit # Add current spectral axis units to equivalencies if u.Unit(self.hub.plot_widget.spectral_axis_unit) not in self.spectral_axis_unit_equivalencies: self.spectral_axis_unit_equivalencies.append(u.Unit(self.hub.plot_widget.spectral_axis_unit)) # Add original spectral axis units to equivalencies if u.Unit(self.hub.data_item.spectral_axis.unit) not in self.spectral_axis_unit_equivalencies: self.spectral_axis_unit_equivalencies.append(u.Unit(self.hub.data_item.spectral_axis.unit)) # Add current data units to equivalencies if u.Unit(self.hub.plot_widget.data_unit) not in self.data_unit_equivalencies: self.data_unit_equivalencies.append(u.Unit(self.hub.plot_widget.data_unit)) # Add original flux units to equivalencies if u.Unit(self.hub.data_item.flux.unit) not in self.data_unit_equivalencies: self.data_unit_equivalencies.append(u.Unit(self.hub.data_item.flux.unit)) # Sort units by to_string() self.spectral_axis_unit_equivalencies = sorted(self.spectral_axis_unit_equivalencies, key=lambda x: x.to_string()) self.data_unit_equivalencies = sorted(self.data_unit_equivalencies, key=lambda y: y.to_string()) # Create lists with the "pretty" versions of unit names self.spectral_axis_unit_equivalencies_titles = [ u.Unit(unit).name if u.Unit(unit) == u.Unit("Angstrom") else u.Unit(unit).long_names[0].title() if (hasattr(u.Unit(unit), "long_names") and len(u.Unit(unit).long_names) > 0) else u.Unit(unit).to_string() for unit in self.spectral_axis_unit_equivalencies] self.data_unit_equivalencies_titles = [ u.Unit(unit).name if u.Unit(unit) == u.Unit("Angstrom") else u.Unit(unit).long_names[0].title() if (hasattr(u.Unit(unit), "long_names") and len(u.Unit(unit).long_names) > 0) else u.Unit(unit).to_string() for unit in self.data_unit_equivalencies] # This gives the user the option to use their own units. These units are checked by u.Unit() # and PlotDataItem.is_spectral_axis_unit_compatible(spectral_axis_unit) and # PlotDataItem.is_data_unit_compatible(data_unit) self.spectral_axis_unit_equivalencies_titles.append("Custom") self.data_unit_equivalencies_titles.append("Custom") self.setup_ui() self.setup_connections() super().show()
def errormessage(self, message): msg = QMessageBox() msg.setText(str(message)) msg.setStandardButtons(QMessageBox.Ok) msg.exec_()
class MainWindow(QMainWindow): """ Class of Main Window (top) """ _errMsgWindow = None def __init__(self, parent=None): """ Initialization and set up """ # Base class QMainWindow.__init__(self, parent) # Mantid configuration config = ConfigService.Instance() self._instrument = config["default.instrument"] # Central widget self.centralwidget = QWidget(self) # UI Window (from Qt Designer) self.ui = load_ui(__file__, 'MainWindow.ui', baseinstance=self) mpl_layout = QVBoxLayout() self.ui.graphicsView.setLayout(mpl_layout) self.fig = Figure() self.canvas = FigureCanvas(self.fig) self.ui.mainplot = self.fig.add_subplot(111, projection='mantid') mpl_layout.addWidget(self.canvas) # Do initialize plotting vecx, vecy, xlim, ylim = self.computeMock() self.mainline = self.ui.mainplot.plot(vecx, vecy, 'r-') leftx = [xlim[0], xlim[0]] lefty = [ylim[0], ylim[1]] self.leftslideline = self.ui.mainplot.plot(leftx, lefty, 'b--') rightx = [xlim[1], xlim[1]] righty = [ylim[0], ylim[1]] self.rightslideline = self.ui.mainplot.plot(rightx, righty, 'g--') upperx = [xlim[0], xlim[1]] uppery = [ylim[1], ylim[1]] self.upperslideline = self.ui.mainplot.plot(upperx, uppery, 'b--') lowerx = [xlim[0], xlim[1]] lowery = [ylim[0], ylim[0]] self.lowerslideline = self.ui.mainplot.plot(lowerx, lowery, 'g--') self.canvas.mpl_connect('button_press_event', self.on_mouseDownEvent) # Set up horizontal slide (integer) and string value self._leftSlideValue = 0 self._rightSlideValue = 99 self.ui.horizontalSlider.setRange(0, 100) self.ui.horizontalSlider.setValue(self._leftSlideValue) self.ui.horizontalSlider.setTracking(True) self.ui.horizontalSlider.setTickPosition(QSlider.NoTicks) self.ui.horizontalSlider.valueChanged.connect(self.move_leftSlider) self.ui.horizontalSlider_2.setRange(0, 100) self.ui.horizontalSlider_2.setValue(self._rightSlideValue) self.ui.horizontalSlider_2.setTracking(True) self.ui.horizontalSlider_2.setTickPosition(QSlider.NoTicks) self.ui.horizontalSlider_2.valueChanged.connect(self.move_rightSlider) # self.connect(self.ui.lineEdit_3, QtCore.SIGNAL("textChanged(QString)"), # self.set_startTime) self.ui.lineEdit_3.setValidator(QDoubleValidator(self.ui.lineEdit_3)) self.ui.pushButton_setT0.clicked.connect(self.set_startTime) # self.connect(self.ui.lineEdit_4, QtCore.SIGNAL("textChanged(QString)"), # self.set_stopTime) self.ui.lineEdit_4.setValidator(QDoubleValidator(self.ui.lineEdit_4)) self.ui.pushButton_setTf.clicked.connect(self.set_stopTime) # File loader self.scanEventWorkspaces() self.ui.pushButton_refreshWS.clicked.connect(self.scanEventWorkspaces) self.ui.pushButton_browse.clicked.connect(self.browse_File) self.ui.pushButton_load.clicked.connect(self.load_File) self.ui.pushButton_3.clicked.connect(self.use_existWS) # Set up time self.ui.lineEdit_3.setValidator(QDoubleValidator(self.ui.lineEdit_3)) self.ui.lineEdit_4.setValidator(QDoubleValidator(self.ui.lineEdit_4)) # Filter by time self.ui.pushButton_filterTime.clicked.connect(self.filterByTime) # Filter by log value self.ui.lineEdit_5.setValidator(QDoubleValidator(self.ui.lineEdit_5)) self.ui.lineEdit_6.setValidator(QDoubleValidator(self.ui.lineEdit_6)) self.ui.lineEdit_7.setValidator(QDoubleValidator(self.ui.lineEdit_7)) self.ui.lineEdit_8.setValidator(QDoubleValidator(self.ui.lineEdit_8)) self.ui.lineEdit_9.setValidator(QDoubleValidator(self.ui.lineEdit_9)) self.ui.lineEdit_5.textChanged.connect(self.set_minLogValue) self.ui.lineEdit_6.textChanged.connect(self.set_maxLogValue) dirchangeops = ["Both", "Increase", "Decrease"] self.ui.comboBox_4.addItems(dirchangeops) logboundops = ["Centre", "Left"] self.ui.comboBox_5.addItems(logboundops) self.ui.pushButton_4.clicked.connect(self.plotLogValue) self.ui.pushButton_filterLog.clicked.connect(self.filterByLogValue) # Set up help button self.ui.helpBtn.clicked.connect(self.helpClicked) # Set up vertical slide self._upperSlideValue = 99 self._lowerSlideValue = 0 self.ui.verticalSlider.setRange(0, 100) self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.verticalSlider.setTracking(True) self.ui.verticalSlider.valueChanged.connect(self.move_upperSlider) self.ui.verticalSlider_2.setRange(0, 100) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) self.ui.verticalSlider_2.setTracking(True) self.ui.verticalSlider_2.valueChanged.connect(self.move_lowerSlider) # Set up for filtering (advanced setup) self._tofcorrection = False self.ui.checkBox_fastLog.setChecked(False) self.ui.checkBox_filterByPulse.setChecked(False) self.ui.checkBox_from1.setChecked(False) self.ui.checkBox_groupWS.setChecked(True) self.ui.comboBox_tofCorr.currentIndexChanged.connect(self.showHideEi) self.ui.pushButton_refreshCorrWSList.clicked.connect(self._searchTableWorkspaces) self.ui.lineEdit_Ei.setValidator(QDoubleValidator(self.ui.lineEdit_Ei)) self.ui.label_Ei.hide() self.ui.lineEdit_Ei.hide() self.ui.label_Ei_2.hide() self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() # Set up for workspaces self._dataWS = None self._sampleLogNames = [] self._sampleLog = None # Side information self.ui.label_mean.hide() self.ui.label_meanvalue.hide() self.ui.label_avg.hide() self.ui.label_timeAvgValue.hide() self.ui.label_freq.hide() self.ui.label_freqValue.hide() self.ui.label_logname.hide() self.ui.label_lognamevalue.hide() self.ui.label_logsize.hide() self.ui.label_logsizevalue.hide() # Default self._defaultdir = os.getcwd() # register startup mantid.UsageService.registerFeatureUsage("Interface", "EventFilter", False) def on_mouseDownEvent(self, event): """ Respond to pick up a value with mouse down event """ x = event.xdata y = event.ydata if x is not None and y is not None: msg = "You've clicked on a bar with coords:\n %f, %f" % (x, y) QMessageBox.information(self, "Click!", msg) def computeMock(self): """ Compute vecx and vecy as mocking """ x0 = 0. xf = 1. dx = 0.1 vecx = [] vecy = [] x = x0 while x < xf: y = 0.0 vecx.append(x) vecy.append(y) x += dx xlim = [x0, xf] ylim = [-1., 1] return (vecx, vecy, xlim, ylim) def move_leftSlider(self): """ Re-setup left range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ newx = self.ui.horizontalSlider.value() if newx <= self._rightSlideValue and newx != self._leftSlideValue: # Allowed value: move the value bar self._leftSlideValue = newx # Move the vertical line xlim = self.ui.mainplot.get_xlim() newx = xlim[0] + newx*(xlim[1] - xlim[0])*0.01 leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Change value self.ui.lineEdit_3.setText(str(newx)) else: # Reset the value to original value self.ui.horizontalSlider.setValue(self._leftSlideValue) def set_startTime(self): """ Set the starting time and left slide bar """ inps = str(self.ui.lineEdit_3.text()) info_msg = "Starting time = %s" % (inps) Logger("Filter_Events").information(info_msg) xlim = self.ui.mainplot.get_xlim() if inps == "": # Empty. Use default newtime0 = xlim[0] else: newtime0 = float(inps) # Convert to integer slide value ileftvalue = int((newtime0-xlim[0])/(xlim[1] - xlim[0])*100) debug_msg = "iLeftSlide = %s" % str(ileftvalue) Logger("Filter_Events").debug(debug_msg) # Skip if same as origina if ileftvalue == self._leftSlideValue: return # Set the value if out of range resetT = True if ileftvalue < 0: # Minimum value as 0 ileftvalue = 0 elif ileftvalue > self._rightSlideValue: # Maximum value as right slide value ileftvalue = self._rightSlideValue else: resetT = False if resetT is True: newtime0 = xlim[0] + ileftvalue*(xlim[1]-xlim[0])*0.01 info_msg = 'Corrected iLeftSlide = {} (vs. right = {})'.format(ileftvalue, self._rightSlideValue) Logger("Filter_Events").information(info_msg) # Move the slide bar (left) self._leftSlideValue = ileftvalue # Move the vertical line leftx = [newtime0, newtime0] lefty = self.ui.mainplot.get_ylim() setp(self.leftslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider.setValue(self._leftSlideValue) # Reset the value of line edit if resetT is True: self.ui.lineEdit_3.setText(str(newtime0)) def move_rightSlider(self): """ Re-setup left range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ newx = self.ui.horizontalSlider_2.value() if newx >= self._leftSlideValue and newx != self._rightSlideValue: # Allowed value: move the value bar self._rightSlideValue = newx xlim = self.ui.mainplot.get_xlim() newx = xlim[0] + newx*(xlim[1] - xlim[0])*0.01 leftx = [newx, newx] lefty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=leftx, ydata=lefty) self.canvas.draw() # Change value self.ui.lineEdit_4.setText(str(newx)) else: # Reset the value self.ui.horizontalSlider_2.setValue(self._rightSlideValue) def set_stopTime(self): """ Set the starting time and left slide bar """ inps = str(self.ui.lineEdit_4.text()) Logger("Filter_Events").information('Stopping time = {}'.format(inps)) xlim = self.ui.mainplot.get_xlim() if inps == "": # Empty. Use default newtimef = xlim[1] else: # Parse newtimef = float(inps) # Convert to integer slide value irightvalue = int((newtimef-xlim[0])/(xlim[1] - xlim[0])*100) Logger("Filter_Events").information('iRightSlide = {}'.format(irightvalue)) # Return if no change if irightvalue == self._rightSlideValue: return # Correct value resetT = True if irightvalue > 100: irightvalue = 100 elif irightvalue < self._leftSlideValue: irightvalue = self._leftSlideValue else: resetT = False if resetT is True: newtimef = xlim[0] + irightvalue*(xlim[1]-xlim[0])*0.01 # Move the slide bar (right) self._rightSlideValue = irightvalue # Move the vertical line rightx = [newtimef, newtimef] righty = self.ui.mainplot.get_ylim() setp(self.rightslideline, xdata=rightx, ydata=righty) self.canvas.draw() # Set the value to left slider self.ui.horizontalSlider_2.setValue(self._rightSlideValue) # Reset to line edit if resetT: self.ui.lineEdit_4.setText(str(newtimef)) def move_lowerSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ inewy = self.ui.verticalSlider_2.value() debug_msg = 'LowerSlFider is set with value {} vs. class variable {}'.format(inewy, self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) # Return with no change if inewy == self._lowerSlideValue: # No change return if inewy >= self._upperSlideValue: # Out of upper range inewy = self._upperSlideValue - 1 if inewy == 0 and self._lowerSlideValue < 0: setLineEdit = False else: setLineEdit = True # Move the lower vertical bar ylim = self.ui.mainplot.get_ylim() newy = ylim[0] + inewy*(ylim[1] - ylim[0])*0.01 lowerx = self.ui.mainplot.get_xlim() lowery = [newy, newy] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) self.canvas.draw() # Set line edit input if setLineEdit is True: # Change value to line edit (5) self.ui.lineEdit_5.setText(str(newy)) # Reset the class variable self._lowerSlideValue = inewy def set_minLogValue(self): """ Set the starting time and left slide bar """ debug_msg = 'Minimum Log Value = {}'.format(self.ui.lineEdit_5.text()) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() if str(self.ui.lineEdit_5.text()) == "": # Empty. Default to minY newminY = ylim[0] else: # Non empty. Parse newminY = float(self.ui.lineEdit_5.text()) # Convert to integer slide value iminlogval = int((newminY-ylim[0])/(ylim[1] - ylim[0])*100) Logger("Filter_Events").debug('ilowerSlide = {}'.format(iminlogval)) # Return if no change if iminlogval == self._lowerSlideValue: return # Set value if out of range resetL = True if iminlogval >= self._upperSlideValue: iminlogval = self._upperSlideValue - 1 else: resetL = False if resetL is True: newminY = ylim[0] + iminlogval * (ylim[1]-ylim[0]) * 0.01 # Move the vertical line lowerx = self.ui.mainplot.get_xlim() lowery = [newminY, newminY] setp(self.lowerslideline, xdata=lowerx, ydata=lowery) self.canvas.draw() # Move the slide bar (lower) self._lowerSlideValue = iminlogval debug_msg = 'LineEdit5 set slide to {}'.format(self._lowerSlideValue) Logger("Filter_Events").debug(debug_msg) self.ui.verticalSlider_2.setValue(self._lowerSlideValue) # Reset line Edit if using default if resetL is True: self.ui.lineEdit_5.setText(str(newminY)) def move_upperSlider(self): """ Re-setup upper range line in figure. Triggered by a change in Qt Widget. NO EVENT is required. """ inewy = self.ui.verticalSlider.value() # Return w/o change if inewy == self._upperSlideValue: return # Set to boundary value if inewy <= self._lowerSlideValue: inewy = self._lowerSlideValue + 1 # Reset line editor? if inewy == 100 and self._upperSlideValue > 100: setLineEdit = False else: setLineEdit = True # Move the upper value bar: upperx and uppery are # real value (float but not (0,100)) of the figure ylim = self.ui.mainplot.get_ylim() newy = ylim[0] + inewy*(ylim[1] - ylim[0])*0.01 upperx = self.ui.mainplot.get_xlim() uppery = [newy, newy] setp(self.upperslideline, xdata=upperx, ydata=uppery) self.canvas.draw() # Change value if setLineEdit is True: self.ui.lineEdit_6.setText(str(newy)) self._upperSlideValue = inewy def set_maxLogValue(self): """ Set maximum log value from line-edit """ inps = str(self.ui.lineEdit_6.text()) debug_msg = 'Maximum Log Value = {}'.format(inps) Logger("Filter_Events").debug(debug_msg) ylim = self.ui.mainplot.get_ylim() if inps == "": # Empty. Default to minY newmaxY = ylim[1] else: # Parse newmaxY = float(inps) # Convert to integer slide value imaxlogval = int((newmaxY-ylim[0])/(ylim[1] - ylim[0])*100) debug_msg = 'iUpperSlide = {}'.format(imaxlogval) Logger("Filter_Events").debug(debug_msg) # Return if no change if imaxlogval == self._upperSlideValue: return # Set to default if out of range resetL = True # if imaxlogval >= 100: # imaxlogval = 100 if imaxlogval < self._lowerSlideValue: imaxlogval = self._lowerSlideValue + 1 else: resetL = False # Set newmaxY if necessary if resetL is True: newmaxY = ylim[0] + imaxlogval * (ylim[1] - ylim[0]) * 0.01 # Move the vertical line upperx = self.ui.mainplot.get_xlim() uppery = [newmaxY, newmaxY] setp(self.upperslideline, xdata=upperx, ydata=uppery) self.canvas.draw() # Set the value to upper slider self._upperSlideValue = imaxlogval self.ui.verticalSlider.setValue(self._upperSlideValue) # Set the value to editor if necessary if resetL is True: self.ui.lineEdit_6.setText(str(newmaxY)) def browse_File(self): """ Open a file dialog to get file """ filename = QFileDialog.getOpenFileName(self, 'Input File Dialog', self._defaultdir, "Data (*.nxs *.dat);;All files (*)") if isinstance(filename, tuple): filename = filename[0] self.ui.lineEdit.setText(filename) Logger("Filter_Events").information('Selected file: "{}"'.format(filename)) def load_File(self): """ Load the file by file name or run number """ # Get file name from line editor filename = str(self.ui.lineEdit.text()) dataws = self._loadFile(str(filename)) if dataws is None: error_msg = 'Unable to locate run {} in default directory {}.'.format(filename, self._defaultdir) Logger("Filter_Events").error(error_msg) self._setErrorMsg(error_msg) else: self._importDataWorkspace(dataws) self._defaultdir = os.path.dirname(str(filename)) # Reset GUI self._resetGUI(resetfilerun=False) def use_existWS(self): """ Set up workspace to an existing one """ wsname = str(self.ui.comboBox.currentText()) try: dataws = AnalysisDataService.retrieve(wsname) self._importDataWorkspace(dataws) except KeyError: pass # Reset GUI self._resetGUI(resetfilerun=True) def plotLogValue(self): """ Plot log value """ # Get log value logname = str(self.ui.comboBox_2.currentText()) if len(logname) == 0: # return due to the empty one is chozen return samplelog = self._dataWS.getRun().getProperty(logname) vectimes = samplelog.times vecvalue = samplelog.value # check if len(vectimes) == 0: error_msg = "Empty log!" Logger("Filter_Events").error(error_msg) # Convert absolute time to relative time in seconds t0 = self._dataWS.getRun().getProperty("proton_charge").times[0] # append 1 more log if original log only has 1 value tf = self._dataWS.getRun().getProperty("proton_charge").times[-1] vectimes = numpy.append(vectimes, tf) vecvalue = numpy.append(vecvalue, vecvalue[-1]) vecreltimes = (vectimes - t0) / numpy.timedelta64(1, 's') # Set to plot xlim = [vecreltimes.min(), vecreltimes.max()] ylim = [vecvalue.min(), vecvalue.max()] self.ui.mainplot.set_xlim(xlim[0], xlim[1]) self.ui.mainplot.set_ylim(ylim[0], ylim[1]) setp(self.mainline, xdata=vecreltimes, ydata=vecvalue) samunit = samplelog.units if len(samunit) == 0: ylabel = logname else: ylabel = "%s (%s)" % (logname, samunit) self.ui.mainplot.set_ylabel(ylabel, fontsize=13) # assume that all logs are on almost same X-range. Only Y need to be reset setp(self.leftslideline, ydata=ylim) setp(self.rightslideline, ydata=ylim) # reset the log value limit as previous one does not make any sense setp(self.lowerslideline, xdata=xlim, ydata=[ylim[0], ylim[0]]) self._lowerSlideValue = 0 self.ui.verticalSlider_2.setValue(self._lowerSlideValue) self.ui.lineEdit_5.setText("") setp(self.upperslideline, xdata=xlim, ydata=[ylim[1], ylim[1]]) self._upperSlideValue = 100 self.ui.verticalSlider.setValue(self._upperSlideValue) self.ui.lineEdit_6.setText("") self.canvas.draw() # Load property's statistic and give suggestion on parallel and fast log timeavg = samplelog.timeAverageValue() numentries = samplelog.size() stat = samplelog.getStatistics() duration = stat.duration mean = stat.mean freq = float(numentries)/float(duration) self.ui.label_mean.show() self.ui.label_meanvalue.show() self.ui.label_avg.show() self.ui.label_timeAvgValue.show() self.ui.label_freq.show() self.ui.label_freqValue.show() self.ui.label_logname.show() self.ui.label_lognamevalue.show() self.ui.label_logsize.show() self.ui.label_logsizevalue.show() self.ui.label_meanvalue.setText("%.5e" % (mean)) self.ui.label_timeAvgValue.setText("%.5e" % (timeavg)) self.ui.label_freqValue.setText("%.5e" % (freq)) self.ui.label_lognamevalue.setText(logname) self.ui.label_logsizevalue.setText(str(numentries)) # Set suggested processing scheme if numentries > HUGE_FAST: self.ui.checkBox_fastLog.setCheckState(True) if numentries > HUGE_PARALLEL: self.ui.checkBox_doParallel.setCheckState(True) else: self.ui.checkBox_doParallel.setCheckState(False) else: self.ui.checkBox_fastLog.setCheckState(False) self.ui.checkBox_doParallel.setCheckState(False) return def _importDataWorkspace(self, dataws): """ Import data workspace for filtering """ if dataws is None: return # Plot time counts errmsg = self._plotTimeCounts(dataws) if errmsg is not None: errmsg = 'Workspace {} has invalid sample logs for splitting. Loading \ failure! \n{}\n'.format(dataws, errmsg) self._setErrorMsg(errmsg) return False # Import log self._sampleLogNames = [""] run = dataws.getRun() plist = run.getProperties() for p in plist: try: times = p.times if len(times) > 1 and numpy.isreal(p.value[0]): self._sampleLogNames.append(p.name) # This is here for FloatArrayProperty. If a log value is of this type it does not have times except AttributeError: pass # ENDFOR(p) # Set up sample log self.ui.comboBox_2.clear() self.ui.comboBox_2.addItems(self._sampleLogNames) # Side information self.ui.label_mean.hide() self.ui.label_meanvalue.hide() self.ui.label_avg.hide() self.ui.label_timeAvgValue.hide() self.ui.label_freq.hide() self.ui.label_freqValue.hide() # Hide 'log name' above the graphic view self.ui.label_logname.hide() self.ui.label_lognamevalue.hide() # Set dataws to class variable self._dataWS = dataws return True def scanEventWorkspaces(self): """ """ wsnames = AnalysisDataService.getObjectNames() eventwsnames = [] for wsname in wsnames: wksp = AnalysisDataService.retrieve(wsname) if wksp.__class__.__name__.count("Event") == 1: eventwsnames.append(wsname) # ENDFOR if len(eventwsnames) > 0: self.ui.comboBox.clear() self.ui.comboBox.addItems(eventwsnames) def _loadFile(self, filename): """ Load file or run File will be loaded to a workspace shown in MantidPlot """ config = ConfigService # Check input file name and output workspace name if filename.isdigit() is True: # Construct a file name from run number runnumber = int(filename) if runnumber <= 0: error_msg = 'Run number cannot be less or equal to zero. User gives {}.'.format(filename) Logger("Filter_Events").error(error_msg) return None else: ishort = config.getInstrument(self._instrument).shortName() filename = '{}_{}'.format(ishort, filename) wsname = filename + "_event" elif filename.count(".") > 0: # A proper file name wsname = os.path.splitext(os.path.split(filename)[1])[0] elif filename.count("_") == 1: # A short one as instrument_runnumber iname = filename.split("_")[0] str_runnumber = filename.split("_")[1] if str_runnumber.isdigit() is True and int(str_runnumber) > 0: # Accepted format ishort = config.getInstrument(iname).shortName() wsname = '{}_{}_event'.format(ishort, str_runnumber) else: # Non-supported error_msg = 'File name / run number in such format {} is not supported.'.format(filename) Logger("Filter_Events").error(error_msg) return None else: # Unsupported format error_msg = 'File name / run number in such format {} is not supported.'.format(filename) Logger("Filter_Events").error(error_msg) return None # Load try: ws = api.Load(Filename=filename, OutputWorkspace=wsname) except RuntimeError as e: ws = None return str(e) return ws def _plotTimeCounts(self, wksp): """ Plot time/counts """ import datetime # Rebin events by pulse time try: # Get run start and run stop if wksp.getRun().hasProperty("run_start"): runstart = wksp.getRun().getProperty("run_start").value else: runstart = wksp.getRun().getProperty("proton_charge").times[0] runstop = wksp.getRun().getProperty("proton_charge").times[-1] runstart = str(runstart).split(".")[0].strip() runstop = str(runstop).split(".")[0].strip() t0 = datetime.datetime.strptime(runstart, "%Y-%m-%dT%H:%M:%S") tf = datetime.datetime.strptime(runstop, "%Y-%m-%dT%H:%M:%S") # Calculate dt = tf-t0 timeduration = dt.days*3600*24 + dt.seconds timeres = float(timeduration)/MAXTIMEBINSIZE if timeres < 1.0: timeres = 1.0 sumwsname = '_Summed_{}'.format(wksp) if AnalysisDataService.doesExist(sumwsname) is False: sumws = api.SumSpectra(InputWorkspace=wksp, OutputWorkspace=sumwsname) sumws = api.RebinByPulseTimes(InputWorkspace=sumws, OutputWorkspace=sumwsname, Params='{}'.format(timeres)) sumws = api.ConvertToPointData(InputWorkspace=sumws, OutputWorkspace=sumwsname) else: sumws = AnalysisDataService.retrieve(sumwsname) except RuntimeError as e: return str(e) vecx = sumws.readX(0) vecy = sumws.readY(0) xmin = min(vecx) xmax = max(vecx) ymin = min(vecy) ymax = max(vecy) # Reset graph self.ui.mainplot.set_xlim(xmin, xmax) self.ui.mainplot.set_ylim(ymin, ymax) self.ui.mainplot.set_xlabel('Time (seconds)', fontsize=13) self.ui.mainplot.set_ylabel('Counts', fontsize=13) # Set up main line setp(self.mainline, xdata=vecx, ydata=vecy) # Reset slide newslidery = [min(vecy), max(vecy)] newleftx = xmin + (xmax-xmin)*self._leftSlideValue*0.01 setp(self.leftslideline, xdata=[newleftx, newleftx], ydata=newslidery) newrightx = xmin + (xmax-xmin)*self._rightSlideValue*0.01 setp(self.rightslideline, xdata=[newrightx, newrightx], ydata=newslidery) self.canvas.draw() def filterByTime(self): """ Filter by time """ # Generate event filters kwargs = {} if self.ui.lineEdit_3.text() != "": rel_starttime = float(self.ui.lineEdit_3.text()) kwargs["StartTime"] = str(rel_starttime) if self.ui.lineEdit_4.text() != "": rel_stoptime = float(self.ui.lineEdit_4.text()) kwargs["StopTime"] = str(rel_stoptime) if self.ui.lineEdit_timeInterval.text() != "": interval = float(self.ui.lineEdit_timeInterval.text()) kwargs["TimeInterval"] = interval splitwsname = str(self._dataWS) + "_splitters" splitinfowsname = str(self._dataWS) + "_info" title = str(self.ui.lineEdit_title.text()) fastLog = self.ui.checkBox_fastLog.isChecked() splitws, infows = api.GenerateEventsFilter(InputWorkspace=self._dataWS, UnitOfTime="Seconds", TitleOfSplitters=title, OutputWorkspace=splitwsname, FastLog=fastLog, InformationWorkspace=splitinfowsname, **kwargs) self.splitWksp(splitws, infows) def filterByLogValue(self): """ Filter by log value """ # Generate event filter kwargs = {} samplelog = str(self.ui.comboBox_2.currentText()) if len(samplelog) == 0: error_msg = "No sample log is selected!" Logger("Filter_Events").error(error_msg) return if self.ui.lineEdit_3.text() != "": rel_starttime = float(self.ui.lineEdit_3.text()) kwargs["StartTime"] = str(rel_starttime) if self.ui.lineEdit_4.text() != "": rel_stoptime = float(self.ui.lineEdit_4.text()) kwargs["StopTime"] = str(rel_stoptime) if self.ui.lineEdit_5.text() != "": minlogvalue = float(self.ui.lineEdit_5.text()) kwargs["MinimumLogValue"] = minlogvalue if self.ui.lineEdit_6.text() != "": maxlogvalue = float(self.ui.lineEdit_6.text()) kwargs["MaximumLogValue"] = maxlogvalue if self.ui.lineEdit_7.text() != "": logvalueintv = float(self.ui.lineEdit_7.text()) kwargs["LogValueInterval"] = logvalueintv logvalchangedir = str(self.ui.comboBox_4.currentText()) kwargs["FilterLogValueByChangingDirection"] = logvalchangedir if self.ui.lineEdit_9.text() != "": logvalueintv = float(self.ui.lineEdit_9.text()) kwargs["TimeTolerance"] = logvalueintv logboundtype = str(self.ui.comboBox_5.currentText()) kwargs["LogBoundary"] = logboundtype if self.ui.lineEdit_8.text() != "": logvaluetol = float(self.ui.lineEdit_8.text()) kwargs["LogValueTolerance"] = logvaluetol splitwsname = str(self._dataWS) + "_splitters" splitinfowsname = str(self._dataWS) + "_info" fastLog = self.ui.checkBox_fastLog.isChecked() title = str(self.ui.lineEdit_title.text()) splitws, infows = api.GenerateEventsFilter(InputWorkspace=self._dataWS, UnitOfTime="Seconds", TitleOfSplitters=title, OutputWorkspace=splitwsname, LogName=samplelog, FastLog=fastLog, InformationWorkspace=splitinfowsname, **kwargs) try: self.splitWksp(splitws, infows) except RuntimeError as e: self._setErrorMsg("Splitting Failed!\n %s" % (str(e))) def splitWksp(self, splitws, infows): """ Run FilterEvents """ dogroupws = self.ui.checkBox_groupWS.isChecked() filterbypulse = self.ui.checkBox_filterByPulse.isChecked() startfrom1 = self.ui.checkBox_from1.isChecked() splitsamplelog = self.ui.checkBox_splitLog.isChecked() corr2sample = str(self.ui.comboBox_tofCorr.currentText()) how2skip = str(self.ui.comboBox_skipSpectrum.currentText()) kwargs = {} if corr2sample == "Direct": ei = float(self.ui.lineEdit_Ei.text()) kwargs["IncidentEnergy"] = ei elif corr2sample == "Customized": corrws = str(self.ui.comboBox_corrWS.currentText()) kwargs["DetectorTOFCorrectionWorkspace"] = corrws # Output workspace name outbasewsname = str(self.ui.lineEdit_outwsname.text()) if len(outbasewsname) == 0: outbasewsname = "tempsplitted" self.ui.lineEdit_outwsname.setText(outbasewsname) api.FilterEvents(InputWorkspace=self._dataWS, SplitterWorkspace=splitws, InformationWorkspace=infows, OutputWorkspaceBaseName=outbasewsname, GroupWorkspaces=dogroupws, FilterByPulseTime=filterbypulse, CorrectionToSample=corr2sample, SpectrumWithoutDetector=how2skip, SplitSampleLogs=splitsamplelog, OutputWorkspaceIndexedFrom1=startfrom1, OutputTOFCorrectionWorkspace='TOFCorrTable', **kwargs) def showHideEi(self): """ """ corrtype = str(self.ui.comboBox_tofCorr.currentText()) # Incident energy if corrtype == "Direct": self.ui.label_Ei.show() self.ui.lineEdit_Ei.show() else: self.ui.label_Ei.hide() self.ui.lineEdit_Ei.hide() # Workspace if corrtype == "Customized": self.ui.label_Ei_2.show() self.ui.comboBox_corrWS.show() self.ui.pushButton_refreshCorrWSList.show() # Search for table workspace self._searchTableWorkspaces() else: self.ui.label_Ei_2.hide() self.ui.comboBox_corrWS.hide() self.ui.pushButton_refreshCorrWSList.hide() def _searchTableWorkspaces(self): """ Search table workspaces and add to 'comboBox_corrWS' """ wsnames = AnalysisDataService.getObjectNames() tablewsnames = [] for wsname in wsnames: wksp = AnalysisDataService.retrieve(wsname) if isinstance(wksp, mantid.api.ITableWorkspace): tablewsnames.append(wsname) # ENDFOR self.ui.comboBox_corrWS.clear() if len(tablewsnames) > 0: self.ui.comboBox_corrWS.addItems(tablewsnames) def _setErrorMsg(self, errmsg): """ Clear error message """ self._errMsgWindow = QMessageBox() self._errMsgWindow.setIcon(QMessageBox.Critical) self._errMsgWindow.setWindowTitle('Error') self._errMsgWindow.setStandardButtons(QMessageBox.Ok) self._errMsgWindow.setText(errmsg) result = self._errMsgWindow.exec_() return result def helpClicked(self): try: from pymantidplot.proxies import showCustomInterfaceHelp showCustomInterfaceHelp("Filter Events") except ImportError: url = ("http://docs.mantidproject.org/nightly/interfaces/{}.html" "".format("Filter Events")) QDesktopServices.openUrl(QUrl(url)) def _resetGUI(self, resetfilerun=False): """ Reset GUI including all text edits and etc. """ if resetfilerun is True: self.ui.lineEdit.clear() # Plot related self.ui.lineEdit_3.clear() self.ui.lineEdit_4.clear() self.ui.horizontalSlider.setValue(0) self.ui.horizontalSlider_2.setValue(100) self.ui.lineEdit_outwsname.clear() self.ui.lineEdit_title.clear() # Filter by log value self.ui.lineEdit_5.clear() self.ui.lineEdit_6.clear() self.ui.verticalSlider_2.setValue(0) self.ui.verticalSlider.setValue(100) ylim = self.ui.mainplot.get_ylim() miny = ylim[0] maxy = ylim[1] xlim = self.ui.mainplot.get_xlim() setp(self.lowerslideline, xdata=xlim, ydata=[miny, miny]) setp(self.upperslideline, xdata=xlim, ydata=[maxy, maxy]) self.ui.lineEdit_7.clear() self.ui.lineEdit_8.clear() self.ui.lineEdit_9.clear() # Filter by time self.ui.lineEdit_timeInterval.clear() # Advanced setup self.ui.comboBox_tofCorr.setCurrentIndex(0) self.ui.lineEdit_Ei.clear() self.ui.checkBox_fastLog.setCheckState(False) self.ui.checkBox_doParallel.setCheckState(False) self.ui.comboBox_skipSpectrum.setCurrentIndex(0) self.ui.checkBox_filterByPulse.setCheckState(False) self.ui.checkBox_from1.setCheckState(False) self.ui.checkBox_groupWS.setCheckState(True) self.ui.checkBox_splitLog.setCheckState(False) self.canvas.draw()
class AbortWindow(QDialog): """ Displays busy message and provides abort button. The class serves SmoothCube, WorkerThread and SelectSmoothing. """ def __init__(self, parent=None): """ init abort or notification ui. Displays while smoothing freezes the application. Allows abort button to be added if needed. """ super(AbortWindow, self).__init__(parent) self.setModal(False) self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) self.parent = parent self.label_a_1 = QLabel("Executing smoothing algorithm.") self.label_a_2 = QLabel("This may take several minutes.") self.abort_button = QPushButton("Abort") self.abort_button.clicked.connect(self.abort) self.pb = QProgressBar(self) self.pb_counter = 0 self.abort_flag = False self.info_box = None # vbl is short for Vertical Box Layout vbl = QVBoxLayout() vbl.addWidget(self.label_a_1) vbl.addWidget(self.label_a_2) vbl.addWidget(self.pb) vbl.addWidget(self.abort_button) self.setLayout(vbl) self.show() def init_pb(self, start, end): """ Init the progress bar :param start: Start Value :param end: End Value """ self.pb.setRange(start, end) self.pb_counter = start def update_pb(self): """ This function is called in the worker thread to update the progress bar and checks if the local class variable abort_flag is active. If the abort button is clicked, the main thread will set abort_flag to True. The next time the worker thread calls this function, a custom exception is raised terminating the calculation. The exception is handled by the WorkerThread class. :raises: AbortException: terminating smoothing calculation """ if self.abort_flag: raise AbortException("Abort Calculation") self.pb_counter += 1 self.pb.setValue(self.pb_counter) QApplication.processEvents() def abort(self): """Abort calculation""" self.abort_flag = True self.parent.clean_up() def show_error_message(self, message, title, parent=None): self.info_box = QMessageBox(parent=parent) self.info_box.setIcon(QMessageBox.Information) self.info_box.setText(message) self.info_box.setWindowTitle(title) self.info_box.setStandardButtons(QMessageBox.Ok) self.info_box.show() def smoothing_done(self, component_id=None): """Notify user success""" self.hide() if component_id is None: message = "The result has been added as a" \ " new component of the input Data." \ " The new component can be accessed" \ " in the viewer drop-downs." else: message = "The result has been added as" \ " \"{0}\" and can be selected" \ " in the viewer drop-down menu.".format(component_id) self.show_error_message(message, "Success", self) self.clean_up() def print_error(self, exception): """Print error message""" if "signal only works in main thread" in str(exception): message = "Smoothing Failed!\n\n" + "Please update your SpectralCube package" else: message = "Smoothing Failed!\n\n" + str(exception) self.show_error_message(message, "Error", self) self.clean_up() def clean_up(self): self.parent.clean_up() def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.abort()