BUGFIX: VFT;
change to src layout
This commit is contained in:
		
							
								
								
									
										0
									
								
								src/gui_qt/io/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/gui_qt/io/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										187
									
								
								src/gui_qt/io/asciireader.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/gui_qt/io/asciireader.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | ||||
| from nmreval.io.asciireader import AsciiReader | ||||
|  | ||||
| from ..Qt import QtGui, QtCore, QtWidgets | ||||
| from .._py.asciidialog import Ui_ascii_reader | ||||
|  | ||||
|  | ||||
| class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader): | ||||
|     data_read = QtCore.pyqtSignal(list) | ||||
|     file_ext = ['.dat', '.txt'] | ||||
|     skip = False | ||||
|  | ||||
|     def __init__(self, fname=None, parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|         self.setupUi(self) | ||||
|  | ||||
|         self.reader = AsciiReader(fname) | ||||
|  | ||||
|         pal = QtWidgets.QApplication.instance().palette() | ||||
|         rgb = pal.color(pal.Base).getRgb()[:3] | ||||
|         rgb2 = pal.color(pal.Text).getRgb()[:3] | ||||
|         self.plainTextEdit_2.setStyleSheet(f'QPlainTextEdit {{ background-color: rgb{rgb} ; color: rgb{rgb2}; }}') | ||||
|  | ||||
|         self.ascii_table.horizontalHeader().setStretchLastSection(True) | ||||
|         self.buttonbox.button(QtWidgets.QDialogButtonBox.Apply).clicked.connect(self.apply) | ||||
|         self.buttonbox.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(self.accept) | ||||
|  | ||||
|         self.changestaggeredrange(0) | ||||
|  | ||||
|         self.ascii_table.contextMenuEvent = self.ctx_table | ||||
|         self.ascii_table.horizontalHeader().setContextMenuPolicy(QtCore.Qt.CustomContextMenu) | ||||
|         self.ascii_table.horizontalHeader().customContextMenuRequested.connect(self.ctx_table) | ||||
|  | ||||
|     def __call__(self, fname, *args, **kwargs): | ||||
|  | ||||
|         for i in [self.stag_lineEdit, self.start_lineedit, self.end_lineedit, | ||||
|                   self.plainTextEdit_2, self.ascii_table, self.delay_lineedit]: | ||||
|             i.clear() | ||||
|         self.checkBox_2.setChecked(False) | ||||
|         self.checkBox.setChecked(False) | ||||
|         self.plainTextEdit_2.show() | ||||
|  | ||||
|         self.reader = AsciiReader(fname) | ||||
|         self.set_gui() | ||||
|  | ||||
|         if QAsciiReader.skip: | ||||
|             self.accept() | ||||
|         else: | ||||
|             self.skippy_checkbox.blockSignals(True) | ||||
|             self.skippy_checkbox.setCheckState(QtCore.Qt.Unchecked) | ||||
|             self.skippy_checkbox.blockSignals(False) | ||||
|  | ||||
|             return self | ||||
|  | ||||
|     def set_gui(self): | ||||
|         for text in self.reader.header: | ||||
|             self.plainTextEdit_2.appendPlainText(text) | ||||
|  | ||||
|         self.ascii_table.setRowCount(self.reader.shape[0]) | ||||
|         self.ascii_table.setColumnCount(self.reader.shape[1]) | ||||
|         try: | ||||
|             last_header_line = self.reader.header[-1].split() | ||||
|             if len(last_header_line) == self.reader.shape[1]: | ||||
|                 self.ascii_table.setHorizontalHeaderLabels(last_header_line) | ||||
|         except IndexError: | ||||
|             self.plainTextEdit_2.hide() | ||||
|  | ||||
|         for i, line in enumerate(self.reader.data): | ||||
|             for j, field in enumerate(line): | ||||
|                 it = QtWidgets.QTableWidgetItem(field) | ||||
|                 self.ascii_table.setItem(i, j, it) | ||||
|  | ||||
|         self.ascii_table.resizeColumnsToContents() | ||||
|  | ||||
|         if self.reader.delays is not None: | ||||
|             set_string = ''.join(str(d) + '\n' for d in self.reader.delays) | ||||
|             self.plainTextEdit.setPlainText(set_string) | ||||
|             self.delay_lineedit.setText(str(len(self.reader.delays))) | ||||
|  | ||||
|     def ctx_table(self, _): | ||||
|         menu = QtWidgets.QMenu(self) | ||||
|         x_action = QtWidgets.QAction('Set as x', self) | ||||
|         x_action.triggered.connect(lambda: self.set_columns('x')) | ||||
|         y_action = QtWidgets.QAction('Set as y', self) | ||||
|         y_action.triggered.connect(lambda: self.set_columns('y')) | ||||
|         menu.addActions([x_action, y_action]) | ||||
|         if self.label_5.isVisible(): | ||||
|             yerr_action = QtWidgets.QAction('Set as \u0394y', self) | ||||
|             yerr_action.triggered.connect(lambda: self.set_columns('yerr')) | ||||
|             menu.addAction(yerr_action) | ||||
|         menu.popup(QtGui.QCursor.pos()) | ||||
|  | ||||
|     def set_columns(self, mode): | ||||
|         cols = ' '.join([str(s.column()+1) for s in self.ascii_table.selectionModel().selectedColumns()]) | ||||
|         try: | ||||
|             lineedit = {'x': self.x_lineedit, 'y': self.y_lineedit, 'yerr': self.lineEdit}[mode] | ||||
|             lineedit.setText(cols) | ||||
|         except KeyError: | ||||
|             pass | ||||
|  | ||||
|     @QtCore.pyqtSlot(int, name='on_checkBox_2_stateChanged') | ||||
|     def changestaggeredrange(self, evt): | ||||
|         if evt == 2: | ||||
|             self.stag_lineEdit.show() | ||||
|             self.stag_lineEdit.setEnabled(True) | ||||
|         else: | ||||
|             self.stag_lineEdit.hide() | ||||
|             self.stag_lineEdit.setDisabled(True) | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_pushButton_clicked') | ||||
|     def calc_delays(self): | ||||
|         self.reader.calc_delays(float(self.start_lineedit.text()), float(self.end_lineedit.text()), | ||||
|                                 int(self.delay_lineedit.text()), log=self.checkBox.isChecked(), | ||||
|                                 stagg=self.checkBox_2.isChecked(), stag_size=int(self.stag_lineEdit.text())) | ||||
|  | ||||
|         set_string = ''.join(str(d) + '\n' for d in self.reader.delays) | ||||
|         self.plainTextEdit.setPlainText(set_string) | ||||
|  | ||||
|     def update_header(self, text, comment='#'): | ||||
|         text = text.replace(comment, '').lstrip().rstrip() | ||||
|         self.plainTextEdit_2.appendPlainText(text) | ||||
|  | ||||
|     @QtCore.pyqtSlot() | ||||
|     def on_plainTextEdit_textChanged(self): | ||||
|         new_delays = str(self.plainTextEdit.toPlainText()).rstrip('\n').split('\n') | ||||
|         self.delay_lineedit.setText(str(len(new_delays))) | ||||
|         if new_delays[0] == '': | ||||
|             new_delays = None | ||||
|         else: | ||||
|             for k, v in enumerate(new_delays): | ||||
|                 try: | ||||
|                     new_delays[k] = float(v) | ||||
|                 except ValueError: | ||||
|                     new_delays[k] = -1 | ||||
|         self.reader.delays = new_delays | ||||
|  | ||||
|     @QtCore.pyqtSlot() | ||||
|     def accept(self): | ||||
|         if self.apply(): | ||||
|             self.close() | ||||
|  | ||||
|     def apply(self): | ||||
|         # default row for x is the first row, it will be superseded if an integer number is given. | ||||
|  | ||||
|         try: | ||||
|             x = [int(self.x_lineedit.text())-1] | ||||
|         except ValueError: | ||||
|             x = None | ||||
|         try: | ||||
|             y = [int(t)-1 for t in str(self.y_lineedit.text()).split(' ')] | ||||
|         except ValueError: | ||||
|             y = None | ||||
|         try: | ||||
|             y_err = [int(t)-1 for t in str(self.lineEdit.text()).split(' ')] | ||||
|         except ValueError: | ||||
|             y_err = None | ||||
|  | ||||
|         ret_dic = self.reader.export(xidx=x, yidx=y, yerridx=y_err, | ||||
|                                      mode=self.buttonGroup.checkedButton().text()) | ||||
|  | ||||
|         self.data_read.emit(ret_dic) | ||||
|  | ||||
|         return True | ||||
|  | ||||
|     @staticmethod | ||||
|     def _update_dic(key, value, old_dic): | ||||
|         old_dic_keys = list(old_dic.keys()) | ||||
|         if key in old_dic_keys: | ||||
|             counter = 0 | ||||
|             replace_key = key + str(counter) | ||||
|             while replace_key in old_dic_keys: | ||||
|                 counter += 1 | ||||
|                 replace_key = key + str(counter) | ||||
|         else: | ||||
|             replace_key = key | ||||
|         old_dic[replace_key] = value | ||||
|  | ||||
|     @QtCore.pyqtSlot(int, name='on_buttonGroup_buttonClicked') | ||||
|     def show_error(self, val): | ||||
|         if val == -2: | ||||
|             self.widget.show() | ||||
|         else: | ||||
|             self.lineEdit.setText('') | ||||
|             self.widget.hide() | ||||
|  | ||||
|     @QtCore.pyqtSlot(int, name='on_skippy_checkbox_stateChanged') | ||||
|     def skip_next_dial(self, _): | ||||
|         QAsciiReader.skip = self.skippy_checkbox.isChecked() | ||||
							
								
								
									
										77
									
								
								src/gui_qt/io/bdsreader.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/gui_qt/io/bdsreader.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| from nmreval.io.bds_reader import BDSReader | ||||
| from ..Qt import QtCore, QtWidgets | ||||
| from .._py.bdsdialog import Ui_Dialog | ||||
|  | ||||
|  | ||||
| class QBDSReader(QtWidgets.QDialog, Ui_Dialog): | ||||
|     data_read = QtCore.pyqtSignal(list) | ||||
|     file_ext = ['.eps'] | ||||
|  | ||||
|     def __init__(self, fname: str = None, parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|         self.setupUi(self) | ||||
|         self.reader = None | ||||
|         self.fname = fname | ||||
|  | ||||
|         if self.fname is not None: | ||||
|             self.reader = BDSReader(fname) | ||||
|             self.setup_gui() | ||||
|  | ||||
|     def __call__(self, fname: str): | ||||
|         self.reader = BDSReader(fname) | ||||
|         self.fname = fname | ||||
|         self.setup_gui() | ||||
|  | ||||
|         return self | ||||
|  | ||||
|     def setup_gui(self): | ||||
|         self.listWidget.clear() | ||||
|         self.label.setText(f'Found entries for {self.reader.fname.name}') | ||||
|  | ||||
|         self.make_list(True) | ||||
|  | ||||
|     @QtCore.pyqtSlot(QtWidgets.QAbstractButton, name='on_buttonGroup_buttonClicked') | ||||
|     def change_list(self, bttn: QtWidgets.QAbstractButton): | ||||
|         self.make_list(bttn == self.freq_button) | ||||
|  | ||||
|     def make_list(self, use_freq: bool) -> None: | ||||
|         self.listWidget.clear() | ||||
|         if use_freq: | ||||
|             secondary = self.reader.set_temp | ||||
|         else: | ||||
|             secondary = self.reader.frequencies | ||||
|  | ||||
|         for x2 in secondary: | ||||
|             item = QtWidgets.QListWidgetItem(f'{x2:.8g}') | ||||
|             item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsSelectable) | ||||
|             item.setCheckState(QtCore.Qt.Checked) | ||||
|             self.listWidget.addItem(item) | ||||
|  | ||||
|     def accept(self): | ||||
|         data = [] | ||||
|  | ||||
|         x2 = [] | ||||
|         for i in range(self.listWidget.count()): | ||||
|             item = self.listWidget.item(i) | ||||
|             if item.checkState() == QtCore.Qt.Checked: | ||||
|                 x2.append(i) | ||||
|  | ||||
|         xmode = 'freq' if self.freq_button.isChecked() else 'temp' | ||||
|  | ||||
|         for (mode, cb) in [ | ||||
|             ('epsilon', self.eps_checkBox), | ||||
|             ('sigma', self.cond_checkBox), | ||||
|             ('modulus', self.modul_checkBox), | ||||
|             ('capacity', self.cap_checkBox), | ||||
|             ('time', self.time_checkBox), | ||||
|             ('sample_temp', self.temp_checkBox), | ||||
|             ('loss_factor', self.loss_checkBox) | ||||
|         ]: | ||||
|             if cb.checkState() == QtCore.Qt.Checked: | ||||
|                 values = self.reader.export(ymode=mode, xmode=xmode) | ||||
|                 for t in x2: | ||||
|                     data.append(values[t]) | ||||
|  | ||||
|         self.data_read.emit(data) | ||||
|  | ||||
|         super().accept() | ||||
							
								
								
									
										267
									
								
								src/gui_qt/io/dscreader.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								src/gui_qt/io/dscreader.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,267 @@ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from pathlib import Path | ||||
|  | ||||
| import numpy as np | ||||
| from pyqtgraph import PlotDataItem | ||||
|  | ||||
| from nmreval.data.points import Points | ||||
| from nmreval.io.dsc import Cyclohexane, DSCCalibrator, DSCSample | ||||
|  | ||||
| from ..Qt import QtWidgets, QtCore | ||||
| from .._py.dscfile_dialog import Ui_Dialog | ||||
|  | ||||
|  | ||||
| class QDSCReader(QtWidgets.QDialog, Ui_Dialog): | ||||
|     data_read = QtCore.pyqtSignal(list) | ||||
|     file_ext = ['.txt', '.dsc'] | ||||
|  | ||||
|     def __init__(self, sample=None, empty=None, reference=None, parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|         self.setupUi(self) | ||||
|  | ||||
|         self.calibrator = DSCCalibrator() | ||||
|         self.current_run = (-1, 'h') | ||||
|         self.sample_idx = None | ||||
|         self.fname = None | ||||
|  | ||||
|         self.raw_graph.setLabel('bottom', text='T', units='K') | ||||
|         self.raw_graph.setTitle('Raw data') | ||||
|         self.raw_graph.addLegend() | ||||
|         self.raw_sample = PlotDataItem(x=[], y=[], name='Sample') | ||||
|         self.empty_sample = PlotDataItem(x=[], y=[], pen={'dash': (5, 5)}, name='Empty') | ||||
|         self.raw_graph.addItem(self.raw_sample) | ||||
|         self.raw_graph.addItem(self.empty_sample) | ||||
|  | ||||
|         self.end_graph.setTitle('End result') | ||||
|         self.end_graph.setLabel('bottom', text='T', units='K') | ||||
|         self.baseline_sample = PlotDataItem(x=[], y=[]) | ||||
|         self.end_graph.addItem(self.baseline_sample) | ||||
|  | ||||
|         self.baseline_graph.setTitle('Time dependence') | ||||
|         self.baseline_graph.setLabel('bottom', text='t', units='min') | ||||
|         self.drift_sample = PlotDataItem(x=[], y=[]) | ||||
|         self.slope_graph = PlotDataItem(x=[], y=[], pen={'color': 'r', 'dash': (5, 5)}) | ||||
|         self.baseline_graph.addItem(self.drift_sample) | ||||
|         self.baseline_graph.addItem(self.slope_graph) | ||||
|  | ||||
|         self.calib_graph.setTitle('Calibration') | ||||
|         self.calib_graph.setLabel('bottom', text='T', units='K') | ||||
|         self.ref_plotitems = [] | ||||
|  | ||||
|         self.sample = None | ||||
|         if sample is not None: | ||||
|             self.add_sample(sample) | ||||
|  | ||||
|         self.empty = None | ||||
|         if empty is not None: | ||||
|             self.add_empty(empty=empty) | ||||
|  | ||||
|         self.references = [] | ||||
|         if reference is not None: | ||||
|             if isinstance(reference, (str, Path, DSCSample)): | ||||
|                 reference = [reference] | ||||
|                 for r in reference: | ||||
|                     self.add_reference(ref=r) | ||||
|  | ||||
|     def __call__(self, fname: Path | str): | ||||
|         self.clear_plots() | ||||
|         self.add_sample(fname) | ||||
|  | ||||
|         return self | ||||
|  | ||||
|     def add_sample(self, fname: Path | str): | ||||
|         self.sample = self.calibrator.set_measurement(fname, mode='sample') | ||||
|         self.fname = self.sample.fname | ||||
|  | ||||
|         self.step_listWidget.clear() | ||||
|  | ||||
|         for opts in self.sample.steps: | ||||
|             item = QtWidgets.QListWidgetItem() | ||||
|             item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable) | ||||
|             item.setCheckState(QtCore.Qt.Unchecked) | ||||
|  | ||||
|             if opts[0] == 'i': | ||||
|                 item.setFlags(QtCore.Qt.NoItemFlags) | ||||
|                 item.setText(f'{opts[1]:.2f} K for {opts[1] / 60:.0f} min') | ||||
|             else: | ||||
|                 item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable) | ||||
|                 item.setText(f'{opts[2]:.2f} K to {opts[3]:.2f} K with {opts[1]} K/min') | ||||
|  | ||||
|             self.step_listWidget.addItem(item) | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_loadempty_button_clicked') | ||||
|     def add_empty(self, empty=None): | ||||
|         if empty is None: | ||||
|             empty, _ = QtWidgets.QFileDialog.getOpenFileName(directory=str(self.fname.parent)) | ||||
|  | ||||
|         if empty: | ||||
|             self.empty = self.calibrator.set_measurement(empty, mode='empty') | ||||
|             self.empty_label.setText(str(self.empty.fname.name)) | ||||
|  | ||||
|             self.update_plots() | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_delempty_button_clicked') | ||||
|     def remove_empty(self): | ||||
|         self.empty_label.setText('No empty measurement') | ||||
|         self.calibrator.empty = None | ||||
|  | ||||
|         self.update_plots() | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_ref_add_pushButton_clicked') | ||||
|     def add_reference(self, ref: str | Path = None): | ||||
|         if ref is None: | ||||
|             ref, _ = QtWidgets.QFileDialog.getOpenFileName(directory=str(self.fname.parent)) | ||||
|  | ||||
|         if ref: | ||||
|             ref = self.calibrator.set_measurement(ref, mode='reference') | ||||
|  | ||||
|             self.references.append(ref) | ||||
|             item = QtWidgets.QTableWidgetItem(str(ref.fname.name)) | ||||
|             item.setData(QtCore.Qt.UserRole, ref.fname) | ||||
|             item.setFlags(QtCore.Qt.ItemIsEnabled) | ||||
|  | ||||
|             rowcnt = self.reference_tableWidget.rowCount() | ||||
|             self.reference_tableWidget.setRowCount(rowcnt+1) | ||||
|             self.reference_tableWidget.setItem(rowcnt, 0, item) | ||||
|             self.reference_tableWidget.setCellWidget(rowcnt, 1, ReferenceComboBox()) | ||||
|             self.reference_tableWidget.resizeColumnsToContents() | ||||
|  | ||||
|         self.update_plots() | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_ref_remove_pushButton_clicked') | ||||
|     def remove_reference(self): | ||||
|         idx = self.reference_tableWidget.currentRow() | ||||
|         self.calibrator.remove_reference(self.reference_tableWidget.item(idx, 0).data(QtCore.Qt.UserRole)) | ||||
|  | ||||
|         self.reference_tableWidget.removeRow(idx) | ||||
|         self.update_plots() | ||||
|  | ||||
|     @QtCore.pyqtSlot(QtWidgets.QListWidgetItem, name='on_step_listWidget_itemChanged') | ||||
|     def select_run(self, item: QtWidgets.QListWidgetItem): | ||||
|  | ||||
|         idx = self.step_listWidget.indexFromItem(item).row() | ||||
|         self.step_listWidget.blockSignals(True) | ||||
|         for row in range(self.step_listWidget.count()): | ||||
|             if idx == row: | ||||
|                 continue | ||||
|             self.step_listWidget.item(row).setCheckState(QtCore.Qt.Unchecked) | ||||
|         self.step_listWidget.blockSignals(False) | ||||
|  | ||||
|         if item.checkState() == QtCore.Qt.Checked: | ||||
|             mode, rate, _, _ = self.sample.steps[idx] | ||||
|             self.current_run = (rate, mode) | ||||
|             self.sample_idx = idx | ||||
|             self.update_plots() | ||||
|         else: | ||||
|             self.current_run = (-1, 'h') | ||||
|             self.sample_idx = None | ||||
|             self.clear_plots() | ||||
|  | ||||
|     def get_data(self, ): | ||||
|         if self.sample_idx is None: | ||||
|             return | ||||
|  | ||||
|         rate = self.current_run[0] | ||||
|         slope_type = {self.none_radioButton: None, | ||||
|                       self.isotherm_radioButton: 'iso', | ||||
|                       self.slope_radioButton: 'curve'}[self.buttonGroup.checkedButton()] | ||||
|  | ||||
|         try: | ||||
|             raw_sample, drift_value, sample_data, empty_data, slope = self.calibrator.get_data(self.sample_idx, | ||||
|                                                                                                slope=slope_type) | ||||
|         except ValueError as e: | ||||
|             _msg = QtWidgets.QMessageBox.warning(self, 'No rate found', e.args[0]) | ||||
|             return | ||||
|  | ||||
|         self.calibrator.ref_list = [] | ||||
|         for row in range(self.reference_tableWidget.rowCount()): | ||||
|             self.calibrator.ref_list.append(self.reference_tableWidget.cellWidget(row, 1).get_reference()) | ||||
|  | ||||
|         calib_x, calib_y, regions = self.calibrator.get_calibration(rate) | ||||
|  | ||||
|         drift_value[0] /= 60. | ||||
|         slope[0] /= 60. | ||||
|  | ||||
|         if calib_x is not None: | ||||
|             sample_data[0] *= calib_x[0] | ||||
|             sample_data[0] += calib_x[1] | ||||
|  | ||||
|             if self.cp_checkBox.isChecked(): | ||||
|                 sample_data[1] *= calib_y | ||||
|  | ||||
|         return sample_data, raw_sample, empty_data, drift_value, slope, calib_x, calib_y, regions | ||||
|  | ||||
|     @QtCore.pyqtSlot(QtWidgets.QAbstractButton, name='on_buttonGroup_buttonClicked') | ||||
|     @QtCore.pyqtSlot(int, name='on_cp_checkBox_stateChanged') | ||||
|     def update_plots(self, _=None): | ||||
|         sample_data, raw_sample, empty_data, drift_value, slope, calib_x, calib_y, regions = self.get_data() | ||||
|  | ||||
|         self.raw_sample.setData(x=raw_sample[0], y=raw_sample[1]) | ||||
|         self.drift_sample.setData(x=drift_value[0], y=drift_value[1]) | ||||
|         self.slope_graph.setData(x=slope[0], y=slope[1]) | ||||
|  | ||||
|         if empty_data is not None: | ||||
|             self.empty_sample.setData(x=empty_data[0], y=empty_data[1]) | ||||
|  | ||||
|         self.calib_graph.clear() | ||||
|  | ||||
|         if calib_x is not None: | ||||
|             for ref_zoom, onset, grad_points in regions: | ||||
|                 ref_plot = PlotDataItem(x=ref_zoom[0], y=ref_zoom[1]) | ||||
|                 self.calib_graph.addItem(ref_plot) | ||||
|  | ||||
|                 self.calib_graph.addItem(PlotDataItem(x=grad_points[0], y=grad_points[1], | ||||
|                                                       symbol='x')) | ||||
|  | ||||
|                 view_limits = -np.max(ref_zoom[1])/10, np.max(ref_zoom[1]) * 1.1 | ||||
|                 cut_idx, = np.where((onset < view_limits[1]) & (onset > view_limits[0])) | ||||
|                 self.calib_graph.addItem(PlotDataItem(x=ref_zoom[0, cut_idx], y=onset[cut_idx], | ||||
|                                                       pen={'color': 'r', 'dash': (2, 5)})) | ||||
|                 self.calib_graph.addItem(PlotDataItem(x=[ref_zoom[0, 0], ref_zoom[0, -1]], y=[0, 0], | ||||
|                                                       pen={'color': 'r', 'dash': (2, 5)})) | ||||
|  | ||||
|         self.baseline_sample.setData(x=sample_data[0], y=sample_data[1]) | ||||
|  | ||||
|     def clear_plots(self): | ||||
|         for plot in [self.raw_sample, self.baseline_sample, self.empty_sample, self.drift_sample, self.slope_graph]: | ||||
|             plot.setData(x=[], y=[]) | ||||
|  | ||||
|         self.calib_graph.clear() | ||||
|  | ||||
|     def export_data(self, filesave=False, close_after=True): | ||||
|         try: | ||||
|             sample_data = self.get_data()[0] | ||||
|         except TypeError: | ||||
|             return | ||||
|  | ||||
|         rate, mode = self.current_run | ||||
|         new_val = Points(sample_data[0], sample_data[1], value=rate, name=f'{self.fname.stem} {rate} ({mode})') | ||||
|  | ||||
|         if filesave: | ||||
|             new_val.savetxt(self.fname.with_name(f'{self.fname.stem} {rate}K-min {mode}.dat'.replace(' ', '_'))) | ||||
|         else: | ||||
|             self.data_read.emit([new_val]) | ||||
|  | ||||
|         if close_after: | ||||
|             super().accept() | ||||
|  | ||||
|     @QtCore.pyqtSlot(QtWidgets.QAbstractButton, name='on_buttonBox_clicked') | ||||
|     def button_clicked(self, bttn: QtWidgets.QAbstractButton): | ||||
|         bttn_value = self.buttonBox.standardButton(bttn) | ||||
|         if bttn_value in (self.buttonBox.Ok, self.buttonBox.Apply, self.buttonBox.Save): | ||||
|             self.export_data(filesave=bttn_value==self.buttonBox.Save, close_after=bttn_value==self.buttonBox.Ok) | ||||
|         else: | ||||
|             super().close() | ||||
|  | ||||
|  | ||||
| class ReferenceComboBox(QtWidgets.QComboBox): | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|  | ||||
|         self.references = [Cyclohexane] | ||||
|         for ref in self.references: | ||||
|             self.addItem(ref.name) | ||||
|  | ||||
|     def get_reference(self): | ||||
|         return self.references[self.currentIndex()] | ||||
							
								
								
									
										114
									
								
								src/gui_qt/io/exporters.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/gui_qt/io/exporters.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from numpy import c_ | ||||
|  | ||||
| from nmreval.io.graceeditor import GraceEditor | ||||
| from nmreval.utils.text import convert | ||||
|  | ||||
| from ..Qt import QtGui, QtCore, QtPrintSupport | ||||
|  | ||||
|  | ||||
| class GraceExporter: | ||||
|     def __init__(self, kwargs: dict): | ||||
|         self.__agr = None | ||||
|         self.__opts = kwargs | ||||
|  | ||||
|     def export(self, outfile: str, mode: int | str = 'w'): | ||||
|         if mode == 'w': | ||||
|             self.__agr = GraceEditor() | ||||
|         else: | ||||
|             self.__agr = GraceEditor(outfile) | ||||
|  | ||||
|         if isinstance(mode, str): | ||||
|             new_g = self.__agr.new_graph() | ||||
|  | ||||
|             new_g.set_limits(x=self.__opts['limits'][0], y=self.__opts['limits'][1]) | ||||
|             new_g.set_log(x=self.__opts['log'][0], y=self.__opts['log'][1]) | ||||
|  | ||||
|             new_g.set_onoff('legend', self.__opts['legend']) | ||||
|             new_g.set_property(**{'title': f'"{convert(self.__opts["labels"][2], old="html", new="agr")}"', | ||||
|                                   'legend loctype': 'view', | ||||
|                                   'legend': ', '.join(str(i) for i in new_g.world_to_view(self.__opts['legend_pos']))}) | ||||
|  | ||||
|             for i, ax in enumerate('xy'): | ||||
|                 new_g.set_axis_property(ax, **{'label': f'"{convert(self.__opts["labels"][i], old="html", new="agr")}"', | ||||
|                                                'tick major': self.__opts['ticks'][i][0], | ||||
|                                                'tick minor ticks': self.__opts['ticks'][i][1],}) | ||||
|                 new_g.set_axis_onoff(ax, 'tick major grid', self.__opts['grid']) | ||||
|             g_idx = new_g.idx | ||||
|         else: | ||||
|             g_idx = mode | ||||
|  | ||||
|         colors = self.__agr.colors | ||||
|  | ||||
|         new_colors = [] | ||||
|         for plot_label, item in zip(self.__opts['in_legend'], self.__opts['items']): | ||||
|             new_s = self.__agr.new_set(g_idx) | ||||
|  | ||||
|             sc = item['symbolcolor'] | ||||
|             c_num = -1 | ||||
|             for i, (_, rgb) in colors.items(): | ||||
|                 if rgb == sc: | ||||
|                     c_num = i | ||||
|                     break | ||||
|  | ||||
|             if c_num == -1: | ||||
|                 c_num = max(colors.keys()) | ||||
|                 colors[c_num + 1] = (f'color{c_num + 1}', sc) | ||||
|                 new_colors.append((c_num + 1, f'color{c_num + 1}', sc)) | ||||
|  | ||||
|             new_s.set_symbol(**{'symbol': item['symbol'].value, 'size': item['symbolsize'] / 10., 'color': c_num, | ||||
|                                 'fill color': c_num, 'fill pattern': 1}) | ||||
|             new_s.set_onoff('errorbar', self.__opts['plots'][2]) | ||||
|  | ||||
|             lc = item['linecolor'] | ||||
|             c_num = -1 | ||||
|             for c_num, (_, rgb) in colors.items(): | ||||
|                 if rgb == lc: | ||||
|                     break | ||||
|  | ||||
|             if c_num == -1: | ||||
|                 c_num = max(colors.keys()) | ||||
|                 colors[c_num + 1] = () | ||||
|                 new_colors.append((c_num, f'color{c_num + 1}', sc)) | ||||
|  | ||||
|             new_s.set_line(**{'color': c_num, 'linewidth': item['linewidth'], | ||||
|                               'linestyle': item['linestyle'].to_agr()}) | ||||
|  | ||||
|             if plot_label: | ||||
|                 new_s.set_property(comment=f'"{item["name"]}"', | ||||
|                                    legend=f'"{convert(item["name"], old="tex", new="agr")}"') | ||||
|             else: | ||||
|                 new_s.set_property(comment=f'"{item["name"]}"') | ||||
|  | ||||
|             data = self.__agr.dataset(g_idx, new_s.idx) | ||||
|             if 'yerr' in item: | ||||
|                 data.type = 'xydy' | ||||
|                 data.data = c_[item['x'], item['y'], item['yerr']] | ||||
|                 new_s.set_property(**{'errorbar color': c_num}) | ||||
|             else: | ||||
|                 data.data = c_[item['x'], item['y']] | ||||
|  | ||||
|         for c in new_colors: | ||||
|             self.__agr.set_color(c[1], c[2], idx=c[0]) | ||||
|  | ||||
|         self.__agr.write(outfile) | ||||
|  | ||||
|  | ||||
| class PDFPrintExporter: | ||||
|     def __init__(self, graphview): | ||||
|         self.graphic = graphview | ||||
|  | ||||
|     def export(self, outfile): | ||||
|         printer = QtPrintSupport.QPrinter() | ||||
|  | ||||
|         printer.setOutputFormat(printer.PdfFormat) | ||||
|         printer.setOutputFileName(outfile) | ||||
|  | ||||
|         printer.setPaperSize(QtCore.QSizeF(self.graphic.width(), self.graphic.height()), | ||||
|                              printer.DevicePixel) | ||||
|         printer.setPageMargins(0, 0, 0, 0, printer.DevicePixel) | ||||
|  | ||||
|         painter = QtGui.QPainter(printer) | ||||
|         self.graphic.render(painter) | ||||
|         painter.end() | ||||
							
								
								
									
										107
									
								
								src/gui_qt/io/fcbatchreader.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/gui_qt/io/fcbatchreader.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| import pathlib | ||||
|  | ||||
| from nmreval.io.fcbatchreader import FCReader | ||||
|  | ||||
| from ..lib.utils import busy_cursor | ||||
| from ..Qt import QtCore, QtWidgets, QtGui | ||||
| from .._py.fcreader import Ui_FCEval_dialog | ||||
|  | ||||
|  | ||||
| class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog): | ||||
|     data_read = QtCore.pyqtSignal(list, str) | ||||
|  | ||||
|     def __init__(self, path=None, parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|         self.setupUi(self) | ||||
|         if path is None: | ||||
|             path = pathlib.Path().home() | ||||
|         self.path = path | ||||
|  | ||||
|         self.start_lineedit.setValidator(QtGui.QDoubleValidator()) | ||||
|         self.stop_lineedit.setValidator(QtGui.QDoubleValidator()) | ||||
|  | ||||
|         self.listWidget.installEventFilter(self) | ||||
|  | ||||
|     def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent) -> bool: | ||||
|         # intercept key press in listwidget to allow deletion with Del | ||||
|         if evt.type() == QtCore.QEvent.KeyPress: | ||||
|             if evt.key() == QtCore.Qt.Key_Delete: | ||||
|                 self.listWidget.takeItem(self.listWidget.currentRow()) | ||||
|                 return True | ||||
|  | ||||
|         return super().eventFilter(src, evt) | ||||
|  | ||||
|     @QtCore.pyqtSlot(int, name='on_region_checkBox_stateChanged') | ||||
|     def use_region(self, state: int): | ||||
|         self.start_lineedit.setEnabled(state == QtCore.Qt.Checked) | ||||
|         self.stop_lineedit.setEnabled(state == QtCore.Qt.Checked) | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_file_pushbutton_clicked') | ||||
|     @QtCore.pyqtSlot(name='on_dir_pushbutton_clicked') | ||||
|     def get_input(self): | ||||
|         if self.sender() == self.file_pushbutton: | ||||
|             infiles, _ = QtWidgets.QFileDialog.getOpenFileNames(caption='Select HDF files', | ||||
|                                                                 directory=str(self.path), | ||||
|                                                                 filter='HDF files (*.h5)') | ||||
|             if infiles: | ||||
|                 self.listWidget.addItems(infiles) | ||||
|                 self.label.setText(str(pathlib.Path(infiles[-1]).parent)) | ||||
|         else: | ||||
|             infiles = QtWidgets.QFileDialog.getExistingDirectory(caption='Select input directory', | ||||
|                                                                  directory=str(self.path), | ||||
|                                                                  options=QtWidgets.QFileDialog.ShowDirsOnly) | ||||
|  | ||||
|             if infiles: | ||||
|                 self.listWidget.addItem(infiles) | ||||
|                 self.label.setText(str(pathlib.Path(infiles).parent)) | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_savebutton_clicked') | ||||
|     def save_path(self): | ||||
|         outfile = QtWidgets.QFileDialog.getExistingDirectory(self, caption='Select directory', | ||||
|                                                              directory=self.label.text(), | ||||
|                                                              options=QtWidgets.QFileDialog.ShowDirsOnly) | ||||
|         if outfile: | ||||
|             self.label.setText(outfile) | ||||
|  | ||||
|     def accept(self): | ||||
|         items = [self.listWidget.item(i).text() for i in range(self.listWidget.count())] | ||||
|         if items: | ||||
|             with busy_cursor(): | ||||
|                 self.read(items) | ||||
|  | ||||
|         self.close() | ||||
|  | ||||
|     def read(self, items): | ||||
|         region = (None, None) | ||||
|         if self.region_box.isChecked(): | ||||
|             start = None | ||||
|             if self.start_lineedit.text(): | ||||
|                 start = float(self.start_lineedit.text()) | ||||
|  | ||||
|             stop = None | ||||
|             if self.stop_lineedit.text(): | ||||
|                 stop = float(self.stop_lineedit.text()) | ||||
|             region = (start, stop) | ||||
|  | ||||
|         fc_eval = FCReader(items) | ||||
|         try: | ||||
|             fc_eval.load_magnetization(region=region, overwrite=self.overwrite_cb.isChecked()) | ||||
|         except OSError as e: | ||||
|             QtWidgets.QMessageBox.warning(self, 'Missing data', e.strerror) | ||||
|             return | ||||
|  | ||||
|         fc_eval.fit(kww=self.kww_checkbox.isChecked(), save_fits=True, save_fig=True) | ||||
|  | ||||
|         save_variables = [] | ||||
|         for name, cb in [('t1', self.t1_cb), ('beta', self.beta_cb), ('m0', self.m0_cb), ('off', self.off_cb)]: | ||||
|             if cb.isChecked(): | ||||
|                 save_variables.append(name) | ||||
|  | ||||
|         ret_vals = [] | ||||
|         ret_vals.extend(fc_eval.get_parameter(path=self.label.text(), kind='temp', parameter=save_variables)) | ||||
|  | ||||
|         grp = '' | ||||
|         if self.graph_checkbox.isChecked(): | ||||
|             grp = self.graph_comboBox.currentData(QtCore.Qt.UserRole) | ||||
|  | ||||
|         self.data_read.emit(ret_vals, grp) | ||||
							
								
								
									
										122
									
								
								src/gui_qt/io/filedialog.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								src/gui_qt/io/filedialog.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| from __future__ import annotations | ||||
|  | ||||
| import pathlib | ||||
|  | ||||
| from ..Qt import QtWidgets, QtCore | ||||
|  | ||||
|  | ||||
| class _FileDialog(QtWidgets.QFileDialog): | ||||
|     def __init__(self, directory=None, caption=None, filters='', parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|  | ||||
|         self.setOption(QtWidgets.QFileDialog.DontUseNativeDialog, True) | ||||
|  | ||||
|         self.setWindowTitle(caption) | ||||
|         self.setDirectory(str(directory)) | ||||
|         self.setNameFilters(filters.split(';;')) | ||||
|  | ||||
|         file_tree = self.findChild(QtWidgets.QTreeView, 'treeView') | ||||
|         file_tree.setSortingEnabled(True) | ||||
|         for i in range(file_tree.header().count()): | ||||
|             file_tree.header().setSectionResizeMode(i, 0) | ||||
|         file_tree.model().sort(0) | ||||
|  | ||||
|         file_list = self.findChild(QtWidgets.QListView, 'listView') | ||||
|         file_list.model().sort(0) | ||||
|  | ||||
|         line = QtWidgets.QFrame(self) | ||||
|         line.setFrameShape(line.HLine) | ||||
|         line.setFrameShadow(line.Sunken) | ||||
|         self.layout().addWidget(line, self.layout().rowCount(), 0, 1, self.layout().columnCount()) | ||||
|  | ||||
|  | ||||
| class OpenFileDialog(_FileDialog): | ||||
|     def __init__(self, directory=None, caption=None, filters='', parent=None): | ||||
|         super().__init__(directory=directory, caption=caption, filters=filters, parent=parent) | ||||
|  | ||||
|         self.setFileMode(QtWidgets.QFileDialog.ExistingFiles) | ||||
|  | ||||
|         self.checkBox = QtWidgets.QCheckBox(self) | ||||
|         self.checkBox.setChecked(False) | ||||
|         self.checkBox.setText('Use existing graph') | ||||
|         self.checkBox.stateChanged.connect(self.checkbox_state) | ||||
|         self.layout().addWidget(self.checkBox) | ||||
|  | ||||
|         self.comboBox = QtWidgets.QComboBox(self) | ||||
|         self.comboBox.setEnabled(False) | ||||
|         self.layout().addWidget(self.comboBox) | ||||
|  | ||||
|         self.add_to_graph = None | ||||
|  | ||||
|     def set_graphs(self, graphs): | ||||
|         self.comboBox.blockSignals(True) | ||||
|         for gid, name in graphs: | ||||
|             self.comboBox.addItem(name, userData=gid) | ||||
|         self.comboBox.blockSignals(False) | ||||
|  | ||||
|         if not self.comboBox.count(): | ||||
|             self.comboBox.hide() | ||||
|             self.checkBox.hide() | ||||
|  | ||||
|     def checkbox_state(self, checked: QtCore.Qt.CheckState): | ||||
|         if checked == QtCore.Qt.Checked: | ||||
|             self.comboBox.setEnabled(True) | ||||
|             self.add_to_graph = self.comboBox.currentData() | ||||
|         else: | ||||
|             self.comboBox.setEnabled(False) | ||||
|             self.add_to_graph = None | ||||
|  | ||||
|     @QtCore.pyqtSlot(int, name='on_comboBox_currentIndexChanged') | ||||
|     def graph_changed(self, idx: int): | ||||
|         self.add_to_graph = self.comboBox.itemData(idx) | ||||
|  | ||||
|  | ||||
| class SaveDirectoryDialog(_FileDialog): | ||||
|     def __init__(self, directory=None, filters='', parent=None): | ||||
|         super().__init__(directory=directory, filters=filters, parent=parent) | ||||
|  | ||||
|         self.setOption(QtWidgets.QFileDialog.DontConfirmOverwrite, False) | ||||
|         self.setAcceptMode(QtWidgets.QFileDialog.AcceptSave) | ||||
|  | ||||
|         lay = self.layout() | ||||
|  | ||||
|         self.label = QtWidgets.QLabel(self) | ||||
|         self.label.setTextFormat(QtCore.Qt.RichText) | ||||
|         self.label.setText('Use <b><label></b> as placeholder in filename. (e.g. <i>t1_<label>.dat</i>)') | ||||
|         lay.addWidget(self.label, lay.rowCount(), 0, 1, lay.columnCount()) | ||||
|  | ||||
|         line = QtWidgets.QFrame(self) | ||||
|         line.setFrameShape(line.HLine) | ||||
|         line.setFrameShadow(line.Sunken) | ||||
|         lay.addWidget(line, lay.rowCount(), 0, 1, lay.columnCount()) | ||||
|  | ||||
|         h_layout = QtWidgets.QHBoxLayout() | ||||
|         h_layout.setContentsMargins(0, 0, 0, 0) | ||||
|         h_layout.setSpacing(3) | ||||
|  | ||||
|         self.checkBox = QtWidgets.QCheckBox(self) | ||||
|         self.checkBox.setChecked(True) | ||||
|         self.checkBox.setText('Replace spaces with _') | ||||
|         h_layout.addWidget(self.checkBox) | ||||
|  | ||||
|         self.agr_cb = QtWidgets.QCheckBox(self) | ||||
|         self.agr_cb.setChecked(True) | ||||
|         self.agr_cb.setText('Save graph as Grace file') | ||||
|         h_layout.addWidget(self.agr_cb) | ||||
|  | ||||
|         self.fit_cb = QtWidgets.QCheckBox(self) | ||||
|         self.fit_cb.setChecked(True) | ||||
|         self.fit_cb.setText('Save fit parameter') | ||||
|         h_layout.addWidget(self.fit_cb) | ||||
|  | ||||
|         lay.addLayout(h_layout, lay.rowCount(), 0, 1, lay.columnCount()) | ||||
|  | ||||
|         self.setWindowTitle('Save') | ||||
|         self.setNameFilters(['All files (*.*)', 'Session file (*.nmr)', 'Text file (*.dat)', | ||||
|                              'HDF file (*.h5)', 'Grace files (*.agr)']) | ||||
|  | ||||
|     def save_file(self) -> pathlib.Path | None: | ||||
|         outfile = self.selectedFiles() | ||||
|         if outfile: | ||||
|             return pathlib.Path(outfile[0]) | ||||
|         return | ||||
							
								
								
									
										129
									
								
								src/gui_qt/io/filereaders.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										129
									
								
								src/gui_qt/io/filereaders.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| from __future__ import annotations | ||||
|  | ||||
| from pathlib import Path | ||||
| import struct | ||||
|  | ||||
| from ..Qt import QtCore | ||||
| from .asciireader import QAsciiReader | ||||
| from .hdfreader import QHdfViewer | ||||
| from .bdsreader import QBDSReader | ||||
| from .gracereader import QGraceReader | ||||
| from .dscreader import QDSCReader | ||||
| from .nmrreader import QNMRReader | ||||
|  | ||||
|  | ||||
| class QFileReader(QtCore.QObject): | ||||
|     data_read = QtCore.pyqtSignal([list], [dict]) | ||||
|  | ||||
|     def __init__(self, manager=None): | ||||
|         QtCore.QObject.__init__(self) | ||||
|  | ||||
|         self.select = 'all' | ||||
|         self.data = [] | ||||
|         self.filenames = None | ||||
|         self.extensions = set() | ||||
|  | ||||
|         self.reader = {} | ||||
|  | ||||
|         for ext, reader in [ | ||||
|             ('txt', QAsciiReader), ('dsc', QDSCReader), ('agr', QGraceReader), | ||||
|             ('bds', QBDSReader), ('hdf', QHdfViewer),  ('nmr', QNMRReader) | ||||
|         ]: | ||||
|             self.register(ext, reader) | ||||
|  | ||||
|     def __call__(self, files: list[str] | str) -> list: | ||||
|         self.data = [] | ||||
|         if isinstance(files, str): | ||||
|             self.filenames = [files] | ||||
|         else: | ||||
|             self.filenames = files | ||||
|  | ||||
|         return self.readfiles(files) | ||||
|  | ||||
|     def readfiles(self, fname: list[str] | str) -> list: | ||||
|         if not isinstance(fname, list): | ||||
|             fname = [fname] | ||||
|  | ||||
|         for f in fname: | ||||
|             f = Path(f) | ||||
|             dtype = self.guess_type(f) | ||||
|             if dtype in self.reader: | ||||
|                 r = self.reader[dtype] | ||||
|             else: | ||||
|                 raise ValueError(f'Unknown type for file {f}') | ||||
|  | ||||
|             if r(f) is not None: | ||||
|                 # If QAsciiReader.skip = True it accepts automatically and returns None | ||||
|                 r(f).exec() | ||||
|  | ||||
|         self.data_read.emit(self.data) | ||||
|  | ||||
|         try: | ||||
|             self.reader['txt'].skip = False | ||||
|         except KeyError: | ||||
|             pass | ||||
|  | ||||
|         return self.data | ||||
|  | ||||
|     def readtnt(self, fname): | ||||
|         """ Special treatment for tnt. If data is a single measurement, skip dialog """ | ||||
|         raise NotImplementedError | ||||
|         # tntreader = self.reader[2] | ||||
|         # tntreader(fname) | ||||
|         # if not tntreader.reader.onedimensional: | ||||
|         #     tntreader.exec() | ||||
|  | ||||
|     @QtCore.pyqtSlot(list) | ||||
|     def _update_dic(self, other: list): | ||||
|         self.data.extend(other) | ||||
|  | ||||
|     def register(self, key, new_reader): | ||||
|         if key in self.reader: | ||||
|             return self.reader[key] | ||||
|         r = new_reader() | ||||
|         self.reader[key] = r | ||||
|         r.data_read.connect(self._update_dic) | ||||
|         self.extensions.update(r.file_ext) | ||||
|  | ||||
|         return r | ||||
|  | ||||
|     def guess_type(self, fname: Path) -> str: | ||||
|         ext = fname.suffix.lower() | ||||
|  | ||||
|         if ext in self.extensions: | ||||
|             if ext in ('.dat', '.txt'): | ||||
|                 with fname.open('r', encoding='iso-8859-15') as fp: | ||||
|                     line = fp.readline() | ||||
|                     if line.strip().startswith('Filename:	C:\\'): | ||||
|                         return 'dsc' | ||||
|  | ||||
|                 return 'txt' | ||||
|  | ||||
|             if ext in ('.h5', '.hdf', '.hdf5'): | ||||
|                 return 'hdf' | ||||
|  | ||||
|             if ext == '.eps': | ||||
|                 return 'bds' | ||||
|  | ||||
|             return ext[1:]  # remove dot | ||||
|  | ||||
|         else: | ||||
|             with fname.open('rb') as fp: | ||||
|                 s16 = fp.read(16) | ||||
|  | ||||
|                 # copied from whichdb (Python 2.7) to look for magic value of dbhash | ||||
|                 (magic,) = struct.unpack("=l", s16[-4:]) | ||||
|                 if magic in (0x00061561, 0x61150600): | ||||
|                     return 'nmr' | ||||
|  | ||||
|                 else: | ||||
|                     ret_types = ('nmr', 'bds', 'tnt', 'agr', 'dsc') | ||||
|                     strings = (b'NMREVAL', b'NOVOCONTROL', b'TNT1.005', b'# Grace project', b'Filename:\tC:') | ||||
|  | ||||
|                     (magic,) = struct.unpack('<16s', s16) | ||||
|                     for dtype, startstring in zip(ret_types, strings): | ||||
|                         if magic.startswith(startstring): | ||||
|                             return dtype | ||||
|  | ||||
|                     # nothing matched, text file is best guess | ||||
|                     return 'txt' | ||||
							
								
								
									
										100
									
								
								src/gui_qt/io/gracereader.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/gui_qt/io/gracereader.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| from nmreval.lib.lines import LineStyle | ||||
| from nmreval.lib.symbols import SymbolStyle | ||||
| from nmreval.data.points import Points | ||||
| from nmreval.io.graceeditor import GraceEditor | ||||
|  | ||||
| from ..Qt import QtCore, QtWidgets, QtGui | ||||
| from .._py.gracereader import Ui_Dialog | ||||
|  | ||||
|  | ||||
| class QGraceReader(QtWidgets.QDialog, Ui_Dialog): | ||||
|     data_read = QtCore.pyqtSignal(list) | ||||
|     file_ext = ['.agr'] | ||||
|  | ||||
|     def __init__(self, parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|         self.setupUi(self) | ||||
|         self._reader = GraceEditor() | ||||
|         self.treeWidget.itemClicked.connect(self.show_property) | ||||
|  | ||||
|         self.treeWidget.installEventFilter(self) | ||||
|  | ||||
|     def __call__(self, fname, *args, **kwargs): | ||||
|         self.read(fname) | ||||
|  | ||||
|         return self | ||||
|  | ||||
|     def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent): | ||||
|         if evt.type() == QtCore.QEvent.KeyPress: | ||||
|             if evt.key() == QtCore.Qt.Key_Space: | ||||
|                 iterator = QtWidgets.QTreeWidgetItemIterator(self.treeWidget) | ||||
|                 while iterator.value(): | ||||
|                     item = iterator.value() | ||||
|                     if item.parent() is not None and item.isSelected(): | ||||
|                         item.setCheckState(0, | ||||
|                                            QtCore.Qt.Checked if item.checkState(0) == QtCore.Qt.Unchecked else | ||||
|                                            QtCore.Qt.Unchecked) | ||||
|  | ||||
|                     iterator += 1 | ||||
|  | ||||
|                 return True | ||||
|  | ||||
|         return super().eventFilter(src, evt) | ||||
|  | ||||
|     def read(self, fname): | ||||
|         self._reader.parse(fname) | ||||
|  | ||||
|         for graphs in self._reader.graphs: | ||||
|             item = QtWidgets.QTreeWidgetItem([f'Graph {graphs.idx} (Title "{graphs.get_property("title")}")']) | ||||
|             for gset in graphs.set: | ||||
|                 item_2 = QtWidgets.QTreeWidgetItem([f'Set {gset.idx} (Label:  {gset.get_property("legend")}, ' | ||||
|                                                     f'shape: {self._reader.dataset(graphs.idx, gset.idx).shape})']) | ||||
|                 item_2.setCheckState(0, QtCore.Qt.Checked) | ||||
|                 item_2.setData(0, QtCore.Qt.UserRole, (graphs.idx, gset.idx)) | ||||
|                 item.addChild(item_2) | ||||
|  | ||||
|             self.treeWidget.addTopLevelItem(item) | ||||
|         self.treeWidget.expandAll() | ||||
|  | ||||
|     @QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem, int) | ||||
|     def show_property(self, item: QtWidgets.QTreeWidgetItem, col: int): | ||||
|         keys = item.data(col, QtCore.Qt.UserRole) | ||||
|         if keys is not None: | ||||
|             cols = self._reader.colors | ||||
|  | ||||
|             self.tableWidget.item(0, 1).setText(SymbolStyle(self._reader.get_property(*keys, 'symbol')).name) | ||||
|             sym_col = cols[self._reader.get_property(*keys, 'symbol fill color')][1] | ||||
|             self.tableWidget.item(1, 1).setBackground(QtGui.QBrush(QtGui.QColor(*sym_col))) | ||||
|  | ||||
|             self.tableWidget.item(2, 1).setText(LineStyle(self._reader.get_property(*keys, 'line linestyle')).name) | ||||
|  | ||||
|             line_col = cols[self._reader.get_property(*keys, 'line color')][1] | ||||
|             self.tableWidget.item(3, 1).setBackground(QtGui.QBrush(QtGui.QColor(*line_col))) | ||||
|  | ||||
|     def accept(self): | ||||
|         data = [] | ||||
|         iterator = QtWidgets.QTreeWidgetItemIterator(self.treeWidget, | ||||
|                                                      QtWidgets.QTreeWidgetItemIterator.NoChildren | | ||||
|                                                      QtWidgets.QTreeWidgetItemIterator.Checked) | ||||
|  | ||||
|         while iterator.value(): | ||||
|             item = iterator.value() | ||||
|             key = (item.data(0, QtCore.Qt.UserRole)) | ||||
|             s = self._reader.dataset(*key) | ||||
|             label = self._reader.get_property(*key, 'legend').replace('"', '') | ||||
|             # label = self._reader.graphs[key[0]].sets[key[1]]['legend'].replace('"', '') | ||||
|             sd = s.data | ||||
|             if s.type == 'xydy': | ||||
|                 data.append(Points(x=sd[:, 0], y=sd[:, 1], y_err=sd[:, 2], name=label)) | ||||
|             else: | ||||
|                 data.append(Points(x=sd[:, 0], y=sd[:, 1], name=label)) | ||||
|  | ||||
|             iterator += 1 | ||||
|  | ||||
|         self.data_read.emit(data) | ||||
|  | ||||
|         self.close() | ||||
|  | ||||
|     def close(self): | ||||
|         self._reader.clear() | ||||
|         super().close() | ||||
							
								
								
									
										184
									
								
								src/gui_qt/io/hdfreader.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								src/gui_qt/io/hdfreader.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | ||||
| from nmreval.io.hdfreader import HdfReader | ||||
|  | ||||
| from ..Qt import QtGui, QtCore, QtWidgets | ||||
| from .._py.hdftree import Ui_Hdf_Dialog | ||||
|  | ||||
|  | ||||
| class QHdfViewer(QtWidgets.QDialog, Ui_Hdf_Dialog): | ||||
|     data_read = QtCore.pyqtSignal(list) | ||||
|     file_ext = ['.h5', '.hdf', '.hdf5'] | ||||
|  | ||||
|     def __init__(self, fname: str = None, parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|         self.setupUi(self) | ||||
|  | ||||
|         self.treewidget = HDFTreeWidget(self) | ||||
|         self.verticalLayout_3.addWidget(self.treewidget) | ||||
|  | ||||
|         self.variables = VarTable(self) | ||||
|         self.widget_2.addWidget(self.variables) | ||||
|         self.widget_2.setText('Variables') | ||||
|  | ||||
|         self._reader = HdfReader() | ||||
|  | ||||
|         if fname is not None: | ||||
|             self.__call__(fname) | ||||
|  | ||||
|     def __call__(self, fname, *args, **kwargs): | ||||
|         self.treewidget.clear() | ||||
|         for cb in [self.comboBox, self.comboBox_2]: | ||||
|             cb.clear() | ||||
|             cb.addItem('Automatic for the people') | ||||
|             cb.show() | ||||
|  | ||||
|         self._reader(filename=fname) | ||||
|         self._fill_boxes() | ||||
|         self._populate_tree(self._reader, self.treewidget.invisibleRootItem()) | ||||
|  | ||||
|         if self.comboBox.count() == 1: | ||||
|             self.comboBox.hide() | ||||
|             self.comboBox_2.hide() | ||||
|  | ||||
|         self.treewidget.expandToDepth(0) | ||||
|         self.treewidget.resizeColumnToContents(1) | ||||
|  | ||||
|         return self | ||||
|  | ||||
|     def _populate_tree(self, node, item): | ||||
|         self.treewidget.blockSignals(True) | ||||
|  | ||||
|         # add varied parameter to comboboxes | ||||
|         for key, value in node.title_parameter[1].items(): | ||||
|             if isinstance(value, list): | ||||
|                 idx = self.comboBox.findText(key) | ||||
|                 if idx == -1: | ||||
|                     self.comboBox.addItem(key) | ||||
|                     self.comboBox_2.addItem(key) | ||||
|  | ||||
|         if node.children is not None: | ||||
|             for child in node.children.values(): | ||||
|                 label_item = QtWidgets.QTreeWidgetItem([child.name]) | ||||
|                 label_item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsSelectable) | ||||
|                 label_item.setCheckState(0, QtCore.Qt.Unchecked) | ||||
|                 if child.type == 'signal': | ||||
|                     label_item.setBackground(0, QtGui.QBrush(QtGui.QColor(31, 119, 180))) | ||||
|                     label_item.setCheckState(1, QtCore.Qt.Unchecked) | ||||
|                 elif child.type == 'points': | ||||
|                     label_item.setBackground(0, QtGui.QBrush(QtGui.QColor(255, 127, 14))) | ||||
|                 item.addChild(label_item) | ||||
|                 self._populate_tree(child, label_item) | ||||
|  | ||||
|         self.treewidget.blockSignals(False) | ||||
|  | ||||
|     def _fill_boxes(self): | ||||
|         for k, v in self._reader.parameter.items(): | ||||
|             if isinstance(v, list): | ||||
|                 idx = self.comboBox.findText(k) | ||||
|                 if idx == -1: | ||||
|                     self.comboBox.addItem(k) | ||||
|                     self.comboBox_2.addItem(k) | ||||
|  | ||||
|         self.variables.populate(self._reader.parameter) | ||||
|  | ||||
|     @QtCore.pyqtSlot() | ||||
|     def get_selected(self): | ||||
|  | ||||
|         if self.comboBox.currentIndex() == 0: | ||||
|             value = None | ||||
|         else: | ||||
|             value = self.comboBox.currentText() | ||||
|  | ||||
|         if self.comboBox_2.currentIndex() == 0: | ||||
|             group = None | ||||
|         else: | ||||
|             group = self.comboBox_2.currentText() | ||||
|  | ||||
|         iterator = QtWidgets.QTreeWidgetItemIterator(self.treewidget, QtWidgets.QTreeWidgetItemIterator.NoChildren) | ||||
|         selected = [] | ||||
|         while iterator.value(): | ||||
|             item = iterator.value() | ||||
|             iterator += 1 | ||||
|             if item.checkState(0) == QtCore.Qt.Checked: | ||||
|                 path = item.text(0) | ||||
|                 parent = item.parent() | ||||
|                 while parent is not None: | ||||
|                     path = parent.text(0) + '/' + path | ||||
|                     parent = parent.parent() | ||||
|  | ||||
|                 if item.checkState(1) == QtCore.Qt.Checked: | ||||
|                     selected.extend(self._reader.get_selected(path, flag='spectrum', value=value, group=group)) | ||||
|                 else: | ||||
|                     selected.extend(self._reader.get_selected(path, value=value, group=group)) | ||||
|  | ||||
|         self.data_read.emit(selected) | ||||
|  | ||||
|     def accept(self): | ||||
|         self.get_selected() | ||||
|         self.close() | ||||
|  | ||||
|  | ||||
| class VarTable(QtWidgets.QTableWidget): | ||||
|     def __init__(self, parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|  | ||||
|         self.setColumnCount(2) | ||||
|         self.setHorizontalHeaderLabels(['Key', 'Value']) | ||||
|         self.horizontalHeader().setStretchLastSection(True) | ||||
|         self.verticalHeader().setVisible(False) | ||||
|         self.horizontalHeader().setVisible(True) | ||||
|  | ||||
|     def populate(self, vars: dict): | ||||
|         self.setHorizontalHeaderLabels(['Key', 'Value']) | ||||
|         self.setRowCount(len(vars)) | ||||
|         for i, (k, v) in enumerate(vars.items()): | ||||
|             key_item = QtWidgets.QTableWidgetItem(k) | ||||
|             key_item.setFlags(QtCore.Qt.NoItemFlags) | ||||
|             key_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0))) | ||||
|             if isinstance(v, list): | ||||
|                 val = f'<{len(v)} values>' | ||||
|                 if len(v) < 40: | ||||
|                     tip = '\n'.join(str(p) for p in v) | ||||
|                 else: | ||||
|                     tip = '\n'.join(str(p) for p in v[:40]) | ||||
|                     tip += '\n...' | ||||
|             else: | ||||
|                 val = str(v) | ||||
|                 tip = val | ||||
|             value_item = QtWidgets.QTableWidgetItem(val) | ||||
|             value_item.setFlags(QtCore.Qt.NoItemFlags) | ||||
|             value_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0))) | ||||
|             value_item.setToolTip(tip) | ||||
|             self.setItem(i, 0, key_item) | ||||
|             self.setItem(i, 1, value_item) | ||||
|  | ||||
|  | ||||
| class HDFTreeWidget(QtWidgets.QTreeWidget): | ||||
|     def __init__(self, parent): | ||||
|         super().__init__(parent=parent) | ||||
|  | ||||
|         self.setHeaderLabels(['Data', 'Spectrum?']) | ||||
|         self.header().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch) | ||||
|         self.header().setSectionResizeMode(1, QtWidgets.QHeaderView.Fixed) | ||||
|         self.header().setStretchLastSection(False) | ||||
|         self.header().setCascadingSectionResizes(True) | ||||
|         self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) | ||||
|         self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems) | ||||
|  | ||||
|         self.itemChanged.connect(self.change_item) | ||||
|  | ||||
|     def keyPressEvent(self, evt: QtGui.QKeyEvent): | ||||
|         if evt.key() == QtCore.Qt.Key_Space: | ||||
|             for idx in self.selectedIndexes(): | ||||
|                 item = self.itemFromIndex(idx) | ||||
|                 col = idx.column() | ||||
|                 cs = item.checkState(col) | ||||
|                 item.setCheckState(col, QtCore.Qt.Unchecked if cs == QtCore.Qt.Checked else QtCore.Qt.Checked) | ||||
|         else: | ||||
|             super().keyPressEvent(evt) | ||||
|  | ||||
|     @staticmethod | ||||
|     def change_item(item: QtWidgets.QTreeWidgetItem, column: int): | ||||
|         state = item.checkState(column) | ||||
|         for i in range(item.childCount()): | ||||
|             child = item.child(i) | ||||
|             child.setCheckState(column, state) | ||||
							
								
								
									
										34
									
								
								src/gui_qt/io/nmrreader.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/gui_qt/io/nmrreader.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| from struct import unpack | ||||
|  | ||||
| from nmreval.io.nmrreader import NMRReader | ||||
|  | ||||
| from ..Qt import QtCore | ||||
|  | ||||
|  | ||||
| class QNMRReader(QtCore.QObject): | ||||
|     data_read = QtCore.pyqtSignal(list) | ||||
|     file_ext = ['.nmr'] | ||||
|  | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self._reader = NMRReader() | ||||
|  | ||||
|     def __call__(self, fname): | ||||
|         with fname.open('rb') as fp: | ||||
|             s16 = fp.read(16) | ||||
|  | ||||
|             # copied from whichdb (Python 2.7) to look for magic value of dbhash | ||||
|             (magic,) = unpack("=l", s16[-4:]) | ||||
|             if magic in (0x00061561, 0x61150600): | ||||
|                 self._reader(fname, '-1') | ||||
|  | ||||
|             else: | ||||
|                 (magic,) = unpack('<16s', s16) | ||||
|                 if magic.startswith(b'NMREVAL'): | ||||
|                     self._reader(fname, str(magic[7:].rstrip(b'\x00'), 'utf8')) | ||||
|  | ||||
|         return self | ||||
|  | ||||
|     def exec(self): | ||||
|         data = self._reader.make_data() | ||||
|         self.data_read.emit([data]) | ||||
							
								
								
									
										65
									
								
								src/gui_qt/io/save_fitparameter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/gui_qt/io/save_fitparameter.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| from ..Qt import QtWidgets, QtCore, QtGui | ||||
| from .._py.save_fit_parameter import Ui_fitparameter_save_dialog | ||||
|  | ||||
|  | ||||
| class QSaveFit(QtWidgets.QDialog, Ui_fitparameter_save_dialog): | ||||
|     def __init__(self, path: str = None, parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|  | ||||
|         self.pnames = None | ||||
|         self.outpath = path | ||||
|  | ||||
|         self.setupUi(self) | ||||
|  | ||||
|         self.tableWidget.cellDoubleClicked.connect(self.clicketyclick) | ||||
|         self.tableWidget.setColumnCount(2) | ||||
|  | ||||
|         self.save_path_line.textEdited.connect(lambda: self.change_path(self.save_path_line.text())) | ||||
|         self.save_path_button.clicked.connect(self.set_save_path) | ||||
|  | ||||
|         self.header_edit.hide() | ||||
|         self.header_checkBox.stateChanged.connect(lambda state: self.header_edit.setVisible(state)) | ||||
|  | ||||
|         self.missing_value_line.setValidator(QtGui.QDoubleValidator()) | ||||
|  | ||||
|     def set_parameter(self, fits: dict): | ||||
|         for model_name, parameter in fits.items(): | ||||
|             for p in parameter: | ||||
|                 item = QtWidgets.QTableWidgetItem(p) | ||||
|                 item2 = QtWidgets.QTableWidgetItem(model_name) | ||||
|                 item2.setToolTip(model_name) | ||||
|                 row = self.tableWidget.rowCount() | ||||
|                 self.tableWidget.setRowCount(row+1) | ||||
|                 self.tableWidget.setItem(row, 0, item) | ||||
|                 self.tableWidget.setItem(row, 1, item2) | ||||
|  | ||||
|         self.tableWidget.resizeColumnsToContents() | ||||
|  | ||||
|     @QtCore.pyqtSlot(int, int) | ||||
|     def clicketyclick(self, row: int, _): | ||||
|         if self.col_line.text(): | ||||
|             self.col_line.setText(self.col_line.text() + '; ' + self.tableWidget.item(row, 0).text()) | ||||
|         else: | ||||
|             self.col_line.setText(self.tableWidget.item(row, 0).text()) | ||||
|  | ||||
|     def set_save_path(self): | ||||
|         fname, _ = QtWidgets.QFileDialog.getSaveFileName(options=QtWidgets.QFileDialog.DontConfirmOverwrite, | ||||
|                                                          directory=self.outpath) | ||||
|  | ||||
|         if fname: | ||||
|             self.outpath = fname | ||||
|             self.save_path_line.setText(fname) | ||||
|  | ||||
|     def add_header(self, idx: int): | ||||
|         self.textEdit.setVisible(idx != 0) | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_usage_button_clicked') | ||||
|     def show_usage(self): | ||||
|         _ = QtWidgets.QMessageBox.information(self, 'Usage', | ||||
|                                               'Separate each column by semicolon.\n' | ||||
|                                               'Use p_err to save error of parameter p.\n' | ||||
|                                               'If a column shall contain different parameters use {p1/p2}.\n' | ||||
|                                               'KWW mean is calculated by mean(τ,β), KWW peak by peak(τ,β).') | ||||
|  | ||||
|     def accept(self): | ||||
|         super().accept() | ||||
							
								
								
									
										109
									
								
								src/gui_qt/io/tntreader.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/gui_qt/io/tntreader.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| from nmreval.io.tntreader import TNTReader | ||||
|  | ||||
| from ..Qt import QtCore, QtWidgets | ||||
| from .._py.tntdialog import Ui_tntdialog | ||||
|  | ||||
|  | ||||
| class QTNTReader(QtWidgets.QDialog, Ui_tntdialog): | ||||
|     data_read = QtCore.pyqtSignal(dict) | ||||
|     file_ext = ['.tnt'] | ||||
|  | ||||
|     def __init__(self, fname=None, parent=None): | ||||
|         super().__init__(parent=parent) | ||||
|         self.setupUi(self) | ||||
|  | ||||
|         self.reader = TNTReader(fname) | ||||
|  | ||||
|         self.frame.hide() | ||||
|  | ||||
|         if fname is not None: | ||||
|             if self.reader.onedimensional: | ||||
|                 self.export() | ||||
|             else: | ||||
|                 self.set_gui() | ||||
|  | ||||
|     def __call__(self, fname, *args, **kwargs): | ||||
|         self.reader(fname) | ||||
|         for s in [self.widget, self.widget_2, self.widget_3]: | ||||
|             s.__call__() | ||||
|  | ||||
|         self.frame.hide() | ||||
|         self.frame_2.show() | ||||
|         self.unknown_delay_combobox.clear() | ||||
|  | ||||
|         if self.reader.onedimensional: | ||||
|             self.export() | ||||
|         else: | ||||
|             self.set_gui() | ||||
|  | ||||
|         return self | ||||
|  | ||||
|     def set_gui(self): | ||||
|         self.label_3.setText(' x '.join(map(str, self.reader.shape))) | ||||
|         for i, w in enumerate([self.widget, self.widget_2, self.widget_3], start=1): | ||||
|             if self.reader.shape[i] == 1: | ||||
|                 w.hide() | ||||
|             else: | ||||
|                 w.label.setText('Dimension {}'.format(i+1)) | ||||
|                 w.dim = i | ||||
|                 w.add_items([x[0] for x in self.reader.delays.items() if len(x[1]) == self.reader.shape[i]]) | ||||
|                 w.get_data.connect(self.show_delays) | ||||
|                 w.newDelay.connect(self.calc_delays) | ||||
|         for x in self.reader.delays.items(): | ||||
|             if len(x[1]) in self.reader.shape[1:]: | ||||
|                 continue | ||||
|             else: | ||||
|                 self.unknown_delay_combobox.addItem(x[0]) | ||||
|         if self.unknown_delay_combobox.count() == 0: | ||||
|             self.frame_2.hide() | ||||
|  | ||||
|     @QtCore.pyqtSlot(str) | ||||
|     def show_delays(self, label): | ||||
|         vals = self.reader.delays[str(label)] | ||||
|         self.sender().vals = '\n'.join(map(str, vals)) | ||||
|  | ||||
|     def calc_delays(self): | ||||
|         self.frame.show() | ||||
|         self._caller = self.sender() | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_pushButton_2_clicked') | ||||
|     def cancel_delay(self): | ||||
|         self.frame.hide() | ||||
|  | ||||
|     @QtCore.pyqtSlot(name='on_pushButton_clicked') | ||||
|     def add_delay(self): | ||||
|         try: | ||||
|             s = float(self.start_lineedit.text()) | ||||
|         except ValueError: | ||||
|             return | ||||
|         try: | ||||
|             e = float(self.end_lineedit.text()) | ||||
|         except ValueError: | ||||
|             return | ||||
|         d = [] | ||||
|         for w in [self.widget, self.widget_2, self.widget_3]: | ||||
|             if w.isVisible(): | ||||
|                 d.append(w.comboBox.currentText()) | ||||
|         self.reader.add_delay(s, e, self._caller.dim, self.lineEdit.text(), | ||||
|                               staggered=self.checkBox_2.isChecked(), stag_steps=int(self.spinBox.value()), | ||||
|                               log=self.checkBox.isChecked()) | ||||
|         self._caller.add_items(self.lineEdit.text()) | ||||
|         self.frame.hide() | ||||
|  | ||||
|     def export(self): | ||||
|         d = [] | ||||
|         for w in [self.widget, self.widget_2, self.widget_3]: | ||||
|             if w.isVisible(): | ||||
|                 d.append(w.comboBox.currentText()) | ||||
|             else: | ||||
|                 d.append(None) | ||||
|  | ||||
|         ret_dic = self.reader.export(d) | ||||
|  | ||||
|         self.data_read.emit(ret_dic) | ||||
|         self.close() | ||||
|  | ||||
|         return ret_dic | ||||
|  | ||||
|     def accept(self): | ||||
|         self.export() | ||||
		Reference in New Issue
	
	Block a user