mirror of
https://github.com/nqrduck/nqrduck-measurement.git
synced 2025-01-03 13:18:11 +00:00
Formatting.
This commit is contained in:
parent
1e6c4d3083
commit
d3594230a0
5 changed files with 162 additions and 91 deletions
|
@ -1,8 +1,9 @@
|
|||
"""Controller for the measurement module."""
|
||||
|
||||
import logging
|
||||
import json
|
||||
import numpy as np
|
||||
from decimal import Decimal
|
||||
from decimal import Decimal
|
||||
from PyQt6.QtCore import pyqtSlot, pyqtSignal
|
||||
from PyQt6.QtGui import QValidator
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
|
@ -27,6 +28,7 @@ class MeasurementController(ModuleController):
|
|||
set_frequency_failure (pyqtSignal): Signal emitted when setting the frequency fails.
|
||||
set_averages_failure (pyqtSignal): Signal emitted when setting the averages fails.
|
||||
"""
|
||||
|
||||
set_frequency_failure = pyqtSignal()
|
||||
set_averages_failure = pyqtSignal()
|
||||
|
||||
|
@ -45,9 +47,14 @@ class MeasurementController(ModuleController):
|
|||
ValueError: If value cannot be converted to float.
|
||||
"""
|
||||
# Use validator
|
||||
if self.module.model.validator_measurement_frequency.validate(value, 0) == QValidator.State.Acceptable:
|
||||
if (
|
||||
self.module.model.validator_measurement_frequency.validate(value, 0)
|
||||
== QValidator.State.Acceptable
|
||||
):
|
||||
self.module.model.measurement_frequency = float(value) * 1e6
|
||||
self.module.nqrduck_signal.emit("set_frequency", str(self.module.model.measurement_frequency))
|
||||
self.module.nqrduck_signal.emit(
|
||||
"set_frequency", str(self.module.model.measurement_frequency)
|
||||
)
|
||||
|
||||
self.toggle_start_button()
|
||||
|
||||
|
@ -59,10 +66,15 @@ class MeasurementController(ModuleController):
|
|||
value (str): Number of averages.
|
||||
"""
|
||||
logger.debug("Setting averages to: " + value)
|
||||
#self.module.nqrduck_signal.emit("set_averages", value)
|
||||
if self.module.model.validator_averages.validate(value, 0) == QValidator.State.Acceptable:
|
||||
# self.module.nqrduck_signal.emit("set_averages", value)
|
||||
if (
|
||||
self.module.model.validator_averages.validate(value, 0)
|
||||
== QValidator.State.Acceptable
|
||||
):
|
||||
self.module.model.averages = int(value)
|
||||
self.module.nqrduck_signal.emit("set_averages", str(self.module.model.averages))
|
||||
self.module.nqrduck_signal.emit(
|
||||
"set_averages", str(self.module.model.averages)
|
||||
)
|
||||
|
||||
self.toggle_start_button()
|
||||
|
||||
|
@ -83,7 +95,9 @@ class MeasurementController(ModuleController):
|
|||
self.module.view.measurement_dialog.show()
|
||||
|
||||
# Set the measurement parameters again in case the user switches spectrometer
|
||||
self.module.nqrduck_signal.emit("set_frequency", str(self.module.model.measurement_frequency))
|
||||
self.module.nqrduck_signal.emit(
|
||||
"set_frequency", str(self.module.model.measurement_frequency)
|
||||
)
|
||||
self.module.nqrduck_signal.emit("set_averages", str(self.module.model.averages))
|
||||
QApplication.processEvents()
|
||||
|
||||
|
@ -132,9 +146,7 @@ class MeasurementController(ModuleController):
|
|||
):
|
||||
logger.debug("Received measurement error.")
|
||||
self.module.view.measurement_dialog.hide()
|
||||
self.module.nqrduck_signal.emit(
|
||||
"notification", ["Error", value]
|
||||
)
|
||||
self.module.nqrduck_signal.emit("notification", ["Error", value])
|
||||
|
||||
elif (
|
||||
key == "failure_set_frequency"
|
||||
|
@ -150,10 +162,11 @@ class MeasurementController(ModuleController):
|
|||
logger.debug("Received set averages failure.")
|
||||
self.set_averages_failure.emit()
|
||||
elif key == "active_spectrometer_changed":
|
||||
self.module.view._ui_form.spectrometerLabel.setText("Spectrometer: %s" % value)
|
||||
self.module.view._ui_form.spectrometerLabel.setText(
|
||||
"Spectrometer: %s" % value
|
||||
)
|
||||
|
||||
|
||||
def save_measurement(self, file_name : str) -> None:
|
||||
def save_measurement(self, file_name: str) -> None:
|
||||
"""Save measurement to file.
|
||||
|
||||
Args:
|
||||
|
@ -169,7 +182,7 @@ class MeasurementController(ModuleController):
|
|||
with open(file_name, "w") as f:
|
||||
json.dump(measurement, f)
|
||||
|
||||
def load_measurement(self, file_name: str) -> None:
|
||||
def load_measurement(self, file_name: str) -> None:
|
||||
"""Load measurement from file.
|
||||
|
||||
Args:
|
||||
|
@ -204,19 +217,25 @@ class MeasurementController(ModuleController):
|
|||
)
|
||||
return
|
||||
|
||||
# We need to create a event which corresponds to the measurement.
|
||||
# We need to create a event which corresponds to the measurement.
|
||||
event_duration = self.module.model.displayed_measurement.tdx[-1] * 1e-6
|
||||
|
||||
event = PulseSequence.Event(name="Apodization", duration=str(event_duration))
|
||||
parameter = Apodization()
|
||||
parameter.start_x = 0
|
||||
parameter.start_x = 0
|
||||
parameter.end_x = event_duration
|
||||
dialog = OptionsDialog(event, parameter, self.module.view)
|
||||
result = dialog.exec()
|
||||
|
||||
if result:
|
||||
for option, function in dialog.return_functions.items():
|
||||
logger.debug("Setting option %s of parameter %s in event %s to %s", option, parameter, event, function())
|
||||
logger.debug(
|
||||
"Setting option %s of parameter %s in event %s to %s",
|
||||
option,
|
||||
parameter,
|
||||
event,
|
||||
function(),
|
||||
)
|
||||
option.set_value(function())
|
||||
|
||||
# Get the function from the Apodization function
|
||||
|
@ -224,9 +243,12 @@ class MeasurementController(ModuleController):
|
|||
logger.debug("Apodization function: %s", function)
|
||||
|
||||
# Get the y data weights from the function
|
||||
resolution = (self.module.model.displayed_measurement.tdx[1] - self.module.model.displayed_measurement.tdx[0]) * 1e-6
|
||||
resolution = (
|
||||
self.module.model.displayed_measurement.tdx[1]
|
||||
- self.module.model.displayed_measurement.tdx[0]
|
||||
) * 1e-6
|
||||
y_weight = function.get_pulse_amplitude(event.duration, Decimal(resolution))
|
||||
#Append the last point to the end of the array
|
||||
# Append the last point to the end of the array
|
||||
y_weight = np.append(y_weight, y_weight[-1])
|
||||
|
||||
tdy_measurement = self.module.model.displayed_measurement.tdy * y_weight
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Module initialization file for the nqrduck-measurement module."""
|
||||
|
||||
from nqrduck.module.module import Module
|
||||
from .model import MeasurementModel
|
||||
from .view import MeasurementView
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Model for the measurement module."""
|
||||
|
||||
import logging
|
||||
from PyQt6.QtCore import pyqtSignal
|
||||
from nqrduck_spectrometer.measurement import Measurement
|
||||
|
@ -7,6 +8,7 @@ from nqrduck.helpers.validators import DuckFloatValidator, DuckIntValidator
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MeasurementModel(ModuleModel):
|
||||
"""Model for the measurement module.
|
||||
|
||||
|
@ -53,10 +55,12 @@ class MeasurementModel(ModuleModel):
|
|||
self.measurements = []
|
||||
self._displayed_measurement = None
|
||||
|
||||
self.validator_measurement_frequency = DuckFloatValidator(self, min_value=20.0, max_value=1000.0)
|
||||
self.validator_measurement_frequency = DuckFloatValidator(
|
||||
self, min_value=20.0, max_value=1000.0
|
||||
)
|
||||
self.validator_averages = DuckIntValidator(self, min_value=1, max_value=1e6)
|
||||
|
||||
self.measurement_frequency = 100.0 # MHz
|
||||
self.measurement_frequency = 100.0 # MHz
|
||||
self.averages = 1
|
||||
|
||||
@property
|
||||
|
@ -68,7 +72,7 @@ class MeasurementModel(ModuleModel):
|
|||
return self._view_mode
|
||||
|
||||
@view_mode.setter
|
||||
def view_mode(self, value : str):
|
||||
def view_mode(self, value: str):
|
||||
self._view_mode = value
|
||||
self.view_mode_changed.emit(value)
|
||||
|
||||
|
@ -78,11 +82,11 @@ class MeasurementModel(ModuleModel):
|
|||
return self._measurements
|
||||
|
||||
@measurements.setter
|
||||
def measurements(self, value : list[Measurement]):
|
||||
def measurements(self, value: list[Measurement]):
|
||||
self._measurements = value
|
||||
self.measurements_changed.emit(value)
|
||||
|
||||
def add_measurement(self, measurement : Measurement):
|
||||
def add_measurement(self, measurement: Measurement):
|
||||
"""Add a measurement to the list of measurements."""
|
||||
self.measurements.append(measurement)
|
||||
self.measurements_changed.emit(self.measurements)
|
||||
|
@ -97,7 +101,7 @@ class MeasurementModel(ModuleModel):
|
|||
return self._displayed_measurement
|
||||
|
||||
@displayed_measurement.setter
|
||||
def displayed_measurement(self, value : Measurement):
|
||||
def displayed_measurement(self, value: Measurement):
|
||||
self._displayed_measurement = value
|
||||
self.displayed_measurement_changed.emit(value)
|
||||
|
||||
|
@ -107,7 +111,7 @@ class MeasurementModel(ModuleModel):
|
|||
return self._measurement_frequency
|
||||
|
||||
@measurement_frequency.setter
|
||||
def measurement_frequency(self, value : float):
|
||||
def measurement_frequency(self, value: float):
|
||||
# Validator is used to check if the value is in the correct range.
|
||||
self._measurement_frequency = value
|
||||
self.measurement_frequency_changed.emit(value)
|
||||
|
@ -118,6 +122,6 @@ class MeasurementModel(ModuleModel):
|
|||
return self._averages
|
||||
|
||||
@averages.setter
|
||||
def averages(self, value : int):
|
||||
def averages(self, value: int):
|
||||
self._averages = value
|
||||
self.averages_changed.emit(value)
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
"""Signal processing options."""
|
||||
|
||||
import sympy
|
||||
from nqrduck_spectrometer.base_spectrometer_model import BaseSpectrometerModel
|
||||
from nqrduck_spectrometer.pulseparameters import FunctionOption, GaussianFunction, CustomFunction, Function
|
||||
from nqrduck_spectrometer.pulseparameters import (
|
||||
FunctionOption,
|
||||
GaussianFunction,
|
||||
CustomFunction,
|
||||
Function,
|
||||
)
|
||||
|
||||
# We implement the signal processing options as PulseParamterOptions because we can then easily use the automatic UI generation
|
||||
|
||||
|
||||
class FIDFunction(Function):
|
||||
"""The exponetial FID function."""
|
||||
|
||||
|
@ -29,6 +36,7 @@ class Apodization(BaseSpectrometerModel.PulseParameter):
|
|||
Attributes:
|
||||
APODIZATION_FUNCTIONS (str): The name of the apodization functions option.
|
||||
"""
|
||||
|
||||
APODIZATION_FUNCTIONS = "Apodization functions"
|
||||
|
||||
def __init__(self):
|
||||
|
@ -41,5 +49,3 @@ class Apodization(BaseSpectrometerModel.PulseParameter):
|
|||
[FIDFunction(), GaussianFunction(), CustomFunction()],
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""View for the measurement module."""
|
||||
|
||||
import logging
|
||||
import numpy as np
|
||||
from PyQt6.QtWidgets import QWidget, QDialog, QLabel, QVBoxLayout
|
||||
|
@ -11,6 +12,7 @@ from .widget import Ui_Form
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MeasurementView(ModuleView):
|
||||
"""View for the measurement module.
|
||||
|
||||
|
@ -24,6 +26,7 @@ class MeasurementView(ModuleView):
|
|||
_ui_form (Ui_Form): The form of the widget.
|
||||
measurement_dialog (MeasurementDialog): The dialog shown when the measurement is started.
|
||||
"""
|
||||
|
||||
def __init__(self, module):
|
||||
"""Initialize the measurement view."""
|
||||
super().__init__(module)
|
||||
|
@ -35,30 +38,59 @@ class MeasurementView(ModuleView):
|
|||
|
||||
# Initialize plotter
|
||||
self.init_plotter()
|
||||
logger.debug("Facecolor %s" % str(self._ui_form.plotter.canvas.ax.get_facecolor()))
|
||||
logger.debug(
|
||||
"Facecolor %s" % str(self._ui_form.plotter.canvas.ax.get_facecolor())
|
||||
)
|
||||
|
||||
# Measurement dialog
|
||||
self.measurement_dialog = self.MeasurementDialog()
|
||||
|
||||
# Connect signals
|
||||
self.module.model.displayed_measurement_changed.connect(self.update_displayed_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.buttonStart.clicked.connect(
|
||||
self.on_measurement_start_button_clicked
|
||||
)
|
||||
self._ui_form.fftButton.clicked.connect(self.module.controller.change_view_mode)
|
||||
|
||||
# Measurement settings controller
|
||||
self._ui_form.frequencyEdit.textChanged.connect(lambda: self.module.controller.set_frequency(self._ui_form.frequencyEdit.text()))
|
||||
self._ui_form.averagesEdit.textChanged.connect(lambda: self.module.controller.set_averages(self._ui_form.averagesEdit.text()))
|
||||
self._ui_form.frequencyEdit.textChanged.connect(
|
||||
lambda: self.module.controller.set_frequency(
|
||||
self._ui_form.frequencyEdit.text()
|
||||
)
|
||||
)
|
||||
self._ui_form.averagesEdit.textChanged.connect(
|
||||
lambda: self.module.controller.set_averages(
|
||||
self._ui_form.averagesEdit.text()
|
||||
)
|
||||
)
|
||||
|
||||
# Update fields
|
||||
self._ui_form.frequencyEdit.textChanged.connect(lambda: self.update_input_widgets(self._ui_form.frequencyEdit, self.module.model.validator_measurement_frequency ))
|
||||
self._ui_form.averagesEdit.textChanged.connect(lambda: self.update_input_widgets(self._ui_form.averagesEdit, self.module.model.validator_averages))
|
||||
self._ui_form.frequencyEdit.textChanged.connect(
|
||||
lambda: self.update_input_widgets(
|
||||
self._ui_form.frequencyEdit,
|
||||
self.module.model.validator_measurement_frequency,
|
||||
)
|
||||
)
|
||||
self._ui_form.averagesEdit.textChanged.connect(
|
||||
lambda: self.update_input_widgets(
|
||||
self._ui_form.averagesEdit, self.module.model.validator_averages
|
||||
)
|
||||
)
|
||||
|
||||
self.module.controller.set_frequency_failure.connect(self.on_set_frequency_failure)
|
||||
self.module.controller.set_averages_failure.connect(self.on_set_averages_failure)
|
||||
self.module.controller.set_frequency_failure.connect(
|
||||
self.on_set_frequency_failure
|
||||
)
|
||||
self.module.controller.set_averages_failure.connect(
|
||||
self.on_set_averages_failure
|
||||
)
|
||||
|
||||
self._ui_form.apodizationButton.clicked.connect(self.module.controller.show_apodization_dialog)
|
||||
self._ui_form.apodizationButton.clicked.connect(
|
||||
self.module.controller.show_apodization_dialog
|
||||
)
|
||||
|
||||
# Add logos
|
||||
self._ui_form.buttonStart.setIcon(Logos.Play_16x16())
|
||||
|
@ -72,8 +104,12 @@ class MeasurementView(ModuleView):
|
|||
self._ui_form.importButton.setIconSize(self._ui_form.importButton.size())
|
||||
|
||||
# Connect measurement save and load buttons
|
||||
self._ui_form.exportButton.clicked.connect(self.on_measurement_save_button_clicked)
|
||||
self._ui_form.importButton.clicked.connect(self.on_measurement_load_button_clicked)
|
||||
self._ui_form.exportButton.clicked.connect(
|
||||
self.on_measurement_save_button_clicked
|
||||
)
|
||||
self._ui_form.importButton.clicked.connect(
|
||||
self.on_measurement_load_button_clicked
|
||||
)
|
||||
|
||||
# Make title label bold
|
||||
self._ui_form.titleLabel.setStyleSheet("font-weight: bold;")
|
||||
|
@ -101,7 +137,7 @@ class MeasurementView(ModuleView):
|
|||
plotter.canvas.ax.set_title("Measurement data - Time domain")
|
||||
plotter.canvas.ax.grid()
|
||||
|
||||
def change_to_fft_view(self)-> None:
|
||||
def change_to_fft_view(self) -> None:
|
||||
"""Change plotter to frequency domain view."""
|
||||
plotter = self._ui_form.plotter
|
||||
self._ui_form.fftButton.setText("iFFT")
|
||||
|
@ -127,11 +163,16 @@ class MeasurementView(ModuleView):
|
|||
x = self.module.model.displayed_measurement.tdx
|
||||
y = self.module.model.displayed_measurement.tdy
|
||||
|
||||
self._ui_form.plotter.canvas.ax.plot(x, y.real, label="Real", linestyle="-", alpha=0.35, color="red")
|
||||
self._ui_form.plotter.canvas.ax.plot(x, y.imag, label="Imaginary", linestyle="-", alpha=0.35, color="green")
|
||||
self._ui_form.plotter.canvas.ax.plot(
|
||||
x, y.real, label="Real", linestyle="-", alpha=0.35, color="red"
|
||||
)
|
||||
self._ui_form.plotter.canvas.ax.plot(
|
||||
x, y.imag, label="Imaginary", linestyle="-", alpha=0.35, color="green"
|
||||
)
|
||||
# Magnitude
|
||||
self._ui_form.plotter.canvas.ax.plot(x, np.abs(y), label="Magnitude", color="blue")
|
||||
|
||||
self._ui_form.plotter.canvas.ax.plot(
|
||||
x, np.abs(y), label="Magnitude", color="blue"
|
||||
)
|
||||
|
||||
# Add legend
|
||||
self._ui_form.plotter.canvas.ax.legend()
|
||||
|
@ -163,7 +204,9 @@ class MeasurementView(ModuleView):
|
|||
"""Slot for when the measurement save button is clicked."""
|
||||
logger.debug("Measurement save button clicked.")
|
||||
|
||||
file_manager = self.QFileManager(self.module.model.FILE_EXTENSION, parent=self.widget)
|
||||
file_manager = self.QFileManager(
|
||||
self.module.model.FILE_EXTENSION, parent=self.widget
|
||||
)
|
||||
file_name = file_manager.saveFileDialog()
|
||||
if file_name:
|
||||
self.module.controller.save_measurement(file_name)
|
||||
|
@ -173,7 +216,9 @@ class MeasurementView(ModuleView):
|
|||
"""Slot for when the measurement load button is clicked."""
|
||||
logger.debug("Measurement load button clicked.")
|
||||
|
||||
file_manager = self.QFileManager(self.module.model.FILE_EXTENSION, parent=self.widget)
|
||||
file_manager = self.QFileManager(
|
||||
self.module.model.FILE_EXTENSION, parent=self.widget
|
||||
)
|
||||
file_name = file_manager.loadFileDialog()
|
||||
if file_name:
|
||||
self.module.controller.load_measurement(file_name)
|
||||
|
@ -186,20 +231,13 @@ class MeasurementView(ModuleView):
|
|||
widget (QLineEdit): The widget to update.
|
||||
validator (QValidator): The validator to use for the widget.
|
||||
"""
|
||||
if (
|
||||
validator.validate(widget.text(), 0)
|
||||
== QValidator.State.Acceptable
|
||||
):
|
||||
if validator.validate(widget.text(), 0) == QValidator.State.Acceptable:
|
||||
widget.setStyleSheet("QLineEdit { background-color: white; }")
|
||||
elif (
|
||||
validator.validate(widget.text(), 0)
|
||||
== QValidator.State.Intermediate
|
||||
):
|
||||
elif validator.validate(widget.text(), 0) == QValidator.State.Intermediate:
|
||||
widget.setStyleSheet("QLineEdit { background-color: yellow; }")
|
||||
else:
|
||||
widget.setStyleSheet("QLineEdit { background-color: red; }")
|
||||
|
||||
|
||||
class MeasurementDialog(QDialog):
|
||||
"""This Dialog is shown when the measurement is started and therefore blocks the main window.
|
||||
|
||||
|
@ -208,6 +246,7 @@ class MeasurementView(ModuleView):
|
|||
Attributes:
|
||||
finished (bool): True if the spinner movie is finished.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the dialog."""
|
||||
super().__init__()
|
||||
|
@ -216,7 +255,7 @@ class MeasurementView(ModuleView):
|
|||
self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||
|
||||
self.message_label = ("Measuring...")
|
||||
self.message_label = "Measuring..."
|
||||
self.spinner_movie = DuckAnimations.DuckKick128x128()
|
||||
self.spinner_label = QLabel(self)
|
||||
self.spinner_label.setMovie(self.spinner_movie)
|
||||
|
@ -239,4 +278,3 @@ class MeasurementView(ModuleView):
|
|||
continue
|
||||
self.spinner_movie.stop()
|
||||
super().hide()
|
||||
|
||||
|
|
Loading…
Reference in a new issue