Added basic apodization.

This commit is contained in:
jupfi 2024-01-03 15:25:31 +01:00
parent 6fef0c2753
commit 2e8084aae2
7 changed files with 114 additions and 22 deletions

View file

@ -26,7 +26,10 @@ classifiers = [
dependencies = [ dependencies = [
"matplotlib", "matplotlib",
"pyqt6", "pyqt6",
"sympy",
"NQRduck", "NQRduck",
"nqrduck-pulseprogrammer",
"nqrduck-spectrometer",
] ]
[project.entry-points."nqrduck"] [project.entry-points."nqrduck"]

View file

@ -1,7 +1,12 @@
import logging import logging
import json import json
import numpy as np
from decimal import Decimal
from PyQt6.QtCore import pyqtSlot, pyqtSignal from PyQt6.QtCore import pyqtSlot, pyqtSignal
from PyQt6.QtWidgets import QWidget import nqrduck.helpers.signalprocessing as sp
from nqrduck_pulseprogrammer.view import OptionsDialog
from nqrduck_spectrometer.pulsesequence import PulseSequence
from .signalprocessing_options import Apodization
from nqrduck.module.module_controller import ModuleController from nqrduck.module.module_controller import ModuleController
from nqrduck_spectrometer.measurement import Measurement from nqrduck_spectrometer.measurement import Measurement
@ -144,3 +149,51 @@ class MeasurementController(ModuleController):
self.module.nqrduck_signal.emit( self.module.nqrduck_signal.emit(
"notification", ["Error", "File is not a valid measurement file."] "notification", ["Error", "File is not a valid measurement file."]
) )
def show_apodization_dialog(self) -> None:
"""Show apodization dialog."""
logger.debug("Showing apodization dialog.")
# First we check if there is a measurement.
if not self.module.model.displayed_measurement:
logger.debug("No measurement to apodize.")
self.module.nqrduck_signal.emit(
"notification", ["Error", "No measurement to apodize."]
)
return
# 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.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())
option.set_value(function())
# Get the function from the Apodization function
function = parameter.get_option_by_name(Apodization.APODIZATION_FUNCTIONS).value
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
y_weight = function.get_pulse_amplitude(event.duration, Decimal(resolution))
#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
measurement = Measurement(
self.module.model.displayed_measurement.tdx,
tdy_measurement,
target_frequency=self.module.model.displayed_measurement.target_frequency,
IF_frequency=self.module.model.displayed_measurement.IF_frequency,
)
self.module.model.displayed_measurement = measurement
self.module.model.add_measurement(measurement)

View file

@ -20,6 +20,7 @@ class MeasurementModel(ModuleModel):
super().__init__(module) super().__init__(module)
self.view_mode = self.TIME_VIEW self.view_mode = self.TIME_VIEW
self.measurements = [] self.measurements = []
self._displayed_measurement = None
@property @property
def view_mode(self): def view_mode(self):

View file

@ -116,28 +116,28 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_2"> <widget class="QPushButton" name="apodizationButton">
<property name="text"> <property name="text">
<string>Apodization</string> <string>Apodization</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton"> <widget class="QPushButton" name="baselineButton">
<property name="text"> <property name="text">
<string>Baseline Correction</string> <string>Baseline Correction</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_3"> <widget class="QPushButton" name="peakButton">
<property name="text"> <property name="text">
<string>Peak-Picking</string> <string>Peak-Picking</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_4"> <widget class="QPushButton" name="fittingButton">
<property name="text"> <property name="text">
<string>Fitting</string> <string>Fitting</string>
</property> </property>

View file

@ -0,0 +1,34 @@
import sympy
from nqrduck_spectrometer.base_spectrometer_model import BaseSpectrometerModel
from nqrduck_spectrometer.pulseparameters import FunctionOption, NumericOption, 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."""
name = "FID"
def __init__(self) -> None:
expr = sympy.sympify("exp( -x / T2star )")
super().__init__(expr)
self.start_x = 0
self.end_x = 30
self.add_parameter(Function.Parameter("T2star (microseconds)", "T2star", 10))
class Apodization(BaseSpectrometerModel.PulseParameter):
APODIZATION_FUNCTIONS = "Apodization functions"
def __init__(self):
super().__init__("Apodization")
self.add_option(
FunctionOption(
self.APODIZATION_FUNCTIONS,
[FIDFunction(), GaussianFunction(), CustomFunction()],
),
)

View file

@ -60,6 +60,8 @@ class MeasurementView(ModuleView):
self.module.controller.set_frequency_failure.connect(self.on_set_frequency_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.module.controller.set_averages_failure.connect(self.on_set_averages_failure)
self._ui_form.apodizationButton.clicked.connect(self.module.controller.show_apodization_dialog)
# Call validator for buttonStart # Call validator for buttonStart
# Add logos # Add logos
@ -226,4 +228,3 @@ class MeasurementView(ModuleView):
self.spinner_movie.stop() self.spinner_movie.stop()
super().hide() super().hide()

View file

@ -68,18 +68,18 @@ class Ui_Form(object):
self.spLabel.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.spLabel.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.spLabel.setObjectName("spLabel") self.spLabel.setObjectName("spLabel")
self.settingsLayout.addWidget(self.spLabel) self.settingsLayout.addWidget(self.spLabel)
self.pushButton_2 = QtWidgets.QPushButton(parent=Form) self.apodizationButton = QtWidgets.QPushButton(parent=Form)
self.pushButton_2.setObjectName("pushButton_2") self.apodizationButton.setObjectName("apodizationButton")
self.settingsLayout.addWidget(self.pushButton_2) self.settingsLayout.addWidget(self.apodizationButton)
self.pushButton = QtWidgets.QPushButton(parent=Form) self.baselineButton = QtWidgets.QPushButton(parent=Form)
self.pushButton.setObjectName("pushButton") self.baselineButton.setObjectName("baselineButton")
self.settingsLayout.addWidget(self.pushButton) self.settingsLayout.addWidget(self.baselineButton)
self.pushButton_3 = QtWidgets.QPushButton(parent=Form) self.peakButton = QtWidgets.QPushButton(parent=Form)
self.pushButton_3.setObjectName("pushButton_3") self.peakButton.setObjectName("peakButton")
self.settingsLayout.addWidget(self.pushButton_3) self.settingsLayout.addWidget(self.peakButton)
self.pushButton_4 = QtWidgets.QPushButton(parent=Form) self.fittingButton = QtWidgets.QPushButton(parent=Form)
self.pushButton_4.setObjectName("pushButton_4") self.fittingButton.setObjectName("fittingButton")
self.settingsLayout.addWidget(self.pushButton_4) self.settingsLayout.addWidget(self.fittingButton)
self.spsettingsButton = QtWidgets.QPushButton(parent=Form) self.spsettingsButton = QtWidgets.QPushButton(parent=Form)
self.spsettingsButton.setObjectName("spsettingsButton") self.spsettingsButton.setObjectName("spsettingsButton")
self.settingsLayout.addWidget(self.spsettingsButton) self.settingsLayout.addWidget(self.spsettingsButton)
@ -137,10 +137,10 @@ class Ui_Form(object):
self.frequencyunitLabel.setText(_translate("Form", "MHz")) self.frequencyunitLabel.setText(_translate("Form", "MHz"))
self.buttonStart.setText(_translate("Form", "Start Measurement")) self.buttonStart.setText(_translate("Form", "Start Measurement"))
self.spLabel.setText(_translate("Form", "Signal Processing")) self.spLabel.setText(_translate("Form", "Signal Processing"))
self.pushButton_2.setText(_translate("Form", "Apodization")) self.apodizationButton.setText(_translate("Form", "Apodization"))
self.pushButton.setText(_translate("Form", "Baseline Correction")) self.baselineButton.setText(_translate("Form", "Baseline Correction"))
self.pushButton_3.setText(_translate("Form", "Peak-Picking")) self.peakButton.setText(_translate("Form", "Peak-Picking"))
self.pushButton_4.setText(_translate("Form", "Fitting")) self.fittingButton.setText(_translate("Form", "Fitting"))
self.spsettingsButton.setText(_translate("Form", "Settings")) self.spsettingsButton.setText(_translate("Form", "Settings"))
self.exportButton.setText(_translate("Form", "Export Measurement")) self.exportButton.setText(_translate("Form", "Export Measurement"))
self.importButton.setText(_translate("Form", "Import Measurement")) self.importButton.setText(_translate("Form", "Import Measurement"))