from __future__ import annotations import pathlib import re from pathlib import Path from numpy import geomspace, linspace from pyqtgraph import ViewBox, PlotDataItem from nmreval.configs import * from .management import UpperManagement from ..Qt import QtCore, QtGui, QtPrintSupport, QtWidgets from ..data.shift_graphs import QShift from ..data.signaledit import QApodDialog, QBaselineDialog, QPhasedialog from ..fit.result import QFitResult from ..graphs.graphwindow import QGraphWindow from ..graphs.movedialog import QMover from ..io.fcbatchreader import QFCReader from ..io.filedialog import OpenFileDialog, SaveDirectoryDialog from ..lib import get_icon, make_action_icons from ..lib.pg_objects import RegionItem from ..math.evaluation import QEvalDialog from ..math.interpol import InterpolDialog from ..math.mean_dialog import QMeanTimes from ..math.smooth import QSmooth from ..nmr.coupling_calc import QCoupCalcDialog from ..nmr.t1_from_tau import QRelaxCalc from .._py.basewindow import Ui_BaseWindow class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow): closeSignal = QtCore.pyqtSignal() openpoints = QtCore.pyqtSignal(dict) save_ses_sig = QtCore.pyqtSignal(str) rest_ses_sig = QtCore.pyqtSignal(str) def __init__(self, parents=None, path=None): super().__init__(parent=parents) if path is None: self.path = Path.home() else: self.path = Path(path) self.read_state() self.management = UpperManagement(self) self.fitlimitvalues = [None, None] self.fitpreview = [] self._fit_plot_id = None self.savefitdialog = None self.eval = None self.editor = None self.movedialog = QMover(self) self.current_graph_widget = None self.current_plotitem = None self._block_window_change = False self.fname = None self.tim = QtCore.QTimer() self.settings = QtCore.QSettings('NMREVal', 'settings') self._init_gui() self._init_signals() def _init_gui(self): self.setupUi(self) make_action_icons(self) self.setWindowIcon(get_icon('logo')) self.norm_toolbutton = QtWidgets.QToolButton(self) self.norm_toolbutton.setMenu(self.menuNormalize) self.norm_toolbutton.setPopupMode(self.norm_toolbutton.InstantPopup) self.norm_toolbutton.setIcon(get_icon('normal')) self.toolbar_edit.addWidget(self.norm_toolbutton) self.fitlim_button = QtWidgets.QToolButton(self) self.fitlim_button.setMenu(self.menuLimits) self.fitlim_button.setPopupMode(self.fitlim_button.InstantPopup) self.fitlim_button.setIcon(get_icon('fit_region')) self.toolBar_fit.addWidget(self.fitlim_button) self.area.dragEnterEvent = self.dragEnterEvent while self.tabWidget.count() > 2: self.tabWidget.removeTab(self.tabWidget.count()-1) # Prevent closing "data" and "values" for i in [0, 1]: self.tabWidget.tabBar().tabButton(i, QtWidgets.QTabBar.ButtonPosition.RightSide).resize(0, 0) self.setAcceptDrops(True) self.mousepos = QtWidgets.QLabel('') self.status = QtWidgets.QLabel('') self.statusBar.addWidget(self.status) self.statusBar.addWidget(self.mousepos) self.fitregion = RegionItem() self._values_plot = PlotDataItem(x=[], y=[], symbolSize=30, symbol='x', pen=None, symbolPen='#d526b5', symbolBrush='#d526b5') self._fit_plot_id = None self.setGeometry(QtWidgets.QStyle.alignedRect(QtCore.Qt.LeftToRight, QtCore.Qt.AlignCenter, self.size(), QtWidgets.qApp.desktop().availableGeometry())) self.datawidget.management = self.management self.ac_group = QtWidgets.QActionGroup(self) self.ac_group.addAction(self.action_lm_fit) self.ac_group.addAction(self.action_nm_fit) self.ac_group.addAction(self.action_odr_fit) self.ac_group2 = QtWidgets.QActionGroup(self) self.ac_group2.addAction(self.action_no_range) self.ac_group2.addAction(self.action_x_range) self.ac_group2.addAction(self.action_custom_range) def _init_signals(self): self.actionRedo = self.management.undostack.createRedoAction(self) icon = QtGui.QIcon.fromTheme("edit-redo") self.actionRedo.setIcon(icon) self.actionRedo.setShortcuts(QtGui.QKeySequence.Redo) self.menuData.insertAction(self.action_new_set, self.actionRedo) self.actionUndo = self.management.undostack.createUndoAction(self) self.actionUndo.setShortcuts(QtGui.QKeySequence.Undo) icon = QtGui.QIcon.fromTheme("edit-undo") self.actionUndo.setIcon(icon) self.menuData.insertAction(self.actionRedo, self.actionUndo) # # self.actionSave.triggered.connect(lambda: self.management.save('/autohome/dominik/nmreval/testdata/test.nmr', '')) # self.actionSave.triggered.connect(self.save) self.action_save_fit_parameter.triggered.connect(self.save_fit_parameter) self.ac_group2.triggered.connect(self.change_fit_limits) self.t1action.triggered.connect(lambda: self._show_tab('t1_temp')) self.action_edit.triggered.connect(lambda: self._show_tab('signal')) self.actionPick_position.triggered.connect(lambda: self._show_tab('pick')) self.actionIntegrate.triggered.connect(lambda: self._show_tab('integrate')) self.action_FitWidget.triggered.connect(lambda: self._show_tab('fit')) # self.action_draw_object.triggered.connect(lambda: self._show_tab('drawing')) self.action_new_set.triggered.connect(self.management.create_empty) self.datawidget.keyChanged.connect(self.management.change_keys) self.datawidget.tree.deleteItem.connect(self.management.delete_sets) self.datawidget.tree.moveItem.connect(self.management.move_sets) self.datawidget.tree.copyItem.connect(self.management.copy_sets) self.datawidget.graph_toolButton.clicked.connect(self.new_graph) self.datawidget.empty_toolButton.clicked.connect(self.management.create_empty) self.datawidget.func_toolButton.clicked.connect(self.make_data_from_function) self.datawidget.tree.stateChanged.connect(self.management.change_visibility) self.datawidget.startShowProperty.connect(self.management.get_properties) self.datawidget.propertyChanged.connect(self.management.update_property) self.datawidget.tree.saveFits.connect(self.save_fit_parameter) self.management.newData.connect(self.show_new_data) self.management.newGraph.connect(self.new_graph) self.management.dataChanged.connect(self.update_data) self.management.deleteData.connect(self.delete_data) self.management.deleteGraph.connect(self.remove_graph) self.management.restoreGraph.connect(self.set_graph) self.management.properties_collected.connect(self.datawidget.set_properties) self.management.unset_state.connect(lambda x: self.datawidget.uncheck_sets(x)) self.management.fitFinished.connect(self.show_fit_results) self.fit_dialog._management = self.management self.fit_dialog.preview_emit.connect(self.show_fit_preview) self.fit_dialog.fitStartSig.connect(self.start_fit) self.fit_dialog.abortFit.connect(lambda : self.management.stopFit.emit()) self.movedialog.moveData.connect(self.move_sets) self.movedialog.copyData.connect(self.management.copy_sets) self.ptsselectwidget.points_selected.connect(self.management.extract_points) self.t1tauwidget.newData.connect(self.management.add_new_data) self.editsignalwidget.do_something.connect(self.management.apply) self.editsignalwidget.preview_triggered.connect(self.do_preview) self.action_sort_pts.triggered.connect(lambda: self.management.apply('sort', ())) self.action_calc_eps_derivative.triggered.connect(self.management.bds_deriv) self.action_magnitude.triggered.connect(self.management.calc_magn) self.actionCenterMax.triggered.connect(lambda: self.management.apply('center', ())) self.valuewidget.requestData.connect(self.show_data_values) self.valuewidget.itemChanged.connect(self.management.set_values) self.valuewidget.itemDeleted.connect(self.management.remove_values) self.valuewidget.itemAdded.connect(self.management.append) self.valuewidget.maskSignal.connect(self.management.mask_value) self.valuewidget.values_selected.connect(self.plot_selected_values) self.valuewidget.split_signal.connect(self.management.split_set) self.actionMaximize.triggered.connect(lambda: self.current_graph_widget.showMaximized()) self.actionNext_window.triggered.connect(lambda: self.area.activateNextSubWindow()) self.actionPrevious.triggered.connect(lambda: self.area.activatePreviousSubWindow()) self.closeSignal.connect(self.close) self.action_norm_max.triggered.connect(lambda: self.management.apply('norm', ('max',))) self.action_norm_max_abs.triggered.connect(lambda: self.management.apply('norm', ('maxabs',))) self.action_norm_first.triggered.connect(lambda: self.management.apply('norm', ('first',))) self.action_norm_last.triggered.connect(lambda: self.management.apply('norm', ('last',))) self.action_norm_area.triggered.connect(lambda: self.management.apply('norm', ('area',))) self.action_cut.triggered.connect(lambda: self.management.cut()) self.actionConcatenate_sets.triggered.connect(lambda : self.management.cat()) @QtCore.pyqtSlot(name='on_action_open_triggered') def open(self): filedialog = OpenFileDialog(directory=self.path, caption='Open files', filters='All files (*.*);;' 'Program session (*.nmr);;' 'HDF files (*.h5);;' 'Text files (*.txt *.dat);;' 'Novocontrol Alpha (*.EPS);;' 'TecMag files (*.tnt);;' 'Grace files (*.agr)') filedialog.set_graphs(self.management.graphs.list()) filedialog.exec() fname = filedialog.selectedFiles() if fname: self.path = Path(fname[0]).parent self.management.load_files(fname, new_plot=filedialog.add_to_graph) @QtCore.pyqtSlot(name='on_actionOpen_FC_triggered') def read_fc(self): reader = QFCReader(path=self.path, parent=self) reader.data_read.connect(self.management.add_new_data) reader.exec() del reader @QtCore.pyqtSlot(name='on_actionPrint_triggered') def print(self): QtPrintSupport.QPrintDialog().exec() @QtCore.pyqtSlot(name='on_actionExportData_triggered') @QtCore.pyqtSlot(name='on_actionSave_triggered') def save(self): save_dialog = SaveDirectoryDialog( directory=str(self.path), parent=self, ) mode = save_dialog.exec() if mode == QtWidgets.QDialog.Accepted: savefile = save_dialog.save_file() selected_filter = save_dialog.selectedNameFilter() if savefile is not None: use_underscore = save_dialog.checkBox.isChecked() self.management.save(savefile, selected_filter, strip_spaces=use_underscore) param_outfile = re.sub('[_\s-]?