def start_powder_calibration(self): if not HexrdConfig().has_images(): msg = ('No images available for calibration.') QMessageBox.warning(self.ui, 'HEXRD', msg) return d = PowderCalibrationDialog(self.ui) if not d.exec_(): return HexrdConfig().emit_update_status_bar('Running powder calibration...') # Run the calibration in a background thread worker = AsyncWorker(run_powder_calibration) self.thread_pool.start(worker) # We currently don't have any progress updates, so make the # progress bar indeterminate. self.progress_dialog.setRange(0, 0) self.progress_dialog.setWindowTitle('Calibration Running') # Get the results and close the progress dialog when finished worker.signals.result.connect(self.finish_powder_calibration) worker.signals.finished.connect(self.progress_dialog.accept) msg = 'Powder calibration finished!' f = lambda: HexrdConfig().emit_update_status_bar(msg) worker.signals.finished.connect(f) self.progress_dialog.exec_()
def indexer_finished(self): # Compute number of orientations run_cluster() will use # to make sure there aren't too many config = create_indexing_config() min_compl = config.find_orientations.clustering.completeness num_orientations = (np.array(self.completeness) > min_compl).sum() num_orientations_warning_threshold = 1e6 if num_orientations > num_orientations_warning_threshold: formatted = format_big_int(num_orientations) msg = (f'Over {formatted} orientations are staged for ' 'clustering. This may use up too much memory.\n\n' 'Proceed anyways?') response = QMessageBox.question(self.parent, 'WARNING', msg) if response == QMessageBox.No: # Go back to the eta omega maps viewer self.accept_progress() self.view_ome_maps() return worker = AsyncWorker(self.run_cluster_functions) self.thread_pool.start(worker) worker.signals.result.connect(self.start_fit_grains_runner, Qt.QueuedConnection) worker.signals.finished.connect(self.accept_progress) worker.signals.error.connect(self.on_async_error)
def ome_maps_viewed(self): # The dialog should have automatically updated our internal config # Let's go ahead and run the indexing! # Create a full indexing config config = create_indexing_config() # Hexrd normally applies filtering immediately after eta omega # maps are loaded. We will perform the user-selected filtering now. filter_maps_if_requested(self.ome_maps, config) # Setup to run indexing in background self.progress_dialog.setWindowTitle('Find Orientations') self.progress_dialog.setRange(0, 0) # no numerical updates find_orientations = HexrdConfig().indexing_config['find_orientations'] if find_orientations['use_quaternion_grid']: # Load qfib from a numpy file self.qfib = np.load(find_orientations['use_quaternion_grid']) self.orientation_fibers_generated() else: worker = AsyncWorker(self.generate_orientation_fibers, config) self.thread_pool.start(worker) worker.signals.result.connect(self.orientation_fibers_generated) worker.signals.error.connect(self.on_async_error) self.progress_dialog.exec_()
def fit_grains_options_accepted(self): # Setup to run in background self.progress_dialog.setWindowTitle('Running Fit Grains') self.progress_dialog.setRange(0, 0) # no numerical updates worker = AsyncWorker(self.run_fit_grains) self.thread_pool.start(worker) worker.signals.result.connect(self.view_fit_grains_results) worker.signals.error.connect(self.on_async_error) worker.signals.finished.connect(self.accept_progress) self.progress_dialog.exec_()
def fit_grains_options_accepted(self): # Create a full indexing config config = create_indexing_config() # Setup to run in background self.progress_dialog.setWindowTitle('Fit Grains') self.progress_dialog.setRange(0, 0) # no numerical updates worker = AsyncWorker(self.run_fit_grains, config) self.thread_pool.start(worker) worker.signals.result.connect(self.view_fit_grains_results) worker.signals.finished.connect(self.progress_dialog.accept) self.progress_dialog.exec_()
def run(self, f): worker = AsyncWorker(f) self.thread_pool.start(worker) if self.success_callback: worker.signals.result.connect(self.success_callback) if self.error_callback: worker.signals.error.connect(self.error_callback) else: worker.signals.error.connect(self.on_async_error) worker.signals.finished.connect(self.reset_callbacks) worker.signals.finished.connect(self.progress_dialog.accept) self.progress_dialog.exec_()
def begin_processing(self, postprocess=False): # Create threads and loading dialog thread_pool = QThreadPool(self.parent) progress_dialog = ProgressDialog(self.parent) progress_dialog.setWindowTitle('Loading Processed Imageseries') self.progress_text.connect(progress_dialog.setLabelText) self.progress_dialog = progress_dialog # Start processing in background worker = AsyncWorker(self.process_ims, postprocess) thread_pool.start(worker) worker.signals.progress.connect(progress_dialog.setValue) # On completion load imageseries nd close loading dialog worker.signals.result.connect(self.finish_processing_ims) worker.signals.finished.connect(progress_dialog.accept) progress_dialog.exec_()
def read_data(self): # When this is pressed read in a complete set of data for all detectors. # Run the imageseries processing in a background thread and display a # loading dialog # Create threads and loading dialog thread_pool = QThreadPool(self.parent()) progress_dialog = CalProgressDialog(self.parent()) progress_dialog.setWindowTitle('Loading Processed Imageseries') # Start processing in background worker = AsyncWorker(self.process_ims) thread_pool.start(worker) # On completion load imageseries nd close loading dialog worker.signals.result.connect(self.finish_processing_ims) worker.signals.finished.connect(progress_dialog.accept) progress_dialog.exec_()
def save_images(self): if self.ui.ignore_agg.isChecked(): ims_dict = HexrdConfig().unagg_images else: ims_dict = HexrdConfig().imageseries_dict dets = HexrdConfig().detector_names if self.ui.single_detector.isChecked(): dets = [self.ui.detectors.currentText()] for det in dets: selected_format = self.ui.format.currentText().lower() filename = f'{self.ui.file_stem.text()}_{det}.{selected_format}' path = f'{self.parent_dir}/{filename}' if selected_format.startswith('hdf5'): selected_format = 'hdf5' elif selected_format.startswith('npz'): selected_format = 'frame-cache' kwargs = {} if selected_format == 'hdf5': # A path must be specified. Set it ourselves for now. kwargs['path'] = 'imageseries' elif selected_format == 'frame-cache': # Get the user to pick a threshold result, ok = QInputDialog.getDouble(self.ui, 'HEXRD', 'Choose Threshold', 10, 0, 1e12, 3) if not ok: # User canceled... return kwargs['threshold'] = result # This needs to be specified, but I think it just needs # to be the same as the file name... kwargs['cache_file'] = path worker = AsyncWorker(HexrdConfig().save_imageseries, ims_dict.get(det), det, path, selected_format, **kwargs) self.thread_pool.start(worker) self.progress_dialog.setWindowTitle(f'Saving {filename}') self.progress_dialog.setRange(0, 0) worker.signals.finished.connect(self.progress_dialog.accept) self.progress_dialog.exec_()
def start_line_picked_calibration(self, line_data): HexrdConfig().emit_update_status_bar('Running powder calibration...') # Run the calibration in a background thread worker = AsyncWorker(run_line_picked_calibration, line_data) self.thread_pool.start(worker) # We currently don't have any progress updates, so make the # progress bar indeterminate. self.progress_dialog.setRange(0, 0) self.progress_dialog.setWindowTitle('Calibration Running') # Get the results and close the progress dialog when finished worker.signals.result.connect(self.finish_line_picked_calibration) worker.signals.finished.connect(self.progress_dialog.accept) msg = 'Powder calibration finished!' f = lambda: HexrdConfig().emit_update_status_bar(msg) worker.signals.finished.connect(f) self.progress_dialog.exec_()
def show_polar(self): HexrdConfig().emit_update_status_bar('Loading polar view...') if self.mode != ViewType.polar: self.clear() self.mode = ViewType.polar polar_res_config = HexrdConfig().config['image']['polar'] if self._polar_reset_needed(polar_res_config): # Reset the whole image when certain config items change self.clear() self.mode = ViewType.polar self.polar_res_config = polar_res_config.copy() # Run the calibration in a background thread worker = AsyncWorker(polar_viewer) self.thread_pool.start(worker) # Get the results and close the progress dialog when finished worker.signals.result.connect(self.finish_show_polar)
def show_cartesian(self): HexrdConfig().emit_update_status_bar('Loading Cartesian view...') if self.mode != ViewType.cartesian: self.clear() self.mode = ViewType.cartesian # Force a redraw when the pixel size changes. if (self.cartesian_res_config != HexrdConfig().config['image']['cartesian']): self.cartesian_res_config = ( HexrdConfig().config['image']['cartesian'].copy()) self.figure.clear() self.axes_images.clear() # Run the calibration in a background thread worker = AsyncWorker(cartesian_viewer) self.thread_pool.start(worker) # Get the results and close the progress dialog when finished worker.signals.result.connect(self.finish_show_cartesian)
def orientation_fibers_generated(self): # Perform some validation qfib_warning_threshold = 5e7 if self.qfib.shape[1] > qfib_warning_threshold: formatted = format_big_int(self.qfib.shape[1]) msg = (f'Over {formatted} test orientations were ' 'generated. This may use up too much memory.\n\n' 'Proceed anyways?') response = QMessageBox.question(self.parent, 'WARNING', msg) if response == QMessageBox.No: # Go back to the eta omega maps viewer self.accept_progress() self.view_ome_maps() return worker = AsyncWorker(self.run_indexer) self.thread_pool.start(worker) worker.signals.result.connect(self.indexer_finished) worker.signals.error.connect(self.on_async_error)
def ome_maps_viewed(self): # The dialog should have automatically updated our internal config # Let's go ahead and run the indexing! # For now, always use all hkls from eta omega maps hkls = list(range(len(self.ome_maps.iHKLList))) indexing_config = HexrdConfig().indexing_config indexing_config['find_orientations']['seed_search']['hkl_seeds'] = hkls # Create a full indexing config config = create_indexing_config() # Setup to run indexing in background self.progress_dialog.setWindowTitle('Find Orientations') self.progress_dialog.setRange(0, 0) # no numerical updates worker = AsyncWorker(self.run_indexer, config) self.thread_pool.start(worker) worker.signals.result.connect(self.view_fit_grains_options) worker.signals.finished.connect(self.progress_dialog.accept) self.progress_dialog.exec_()
def ome_maps_selected(self): dialog = self.ome_maps_select_dialog if dialog is None: return if dialog.method_name == 'load': self.ome_maps = EtaOmeMaps(dialog.file_name) self.ome_maps_select_dialog = None self.view_ome_maps() else: # Create a full indexing config config = create_indexing_config() # Setup to generate maps in background self.progress_dialog.setWindowTitle('Generating Eta Omega Maps') self.progress_dialog.setRange(0, 0) # no numerical updates worker = AsyncWorker(self.run_eta_ome_maps, config) self.thread_pool.start(worker) worker.signals.result.connect(self.view_ome_maps) worker.signals.finished.connect(self.progress_dialog.accept) self.progress_dialog.exec_()
def on_action_open_config_dir_triggered(self): dialog = QFileDialog(self.ui, 'Load Configuration', HexrdConfig().working_dir, 'HEXRD directories (*)') dialog.setFileMode(QFileDialog.Directory) selected_files = [] if dialog.exec_(): selected_files = dialog.selectedFiles() if len(selected_files) == 0: return else: selected_file = selected_files[0] path = Path(selected_file) def _load(): path = Path(selected_file) HexrdConfig().working_dir = str(path.parent) # Opening a .hexrd directory, so point to config.yml path = path / 'config.yml' HexrdConfig().load_instrument_config(str(path)) # Check we have the config.yml if not (path / 'config.yml').exists(): msg = 'Invalid HEXRD directory, config.yml missing.' QMessageBox.critical(self.ui, 'HEXRD', msg) return # We do this in a worker thread so the UI can refresh. worker = AsyncWorker(_load) worker.signals.finished.connect(self.update_config_gui) self.thread_pool.start(worker)