From ec9f40dad4384786154763f7c9868dc3868727a3 Mon Sep 17 00:00:00 2001 From: jupfi Date: Tue, 18 Jul 2023 10:08:05 +0200 Subject: [PATCH] Added fft view. --- src/nqrduck_measurement/controller.py | 14 ++++- src/nqrduck_measurement/model.py | 52 ++++++++++++++--- .../resources/measurement_widget.ui | 42 +++++++++++++- src/nqrduck_measurement/view.py | 56 +++++++++++++------ src/nqrduck_measurement/widget.py | 16 ++++++ 5 files changed, 154 insertions(+), 26 deletions(-) diff --git a/src/nqrduck_measurement/controller.py b/src/nqrduck_measurement/controller.py index 1e20b8d..6e9ce10 100644 --- a/src/nqrduck_measurement/controller.py +++ b/src/nqrduck_measurement/controller.py @@ -1,4 +1,5 @@ import logging +from PyQt6.QtCore import pyqtSlot from nqrduck.module.module_controller import ModuleController from nqrduck_spectrometer.measurement import Measurement @@ -8,6 +9,16 @@ class MeasurementController(ModuleController): def __init__(self, module): super().__init__(module) + @pyqtSlot() + def change_view_mode(self): + logger.debug("Changing view mode.") + if self.module.model.view_mode == self.module.model.FFT_VIEW: + self.module.model.view_mode = self.module.model.TIME_VIEW + else: + self.module.model.view_mode = self.module.model.FFT_VIEW + + logger.debug("View mode changed to: " + self.module.model.view_mode) + def start_measurement(self): logger.debug("Start measurement clicked") self.module.view.measurement_dialog.show() @@ -18,5 +29,6 @@ class MeasurementController(ModuleController): if key == "measurement_data" and self.module.view.measurement_dialog.isVisible(): logger.debug("Received single measurement.") - self.module.model.single_measurement = value + self.module.model.displayed_measurement = value + self.module.model.add_measurement(value) self.module.view.measurement_dialog.hide() diff --git a/src/nqrduck_measurement/model.py b/src/nqrduck_measurement/model.py index 803987d..c74a9b8 100644 --- a/src/nqrduck_measurement/model.py +++ b/src/nqrduck_measurement/model.py @@ -7,17 +7,53 @@ logger = logging.getLogger(__name__) class MeasurementModel(ModuleModel): - single_measurement_changed = pyqtSignal(Measurement) + # This constants are used to determine which view is currently displayed. + FFT_VIEW = "fft" + TIME_VIEW = "time" + + displayed_measurement_changed = pyqtSignal(Measurement) + measurements_changed = pyqtSignal(list) + view_mode_changed = pyqtSignal(str) def __init__(self, module) -> None: super().__init__(module) + self.view_mode = self.TIME_VIEW + self.measurements = [] @property - def single_measurement(self): - """Single measurement data.""" - return self._single_measurement + def view_mode(self): + """View mode of the measurement view. + Can be either "time" or "fft".""" + return self._view_mode - @single_measurement.setter - def single_measurement(self, value : Measurement): - self._single_measurement = value - self.single_measurement_changed.emit(value) + @view_mode.setter + def view_mode(self, value : str): + self._view_mode = value + self.view_mode_changed.emit(value) + + @property + def measurements(self): + """List of measurements.""" + return self._measurements + + @measurements.setter + def measurements(self, value : list[Measurement]): + self._measurements = value + self.measurements_changed.emit(value) + + def add_measurement(self, measurement : Measurement): + """Add a measurement to the list of measurements.""" + self.measurements.append(measurement) + self.measurements_changed.emit(self.measurements) + + @property + def displayed_measurement(self): + """Displayed measurement data. + This is the data that is displayed in the view. + It can be data in time domain or frequency domain.""" + return self._displayed_measurement + + @displayed_measurement.setter + def displayed_measurement(self, value : Measurement): + self._displayed_measurement = value + self.displayed_measurement_changed.emit(value) diff --git a/src/nqrduck_measurement/resources/measurement_widget.ui b/src/nqrduck_measurement/resources/measurement_widget.ui index c7aaa39..ffc2fbb 100644 --- a/src/nqrduck_measurement/resources/measurement_widget.ui +++ b/src/nqrduck_measurement/resources/measurement_widget.ui @@ -95,7 +95,7 @@ - + @@ -106,6 +106,46 @@ + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + FFT + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/src/nqrduck_measurement/view.py b/src/nqrduck_measurement/view.py index adcb839..7b6281a 100644 --- a/src/nqrduck_measurement/view.py +++ b/src/nqrduck_measurement/view.py @@ -14,6 +14,7 @@ class MeasurementView(ModuleView): def __init__(self, module): super().__init__(module) + # Set custom matplotlib parameters mpl.rcParams.update({ "figure.facecolor": (0.0, 0.0, 0.0, 0.00), # transparent "axes.facecolor": (0.0, 1.0, 0.0, 0.03), # green @@ -45,33 +46,56 @@ class MeasurementView(ModuleView): self.measurement_dialog = self.MeasurementDialog() # Connect signals - self.module.model.single_measurement_changed.connect(self.update_single_measurement) + self.module.model.displayed_measurement_changed.connect(self.update_displayed_measurement) + self.module.model.view_mode_changed.connect(self.update_displayed_measurement) + self._ui_form.buttonStart.clicked.connect(self.on_measurement_start_button_clicked) + self._ui_form.fftButton.clicked.connect(self.module.controller.change_view_mode) def init_plotter(self): plotter = self._ui_form.plotter + plotter.canvas.ax.clear() plotter.canvas.ax.set_xlim(0, 100) plotter.canvas.ax.set_ylim(0, 1) plotter.canvas.ax.set_xlabel("Time (µs)") plotter.canvas.ax.set_ylabel("Amplitude (a.u.)") - plotter.canvas.ax.set_title("Measurement data") + plotter.canvas.ax.set_title("Measurement data - Time domain") + plotter.canvas.ax.grid() + + def change_to_time_view(self): + plotter = self._ui_form.plotter + plotter.canvas.ax.clear() + plotter.canvas.ax.set_xlabel("Time (µs)") + plotter.canvas.ax.set_ylabel("Amplitude (a.u.)") + plotter.canvas.ax.set_title("Measurement data - Time domain") + plotter.canvas.ax.grid() + + def change_to_fft_view(self): + plotter = self._ui_form.plotter + plotter.canvas.ax.clear() + plotter.canvas.ax.set_xlabel("Frequency (MHz)") + plotter.canvas.ax.set_ylabel("Amplitude (a.u.)") + plotter.canvas.ax.set_title("Measurement data - Frequency domain") plotter.canvas.ax.grid() - plotter.canvas.draw() @pyqtSlot() - def update_single_measurement(self): - logger.debug("Updating single measurement view.") - # Set the x data - tdx = self.module.model.single_measurement.tdx - tdy = self.module.model.single_measurement.tdy - #correcting a offset in the time domain by subtracting the mean - tdy_mean = tdy[:,0]-np.mean(tdy) - self._ui_form.plotter.canvas.ax.set_xlabel("Time (µs)") - self._ui_form.plotter.canvas.ax.set_ylabel("Amplitude (a.u.)") - self._ui_form.plotter.canvas.ax.set_title("Measurement data") - self._ui_form.plotter.canvas.ax.clear() # Clear the axes for the new plot - self._ui_form.plotter.canvas.ax.plot(tdx, tdy_mean) - self._ui_form.plotter.canvas.ax.grid() + def update_displayed_measurement(self): + logger.debug("Updating displayed measurement view.") + plotter = self._ui_form.plotter + plotter.canvas.ax.clear() + try: + if self.module.model.view_mode == self.module.model.FFT_VIEW: + self.change_to_fft_view() + x = self.module.model.displayed_measurement.fdx + y = self.module.model.displayed_measurement.fdy + else: + self.change_to_time_view() + x = self.module.model.displayed_measurement.tdx + y = self.module.model.displayed_measurement.tdy + + self._ui_form.plotter.canvas.ax.plot(x, y) + except AttributeError: + logger.debug("No measurement data to display.") self._ui_form.plotter.canvas.draw() @pyqtSlot() diff --git a/src/nqrduck_measurement/widget.py b/src/nqrduck_measurement/widget.py index d49ea75..e3ee105 100644 --- a/src/nqrduck_measurement/widget.py +++ b/src/nqrduck_measurement/widget.py @@ -68,6 +68,21 @@ class Ui_Form(object): self.plotter.setSizePolicy(sizePolicy) self.plotter.setObjectName("plotter") self.plotterLayout.addWidget(self.plotter) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) + self.horizontalLayout_3.addItem(spacerItem1) + self.fftButton = QtWidgets.QToolButton(parent=Form) + self.fftButton.setObjectName("fftButton") + self.horizontalLayout_3.addWidget(self.fftButton) + self.selectionBox = QtWidgets.QSpinBox(parent=Form) + self.selectionBox.setObjectName("selectionBox") + self.horizontalLayout_3.addWidget(self.selectionBox) + spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) + self.horizontalLayout_3.addItem(spacerItem2) + self.horizontalLayout_3.setStretch(1, 1) + self.plotterLayout.addLayout(self.horizontalLayout_3) + self.plotterLayout.setStretch(1, 1) self.horizontalLayout_2.addLayout(self.plotterLayout) self.horizontalLayout_2.setStretch(1, 1) self.horizontalLayout.addLayout(self.horizontalLayout_2) @@ -83,4 +98,5 @@ class Ui_Form(object): self.label.setText(_translate("Form", "Target Frequency")) self.label_2.setText(_translate("Form", "Averages")) self.buttonStart.setText(_translate("Form", "Start Measurement")) + self.fftButton.setText(_translate("Form", "FFT")) from nqrduck.contrib.mplwidget import MplWidget