Formatting.

This commit is contained in:
jupfi 2024-03-30 16:27:23 +01:00
parent 1e6c4d3083
commit d3594230a0
5 changed files with 162 additions and 91 deletions

View file

@ -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

View file

@ -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

View file

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

View file

@ -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()],
),
)

View file

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