BUGFIX: VFT;

change to src layout
This commit is contained in:
dominik
2022-10-20 17:23:15 +02:00
parent 89ce4bab9f
commit 8d148b639b
445 changed files with 1387 additions and 1920 deletions

View File

View 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()

View 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
View 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
View 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()

View 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
View 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>&lt;label&gt;</b> as placeholder in filename. (e.g. <i>t1_&lt;label&gt;.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
View 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'

View 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
View 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)

View 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])

View 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
View 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()