class FindDialog(NXDialog): def __init__(self, parent=None): super().__init__(parent) self.select_entry(self.choose_entry) default = NXSettings().settings['nxreduce'] self.parameters = GridParameters() self.parameters.add('threshold', default['threshold'], 'Threshold') self.parameters.add('first', default['first'], 'First Frame') self.parameters.add('last', default['last'], 'Last Frame') self.parameters.add('min_pixels', default['min_pixels'], 'Minimum Pixels in Peak') self.parameters.grid() self.find_button = NXPushButton('Find Peaks', self.find_peaks) self.find_layout = self.make_layout(self.action_buttons( ('Find Peaks', self.find_peaks), ('List Peaks', self.list_peaks)), align='center') self.set_layout(self.entry_layout, self.close_layout(save=True, progress=True)) self.set_title('Find Peaks') self.reduce = None self.refine = None self.peaks_box = None def choose_entry(self): if self.layout.count() == 2: self.insert_layout(1, self.parameters.grid_layout) self.insert_layout(2, self.find_layout) self.reduce = NXReduce(self.entry) self.refine = NXRefine(self.entry) self.refine.polar_max = self.refine.two_theta_max() if self.reduce.first is not None: self.parameters['first'].value = self.reduce.first if self.reduce.last: self.parameters['last'].value = self.reduce.last else: try: self.parameters['last'].value = self.reduce.shape[0] except Exception: pass self.parameters['threshold'].value = self.reduce.threshold @property def threshold(self): try: return int(self.parameters['threshold'].value) except Exception as error: report_error("Finding Peaks", error) @property def first(self): try: return int(self.parameters['first'].value) except Exception as error: report_error("Finding Peaks", error) @property def last(self): try: return int(self.parameters['last'].value) except Exception as error: report_error("Finding Peaks", error) @property def min_pixels(self): try: return int(self.parameters['min_pixels'].value) except Exception as error: report_error("Finding Peaks", error) def find_peaks(self): if is_file_locked(self.reduce.data_file): return self.start_thread() self.reduce = NXReduce(self.entry, threshold=self.threshold, first=self.first, last=self.last, min_pixels=self.min_pixels, find=True, overwrite=True, gui=True) self.reduce.moveToThread(self.thread) self.reduce.start.connect(self.start_progress) self.reduce.update.connect(self.update_progress) self.reduce.result.connect(self.get_peaks) self.reduce.stop.connect(self.stop) self.thread.started.connect(self.reduce.nxfind) self.thread.start() def get_peaks(self, peaks): self.peaks = peaks self.status_message.setText(f'{len(self.peaks)} peaks found') self.status_message.setVisible(True) self.refine.xp = np.array([peak.x for peak in peaks]) self.refine.yp = np.array([peak.y for peak in peaks]) self.refine.zp = np.array([peak.z for peak in peaks]) self.refine.intensity = np.array([peak.intensity for peak in peaks]) self.refine.polar_angle, self.refine.azimuthal_angle = ( self.refine.calculate_angles(self.refine.xp, self.refine.yp)) self.update_table() def stop(self): self.stop_progress() if self.thread and self.thread.isRunning(): self.reduce.stopped = True self.stop_thread() def list_peaks(self): if self.peaks_box in self.mainwindow.dialogs: self.update_table() return self.peaks_box = NXDialog(self) self.peaks_box.setMinimumWidth(600) self.peaks_box.setMinimumHeight(600) header = [ 'i', 'x', 'y', 'z', 'Polar', 'Azi', 'Intensity', 'H', 'K', 'L', 'Diff' ] peak_list = self.refine.get_peaks() self.table_view = QtWidgets.QTableView() self.table_model = NXTableModel(self, peak_list, header) self.table_view.setModel(self.table_model) self.table_view.resizeColumnsToContents() self.table_view.horizontalHeader().stretchLastSection() self.table_view.setSelectionBehavior( QtWidgets.QAbstractItemView.SelectRows) self.table_view.doubleClicked.connect(self.plot_peak) self.table_view.setSortingEnabled(True) self.table_view.sortByColumn(0, QtCore.Qt.AscendingOrder) self.peaks_box.set_layout(self.table_view, self.close_buttons(close=True)) self.peaks_box.set_title(f'{self.refine.name} Peak Table') self.peaks_box.adjustSize() self.peaks_box.show() self.plotview = None def update_table(self): if self.peaks_box not in self.mainwindow.dialogs: return elif self.table_model is None: self.close_peaks_box() self.list_peaks() self.table_model.peak_list = self.refine.get_peaks() rows, columns = len(self.table_model.peak_list), 11 self.table_model.dataChanged.emit( self.table_model.createIndex(0, 0), self.table_model.createIndex(rows - 1, columns - 1)) self.table_view.resizeColumnsToContents() self.peaks_box.set_title(f'{self.refine.name} Peak Table') self.peaks_box.adjustSize() self.peaks_box.setVisible(True) def plot_peak(self): row = self.table_view.currentIndex().row() data = self.entry.data i, x, y, z = [ self.table_view.model().peak_list[row][i] for i in range(4) ] signal = data.nxsignal xmin, xmax = max(0, x - 200), min(x + 200, signal.shape[2]) ymin, ymax = max(0, y - 200), min(y + 200, signal.shape[1]) zmin, zmax = max(0, z - 20), min(z + 20, signal.shape[0]) zslab = np.s_[zmin:zmax, ymin:ymax, xmin:xmax] if 'Peak Plot' in self.plotviews: self.plotview = self.plotviews['Peak Plot'] else: self.plotview = NXPlotView('Peak Plot') self.plotview.plot(data[zslab], log=True) self.plotview.ax.set_title(f'{data.nxtitle}: Peak {i}') self.plotview.ztab.maxbox.setValue(z) self.plotview.aspect = 'equal' self.plotview.crosshairs(x, y, color='r', linewidth=0.5) def close_peaks_box(self): try: self.peaks_box.close() except Exception: pass self.peaks_box = None def accept(self): try: self.reduce.write_peaks(self.peaks) self.reduce.record('nxfind', threshold=self.threshold, first_frame=self.first, last_frame=self.last, min_pixels=self.min_pixels, peak_number=len(self.peaks)) self.reduce.record_end('nxfind') super().accept() except Exception as error: report_error("Finding Peaks", error) def reject(self): self.stop() super().reject()
class PrepareDialog(NXDialog): def __init__(self, parent=None): super().__init__(parent) self.select_entry(self.choose_entry) default = NXSettings().settings['nxreduce'] self.parameters = GridParameters() self.parameters.add('first', default['first'], 'First Frame') self.parameters.add('last', default['last'], 'Last Frame') self.parameters.add('threshold1', '2', 'Threshold 1') self.parameters.add('horizontal1', '11', 'Horizontal Size 1') self.parameters.add('threshold2', '0.8', 'Threshold 2') self.parameters.add('horizontal2', '51', 'Horizontal Size 2') self.parameters.grid() self.prepare_button = NXPushButton('Prepare Mask', self.prepare_mask) self.plot_button = NXPushButton('Plot Mask', self.plot_mask) self.prepare_layout = self.make_layout(self.prepare_button, self.plot_button, align='center') self.plot_button.setVisible(False) self.set_layout(self.entry_layout, self.close_layout(save=True, progress=True)) self.set_title('Prepare 3D Mask') self.reduce = None self.mask = None self.plotview = None def choose_entry(self): if self.layout.count() == 2: self.insert_layout(1, self.parameters.grid_layout) self.insert_layout(2, self.prepare_layout) self.reduce = NXReduce(self.entry) self.parameters['first'].value = self.reduce.first self.parameters['last'].value = self.reduce.last @property def first(self): try: return int(self.parameters['first'].value) except Exception as error: report_error("Preparing Mask", error) @property def last(self): try: return int(self.parameters['last'].value) except Exception as error: report_error("Preparing Mask", error) @property def threshold1(self): try: return float(self.parameters['threshold1'].value) except Exception as error: report_error("Preparing Mask", error) @property def horizontal1(self): try: return int(self.parameters['horizontal1'].value) except Exception as error: report_error("Preparing Mask", error) @property def threshold2(self): try: return float(self.parameters['threshold2'].value) except Exception as error: report_error("Preparing Mask", error) @property def horizontal2(self): try: return int(self.parameters['horizontal2'].value) except Exception as error: report_error("Preparing Mask", error) def prepare_mask(self): if is_file_locked(self.reduce.data_file): return self.start_thread() self.reduce = NXReduce(self.entry, prepare=True, first=self.first, last=self.last, overwrite=True, gui=True) self.reduce.mask_parameters['threshold_1'] = self.threshold1 self.reduce.mask_parameters['threshold_1'] = self.threshold1 self.reduce.mask_parameters['horizontal_size_1'] = self.horizontal1 self.reduce.mask_parameters['threshold_2'] = self.threshold2 self.reduce.mask_parameters['horizontal_size_2'] = self.horizontal2 self.reduce.moveToThread(self.thread) self.reduce.start.connect(self.start_progress) self.reduce.update.connect(self.update_progress) self.reduce.result.connect(self.get_mask) self.reduce.stop.connect(self.stop) self.thread.started.connect(self.reduce.nxprepare) self.thread.start() def get_mask(self, mask): self.mask = mask self.status_message.setText("Mask complete") self.status_message.setVisible(True) self.plot_button.setVisible(True) def plot_mask(self): self.plotview = NXPlotView('3D Mask') self.plotview.plot( NXdata(self.mask, self.reduce.data.nxaxes, title=f"3D Mask: {self.reduce.name}")) def stop(self): self.stop_progress() if self.thread and self.thread.isRunning(): self.reduce.stopped = True self.stop_thread() def accept(self): try: if self.mask is None: raise NeXusError("No mask has been created") elif self.entry.nxfilemode == 'r': raise NeXusError("NeXus file opened as readonly") self.reduce.write_mask(self.mask) self.reduce.record('nxprepare', masked_file=self.reduce.mask_file, threshold1=self.threshold1, horizontal1=self.horizontal1, threshold2=self.threshold2, horizontal2=self.horizontal2, process='nxprepare_mask') self.reduce.record_end('nxprepare') super().accept() except Exception as error: report_error("Preparing Mask", error) def reject(self): self.stop() super().reject()
class Mask3DDialog(BaseDialog): def __init__(self, parent=None): super(Mask3DDialog, self).__init__(parent) self.select_entry(self.choose_entry) self.parameters = GridParameters() self.parameters.add('radius', 200, 'Radius') self.parameters.add('width', 3, 'Frame Width') self.set_layout(self.entry_layout, self.parameters.grid(), self.action_buttons(('Calculate 3D Mask', self.calculate_mask)), self.progress_layout(save=True)) self.progress_bar.setVisible(False) self.progress_bar.setValue(0) self.set_title('Calculate 3D Mask') self.reduce = None def choose_entry(self): self.reduce = NXReduce(self.entry) @property def radius(self): return self.parameters['radius'].value @property def width(self): return self.parameters['width'].value def calculate_mask(self): self.check_lock(self.reduce.wrapper_file) self.thread = QtCore.QThread() self.reduce = NXReduce(self.entry, radius=self.radius, width=self.width, mask=True, overwrite=True, gui=True) self.reduce.moveToThread(self.thread) self.reduce.start.connect(self.start_progress) self.reduce.update.connect(self.update_progress) self.reduce.result.connect(self.calculate_mask) self.reduce.stop.connect(self.stop) self.thread.started.connect(self.reduce.nxfind) self.thread.start(QtCore.QThread.LowestPriority) def check_lock(self, file_name): try: with Lock(file_name, timeout=2): pass except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(file_name).release() def calculate_mask(self, mask): self.mask = mask def stop(self): self.stop_progress() if self.thread and self.thread.isRunning(): self.reduce.stopped = True self.thread.exit() def accept(self): try: with Lock(self.reduce.wrapper_file): self.reduce.write_peaks(self.peaks) except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(self.reduce.wrapper_file).release() if self.thread: self.stop() super(Mask3DDialog, self).accept() def reject(self): if self.thread: self.stop() super(Mask3DDialog, self).reject()
class FindDialog(BaseDialog): def __init__(self, parent=None): super(FindDialog, self).__init__(parent) self.select_entry(self.choose_entry) self.parameters = GridParameters() self.parameters.add('threshold', '', 'Threshold') self.parameters.add('first', '', 'First Frame') self.parameters.add('last', '', 'Last Frame') find_layout = QtWidgets.QHBoxLayout() self.find_button = QtWidgets.QPushButton('Find Peaks') self.find_button.clicked.connect(self.find_peaks) self.peak_count = QtWidgets.QLabel() self.peak_count.setVisible(False) find_layout.addStretch() find_layout.addWidget(self.find_button) find_layout.addWidget(self.peak_count) find_layout.addStretch() self.set_layout(self.entry_layout, self.parameters.grid(), find_layout, self.progress_layout(save=True)) self.progress_bar.setVisible(False) self.progress_bar.setValue(0) self.set_title('Find Peaks') self.reduce = None def choose_entry(self): self.reduce = NXReduce(self.entry) if self.reduce.first: self.parameters['first'].value = self.reduce.first if self.reduce.last: self.parameters['last'].value = self.reduce.last else: try: self.parameters['last'].value = len(self.entry.data.nxaxes[0]) except Exception: pass if self.reduce.threshold: self.parameters['threshold'].value = self.reduce.threshold @property def threshold(self): try: _threshold = np.int32(self.parameters['threshold'].value) if _threshold > 0.0: return _threshold else: return None except Exception: return None @property def first(self): try: _first = np.int32(self.parameters['first'].value) if _first >= 0: return _first else: return None except Exception as error: return None @property def last(self): try: _last = np.int32(self.parameters['last'].value) if _last > 0: return _last else: return None except Exception as error: return None def find_peaks(self): self.check_lock(self.reduce.data_file) self.start_thread() self.reduce = NXReduce(self.entry, threshold=self.threshold, first=self.first, last=self.last, find=True, overwrite=True, gui=True) self.reduce.moveToThread(self.thread) self.reduce.start.connect(self.start_progress) self.reduce.update.connect(self.update_progress) self.reduce.result.connect(self.get_peaks) self.reduce.stop.connect(self.stop) self.thread.started.connect(self.reduce.nxfind) self.thread.start(QtCore.QThread.LowestPriority) def check_lock(self, file_name): try: with Lock(file_name, timeout=2): pass except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(file_name).release() def get_peaks(self, peaks): self.peaks = peaks self.peak_count.setText('%s peaks found' % len(self.peaks)) self.peak_count.setVisible(True) def stop(self): self.stop_progress() if self.thread and self.thread.isRunning(): self.reduce.stopped = True self.stop_thread() def accept(self): try: with Lock(self.reduce.wrapper_file): self.reduce.write_peaks(self.peaks) except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(self.reduce.wrapper_file).release() self.stop() super(FindDialog, self).accept() def reject(self): self.stop() super(FindDialog, self).reject()
class MaximumDialog(NXDialog): def __init__(self, parent=None): super().__init__(parent) self.select_entry(self.choose_entry) self.parameters = GridParameters() self.parameters.add('first', '', 'First Frame') self.parameters.add('last', '', 'Last Frame') self.output = NXLabel('Maximum Value:') self.set_layout( self.entry_layout, self.output, self.parameters.grid(), self.action_buttons(('Find Maximum', self.find_maximum)), self.progress_layout(save=True)) self.progress_bar.setVisible(False) self.progress_bar.setValue(0) self.set_title('Find Maximum Value') self.reduce = None def choose_entry(self): self.reduce = NXReduce(self.entry) self.maximum = self.reduce.maximum if self.reduce.first: self.parameters['first'].value = self.reduce.first if self.reduce.last: self.parameters['last'].value = self.reduce.last @property def first(self): try: _first = np.int32(self.parameters['first'].value) if _first >= 0: return _first else: return None except Exception as error: return None @property def last(self): try: _last = np.int32(self.parameters['last'].value) if _last > 0: return _last else: return None except Exception as error: return None @property def maximum(self): return np.float(self.output.text().split()[-1]) @maximum.setter def maximum(self, value): self.output.setText(f'Maximum Value: {value}') def find_maximum(self): if is_file_locked(self.reduce.data_file): return self.start_thread() self.reduce = NXReduce(self.entry, first=self.first, last=self.last, maxcount=True, overwrite=True, gui=True) self.reduce.moveToThread(self.thread) self.reduce.start.connect(self.start_progress) self.reduce.update.connect(self.update_progress) self.reduce.result.connect(self.get_maximum) self.reduce.stop.connect(self.stop) self.thread.started.connect(self.reduce.nxmax) self.thread.finished.connect(self.stop) self.thread.start(QtCore.QThread.LowestPriority) def get_maximum(self, maximum): self.maximum = maximum def stop(self): self.stop_progress() if self.thread and self.thread.isRunning(): self.reduce.stopped = True self.stop_thread() def accept(self): try: self.reduce.write_maximum(self.maximum) self.reduce.record('nxmax', maximum=self.maximum, first_frame=self.first, last_frame=self.last) self.reduce.record_end('nxmax') self.stop() super().accept() except Exception as error: report_error("Finding Maximum", error) def reject(self): self.stop() super().reject()
class Mask3DDialog(BaseDialog): def __init__(self, parent=None): super(Mask3DDialog, self).__init__(parent) self.select_entry(self.choose_entry) self.parameters = GridParameters() self.parameters.add('radius', 200, 'Radius') self.parameters.add('width', 3, 'Frame Width') self.set_layout( self.entry_layout, self.parameters.grid(), self.action_buttons(('Calculate 3D Mask', self.calculate_mask)), self.progress_layout(save=True)) self.progress_bar.setVisible(False) self.progress_bar.setValue(0) self.set_title('Calculate 3D Mask') self.reduce = None def choose_entry(self): self.reduce = NXReduce(self.entry) @property def radius(self): return self.parameters['radius'].value @property def width(self): return self.parameters['width'].value def calculate_mask(self): self.check_lock(self.reduce.wrapper_file) self.thread = QtCore.QThread() self.reduce = NXReduce(self.entry, radius=self.radius, width=self.width, mask=True, overwrite=True, gui=True) self.reduce.moveToThread(self.thread) self.reduce.start.connect(self.start_progress) self.reduce.update.connect(self.update_progress) self.reduce.result.connect(self.calculate_mask) self.reduce.stop.connect(self.stop) self.thread.started.connect(self.reduce.nxfind) self.thread.start(QtCore.QThread.LowestPriority) def check_lock(self, file_name): try: with Lock(file_name, timeout=2): pass except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(file_name).release() def calculate_mask(self, mask): self.mask = mask def stop(self): self.stop_progress() if self.thread and self.thread.isRunning(): self.reduce.stopped = True self.thread.exit() def accept(self): try: with Lock(self.reduce.wrapper_file): self.reduce.write_peaks(self.peaks) except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(self.reduce.wrapper_file).release() if self.thread: self.stop() super(Mask3DDialog, self).accept() def reject(self): if self.thread: self.stop() super(Mask3DDialog, self).reject()
class MaximumDialog(BaseDialog): def __init__(self, parent=None): super(MaximumDialog, self).__init__(parent) self.select_entry(self.choose_entry) self.parameters = GridParameters() self.parameters.add('first', '', 'First Frame') self.parameters.add('last', '', 'Last Frame') self.output = QtWidgets.QLabel('Maximum Value:') self.set_layout(self.entry_layout, self.output, self.parameters.grid(), self.action_buttons(('Find Maximum', self.find_maximum)), self.progress_layout(save=True)) self.progress_bar.setVisible(False) self.progress_bar.setValue(0) self.set_title('Find Maximum Value') self.reduce = None def choose_entry(self): self.reduce = NXReduce(self.entry) self.maximum = self.reduce.maximum if self.reduce.first: self.parameters['first'].value = self.reduce.first if self.reduce.last: self.parameters['last'].value = self.reduce.last @property def first(self): try: _first = np.int32(self.parameters['first'].value) if _first >= 0: return _first else: return None except Exception as error: return None @property def last(self): try: _last = np.int32(self.parameters['last'].value) if _last > 0: return _last else: return None except Exception as error: return None @property def maximum(self): return np.float(self.output.text().split()[-1]) @maximum.setter def maximum(self, value): self.output.setText('Maximum Value: %s' % value) def find_maximum(self): self.check_lock(self.reduce.data_file) self.start_thread() self.reduce = NXReduce(self.entry, first=self.first, last=self.last, maxcount=True, overwrite=True, gui=True) self.reduce.moveToThread(self.thread) self.reduce.start.connect(self.start_progress) self.reduce.update.connect(self.update_progress) self.reduce.result.connect(self.get_maximum) self.reduce.stop.connect(self.stop) self.thread.started.connect(self.reduce.nxmax) self.thread.finished.connect(self.stop) self.thread.start(QtCore.QThread.LowestPriority) def check_lock(self, file_name): try: with Lock(file_name, timeout=2): pass except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(file_name).release() def get_maximum(self, maximum): self.maximum = maximum def stop(self): self.stop_progress() if self.thread and self.thread.isRunning(): self.reduce.stopped = True self.stop_thread() def accept(self): try: with Lock(self.reduce.wrapper_file): self.reduce.write_maximum(self.maximum) except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(self.reduce.wrapper_file).release() self.stop() super(MaximumDialog, self).accept() def reject(self): self.stop() super(MaximumDialog, self).reject()
class MaximumDialog(BaseDialog): def __init__(self, parent=None): super(MaximumDialog, self).__init__(parent) self.select_entry(self.choose_entry) self.parameters = GridParameters() self.parameters.add('first', '', 'First Frame') self.parameters.add('last', '', 'Last Frame') self.output = QtWidgets.QLabel('Maximum Value:') self.set_layout( self.entry_layout, self.output, self.parameters.grid(), self.action_buttons(('Find Maximum', self.find_maximum)), self.progress_layout(save=True)) self.progress_bar.setVisible(False) self.progress_bar.setValue(0) self.set_title('Find Maximum Value') self.reduce = None def choose_entry(self): self.reduce = NXReduce(self.entry) self.maximum = self.reduce.maximum if self.reduce.first: self.parameters['first'].value = self.reduce.first if self.reduce.last: self.parameters['last'].value = self.reduce.last @property def first(self): try: _first = np.int32(self.parameters['first'].value) if _first >= 0: return _first else: return None except Exception as error: return None @property def last(self): try: _last = np.int32(self.parameters['last'].value) if _last > 0: return _last else: return None except Exception as error: return None @property def maximum(self): return np.float(self.output.text().split()[-1]) @maximum.setter def maximum(self, value): self.output.setText('Maximum Value: %s' % value) def find_maximum(self): self.check_lock(self.reduce.data_file) self.start_thread() self.reduce = NXReduce(self.entry, first=self.first, last=self.last, maxcount=True, overwrite=True, gui=True) self.reduce.moveToThread(self.thread) self.reduce.start.connect(self.start_progress) self.reduce.update.connect(self.update_progress) self.reduce.result.connect(self.get_maximum) self.reduce.stop.connect(self.stop) self.thread.started.connect(self.reduce.nxmax) self.thread.finished.connect(self.stop) self.thread.start(QtCore.QThread.LowestPriority) def check_lock(self, file_name): try: with Lock(file_name, timeout=2): pass except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(file_name).release() def get_maximum(self, maximum): self.maximum = maximum def stop(self): self.stop_progress() if self.thread and self.thread.isRunning(): self.reduce.stopped = True self.stop_thread() def accept(self): try: with Lock(self.reduce.wrapper_file): self.reduce.write_maximum(self.maximum) except LockException as error: if self.confirm_action('Clear lock?', str(error)): Lock(self.reduce.wrapper_file).release() self.stop() super(MaximumDialog, self).accept() def reject(self): self.stop() super(MaximumDialog, self).reject()