Started implementation of broadband acquisition.

This commit is contained in:
jupfi 2023-07-19 12:27:18 +02:00
parent 5e5c2da12a
commit e8e55682c9
5 changed files with 216 additions and 42 deletions

View file

@ -1,17 +1,17 @@
import logging import logging
from PyQt6.QtCore import pyqtSlot, pyqtSignal import numpy as np
from PyQt6.QtCore import pyqtSlot, pyqtSignal, QThread
from PyQt6.QtWidgets import QApplication
from nqrduck_spectrometer.measurement import Measurement from nqrduck_spectrometer.measurement import Measurement
from nqrduck.module.module_controller import ModuleController from nqrduck.module.module_controller import ModuleController
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class BroadbandController(ModuleController): class BroadbandController(ModuleController):
MIN_FREQUENCY = 30.0
MAX_FREQUENCY = 200.0
start_measurement = pyqtSignal()
start_broadband_measurement = pyqtSignal()
set_averages_failure = pyqtSignal() set_averages_failure = pyqtSignal()
set_frequency_step_failure = pyqtSignal()
def __init__(self, module): def __init__(self, module):
super().__init__(module) super().__init__(module)
@ -19,18 +19,23 @@ class BroadbandController(ModuleController):
@pyqtSlot(str, object) @pyqtSlot(str, object)
def process_signals(self, key: str, value: Measurement): def process_signals(self, key: str, value: Measurement):
if key == "measurement_data": if key == "measurement_data" and self.module.model.current_broadcast_measurement is not None:
logger.debug("Received single measurement.") logger.debug("Received single measurement.")
self.module.model.single_measurement = value self.module.model.current_broadcast_measurement.add_measurement(value)
elif key == "failure_set_averages" and value == self.module.view._ui_form.averagesEdit.text(): elif key == "failure_set_averages" and value == self.module.view._ui_form.averagesEdit.text():
logger.debug("Received set averages failure.") logger.debug("Received set averages failure.")
self.set_averages_failure.emit() self.set_averages_failure.emit()
@pyqtSlot(str) @pyqtSlot(str)
def set_frequency(self, value): def set_frequency(self, value):
logger.debug("Setting frequency to: " + value) try:
self.module.nqrduck_signal.emit("set_frequency", value) logger.debug("Setting frequency to: " + float(value))
self.module.nqrduck_signal.emit("set_frequency", value)
except ValueError:
self.set_averages_failure.emit()
self.set_frequency_step_failure.emit()
@pyqtSlot(str) @pyqtSlot(str)
def set_averages(self, value): def set_averages(self, value):
@ -40,20 +45,62 @@ class BroadbandController(ModuleController):
@pyqtSlot(str) @pyqtSlot(str)
def change_start_frequency(self, value): def change_start_frequency(self, value):
value = float(value) value = float(value)
if value > self.MIN_FREQUENCY: if value > self.module.model.MIN_FREQUENCY:
self.module._model.start_frequency = value self.module.model.start_frequency = value * 1e6
else: else:
self.module._model.start_frequency = self.MIN_FREQUENCY self.module.model.start_frequency = self.module.model.MIN_FREQUENCY
@pyqtSlot(str) @pyqtSlot(str)
def change_stop_frequency(self, value): def change_stop_frequency(self, value):
value = float(value) value = float(value)
if value < self.MAX_FREQUENCY: if value < self.module.model.MAX_FREQUENCY:
self.module._model.stop_frequency = value self.module._model.stop_frequency = value * 1e6
else: else:
self.module._model.stop_frequency = self.MAX_FREQUENCY self.module._model.stop_frequency = self.module.model.MAX_FREQUENCY
@pyqtSlot(str)
def change_frequency_step(self, value):
try:
logger.debug("Changing frequency step to: " + value)
value = float(value) * 1e6
if value > 0:
self.module.model.frequency_step = value
except ValueError:
logger.debug("Invalid frequency step value")
@pyqtSlot() @pyqtSlot()
def start_measurement(self): def start_broadband_measurement(self):
logger.debug("Start measurement clicked") logger.debug("Start measurement clicked")
self.module.nqrduck_signal.emit("start_measurement", None) # Create a list of different frequency values that we need for our broadband measurement
start_frequency = self.module.model.start_frequency
stop_frequency = self.module.model.stop_frequency
frequency_step = self.module.model.frequency_step
frequency_list = np.arange(start_frequency, stop_frequency + frequency_step, frequency_step)
logger.debug("Frequency list: " + str(frequency_list))
# Create a new broadband measurement object
self.module.model.current_broadcast_measurement = self.module.model.BroadbandMeasurement(frequency_list)
self.module.model.current_broadcast_measurement.received_measurement.connect(self.module.view.on_broadband_measurement_added)
self.module.model.current_broadcast_measurement.received_measurement.connect(self.on_broadband_measurement_added)
# Start the first measurement
self.module.nqrduck_signal.emit("set_frequency", str(start_frequency))
self.module.nqrduck_signal.emit("start_measurement", None)
@pyqtSlot()
def on_broadband_measurement_added(self):
"""This slot is called when a single measurement is added to the broadband measurement.
It then checks if there are more frequencies to measure and if so, starts the next measurement.
Furthermore it updates the plots.
"""
logger.debug("Broadband measurement added.")
# Check if there are more frequencies to measure
if not self.module.model.current_broadcast_measurement.is_complete():
# Get the next frequency to measure
next_frequency = self.module.model.current_broadcast_measurement.get_next_measurement_frequency()
logger.debug("Next frequency: " + str(next_frequency))
# Start the next measurement
self.module.nqrduck_signal.emit("set_frequency", str(next_frequency))
self.module.nqrduck_signal.emit("start_measurement", None)

View file

@ -1,11 +1,26 @@
from PyQt6.QtCore import pyqtSignal import logging
from collections import OrderedDict
from PyQt6.QtWidgets import QApplication
from PyQt6.QtCore import pyqtSignal, QObject
from nqrduck.module.module_model import ModuleModel from nqrduck.module.module_model import ModuleModel
logger = logging.getLogger(__name__)
class BroadbandModel(ModuleModel): class BroadbandModel(ModuleModel):
MIN_FREQUENCY = 30.0
MAX_FREQUENCY = 200.0
DEFAULT_FREQUENCY_STEP = 0.1
start_frequency_changed = pyqtSignal(float) start_frequency_changed = pyqtSignal(float)
stop_frequency_changed = pyqtSignal(float) stop_frequency_changed = pyqtSignal(float)
def __init__(self, module) -> None:
super().__init__(module)
self.start_frequency = self.MIN_FREQUENCY
self.stop_frequency = self.MAX_FREQUENCY
self.DEFAULT_FREQUENCY_STEP = self.DEFAULT_FREQUENCY_STEP
self.current_broadcast_measurement = None
@property @property
def start_frequency(self): def start_frequency(self):
return self._start_frequency return self._start_frequency
@ -23,3 +38,78 @@ class BroadbandModel(ModuleModel):
def stop_frequency(self, value): def stop_frequency(self, value):
self._stop_frequency = value self._stop_frequency = value
self.stop_frequency_changed.emit(value) self.stop_frequency_changed.emit(value)
@property
def frequency_step(self):
return self._frequency_step
@frequency_step.setter
def frequency_step(self, value):
self._frequency_step = value
@property
def current_broadcast_measurement(self):
return self._current_broadcast_measurement
@current_broadcast_measurement.setter
def current_broadcast_measurement(self, value):
self._current_broadcast_measurement = value
class BroadbandMeasurement(QObject):
"""This class represents a single broadband measurement."""
received_measurement = pyqtSignal()
def __init__(self, frequencies) -> None:
super().__init__()
self._single_frequency_measurements = OrderedDict()
for frequency in frequencies:
self._single_frequency_measurements[frequency] = None
def add_measurement(self, measurement):
"""This method adds a single measurement to the broadband measurement.
Args:
measurement (Measurement): The measurement object."""
logger.debug("Adding measurement to broadband measurement at frequency: %s" % str(measurement.target_frequency))
self._single_frequency_measurements[measurement.target_frequency] = measurement
self.received_measurement.emit()
QApplication.processEvents()
def is_complete(self):
"""This method checks if all frequencies have been measured.
Returns:
bool: True if all frequencies have been measured, False otherwise."""
for measurement in self._single_frequency_measurements.values():
if measurement is None:
return False
return True
def get_next_measurement_frequency(self):
"""This method returns the next frequency that has to be measured.
Returns:
float: The next frequency that has to be measured."""
for frequency, measurement in self._single_frequency_measurements.items():
if measurement is None:
return frequency
def get_last_completed_measurement(self):
""" This method returns the last completed measurement.
Returns:
Measurement: The last completed measurement."""
for frequency, measurement in self._single_frequency_measurements.items():
if measurement is not None:
return measurement
@property
def single_frequency_measurements(self):
"""This property contains the dict of all frequencies that have to be measured."""
return self._single_frequency_measurements
@single_frequency_measurements.setter
def single_frequency_measurements(self, value):
self._single_frequency_measurements = value

View file

@ -76,9 +76,9 @@
</widget> </widget>
</item> </item>
<item row="2" column="2"> <item row="2" column="2">
<widget class="QLineEdit" name="frequency_stepField"> <widget class="QLineEdit" name="frequencystepEdit">
<property name="text"> <property name="text">
<string>0.1</string> <string/>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -91,7 +91,7 @@
<enum>Qt::LeftToRight</enum> <enum>Qt::LeftToRight</enum>
</property> </property>
<property name="text"> <property name="text">
<string>50.0</string> <string/>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -108,7 +108,7 @@
<item row="1" column="2"> <item row="1" column="2">
<widget class="QLineEdit" name="stop_frequencyField"> <widget class="QLineEdit" name="stop_frequencyField">
<property name="text"> <property name="text">
<string>70.0</string> <string/>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -132,7 +132,7 @@
<item row="3" column="2"> <item row="3" column="2">
<widget class="QLineEdit" name="averagesEdit"> <widget class="QLineEdit" name="averagesEdit">
<property name="text"> <property name="text">
<string>1000</string> <string/>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>

View file

@ -1,6 +1,6 @@
import logging import logging
from PyQt6.QtCore import pyqtSlot, pyqtSignal from PyQt6.QtCore import pyqtSlot, pyqtSignal
from PyQt6.QtWidgets import QWidget, QMessageBox from PyQt6.QtWidgets import QWidget, QMessageBox, QApplication
from nqrduck.module.module_view import ModuleView from nqrduck.module.module_view import ModuleView
from .widget import Ui_Form from .widget import Ui_Form
@ -10,7 +10,7 @@ logger = logging.getLogger(__name__)
class BroadbandView(ModuleView): class BroadbandView(ModuleView):
start_measurement = pyqtSignal() start_broadband_measurement = pyqtSignal()
def __init__(self, module): def __init__(self, module):
super().__init__(module) super().__init__(module)
@ -28,25 +28,32 @@ class BroadbandView(ModuleView):
def _connect_signals(self) -> None: def _connect_signals(self) -> None:
self._ui_form.start_frequencyField.editingFinished.connect( self._ui_form.start_frequencyField.editingFinished.connect(
lambda: self.module._controller.change_start_frequency( lambda: self.module.controller.change_start_frequency(
self._ui_form.start_frequencyField.text() self._ui_form.start_frequencyField.text()
) )
) )
self._ui_form.stop_frequencyField.editingFinished.connect( self._ui_form.stop_frequencyField.editingFinished.connect(
lambda: self.module._controller.change_stop_frequency( lambda: self.module.controller.change_stop_frequency(
self._ui_form.stop_frequencyField.text() self._ui_form.stop_frequencyField.text()
) )
) )
self.module._model.start_frequency_changed.connect(self.on_start_frequency_change) self._ui_form.frequencystepEdit.editingFinished.connect(
self.module._model.stop_frequency_changed.connect(self.on_stop_frequency_change) lambda: self.module.controller.change_frequency_step(
self._ui_form.frequencystepEdit.text()
)
)
self.module.model.start_frequency_changed.connect(self.on_start_frequency_change)
self.module.model.stop_frequency_changed.connect(self.on_stop_frequency_change)
self._ui_form.start_measurementButton.clicked.connect(lambda: self._start_measurement_clicked()) self._ui_form.start_measurementButton.clicked.connect(self._start_measurement_clicked)
self.start_measurement.connect(lambda: self.module._controller.start_measurement()) self.start_broadband_measurement.connect(self.module._controller.start_broadband_measurement)
self._ui_form.averagesEdit.editingFinished.connect(lambda: self.on_editing_finished(self._ui_form.averagesEdit.text())) self._ui_form.averagesEdit.editingFinished.connect(lambda: self.on_editing_finished(self._ui_form.averagesEdit.text()))
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.module.controller.set_frequency_step_failure.connect(self.on_set_frequency_step_failure)
def _start_measurement_clicked(self): def _start_measurement_clicked(self):
# Create a QMessageBox object # Create a QMessageBox object
@ -62,7 +69,7 @@ class BroadbandView(ModuleView):
# Process the user's choice # Process the user's choice
if choice == QMessageBox.StandardButton.Yes: if choice == QMessageBox.StandardButton.Yes:
self.start_measurement.emit() self.start_broadband_measurement.emit()
def init_plots(self): def init_plots(self):
@ -89,19 +96,23 @@ class BroadbandView(ModuleView):
@pyqtSlot(float) @pyqtSlot(float)
def on_start_frequency_change(self, start_frequency): def on_start_frequency_change(self, start_frequency):
logger.debug("Adjusting view to new start frequency: " + str(start_frequency))
self._ui_form.broadbandPlot.canvas.ax.set_xlim(left=start_frequency) self._ui_form.broadbandPlot.canvas.ax.set_xlim(left=start_frequency)
self._ui_form.broadbandPlot.canvas.draw() self._ui_form.broadbandPlot.canvas.draw()
self._ui_form.broadbandPlot.canvas.flush_events() self._ui_form.broadbandPlot.canvas.flush_events()
self._ui_form.start_frequencyField.setText(str(start_frequency* 1e-6))
@pyqtSlot(float) @pyqtSlot(float)
def on_stop_frequency_change(self, stop_frequency): def on_stop_frequency_change(self, stop_frequency):
logger.debug("Adjusting view to new stop frequency: " + str(stop_frequency))
self._ui_form.broadbandPlot.canvas.ax.set_xlim(right=stop_frequency) self._ui_form.broadbandPlot.canvas.ax.set_xlim(right=stop_frequency)
self._ui_form.broadbandPlot.canvas.draw() self._ui_form.broadbandPlot.canvas.draw()
self._ui_form.broadbandPlot.canvas.flush_events() self._ui_form.broadbandPlot.canvas.flush_events()
self._ui_form.stop_frequencyField.setText(str(stop_frequency* 1e-6))
@pyqtSlot() @pyqtSlot()
def on_editing_finished(self, value): def on_editing_finished(self, value):
logger.debug("Averages editing finished.") logger.debug("Editing finished by.")
self.sender().setStyleSheet("") self.sender().setStyleSheet("")
if self.sender() == self._ui_form.averagesEdit: if self.sender() == self._ui_form.averagesEdit:
self.module.controller.set_averages(value) self.module.controller.set_averages(value)
@ -109,4 +120,30 @@ class BroadbandView(ModuleView):
@pyqtSlot() @pyqtSlot()
def on_set_averages_failure(self): def on_set_averages_failure(self):
logger.debug("Set averages failure.") logger.debug("Set averages failure.")
self._ui_form.averagesEdit.setStyleSheet("border: 1px solid red;") self._ui_form.averagesEdit.setStyleSheet("border: 1px solid red;")
@pyqtSlot()
def on_set_frequency_step_failure(self):
logger.debug("Set frequency step failure.")
self._ui_form.frequencystepEdit.setStyleSheet("border: 1px solid red;")
@pyqtSlot()
def on_broadband_measurement_added(self):
# Get last measurement from the broadband measurement object that is not None
logger.debug("Updating broadband plot.")
measurement = self.module.model.current_broadcast_measurement.get_last_completed_measurement()
td_plotter = self._ui_form.time_domainPlot.canvas.ax
fd_plotter = self._ui_form.frequency_domainPlot.canvas.ax
td_plotter.clear()
fd_plotter.clear()
td_plotter.plot(measurement.tdx, measurement.tdy)
fd_plotter.plot(measurement.fdx, measurement.fdy)
self._ui_form.time_domainPlot.canvas.draw()
self._ui_form.frequency_domainPlot.canvas.draw()
QApplication.processEvents()

View file

@ -49,12 +49,14 @@ class Ui_Form(object):
self.label_3 = QtWidgets.QLabel(parent=Form) self.label_3 = QtWidgets.QLabel(parent=Form)
self.label_3.setObjectName("label_3") self.label_3.setObjectName("label_3")
self.gridLayout_3.addWidget(self.label_3, 1, 0, 1, 1) self.gridLayout_3.addWidget(self.label_3, 1, 0, 1, 1)
self.frequency_stepField = QtWidgets.QLineEdit(parent=Form) self.frequencystepEdit = QtWidgets.QLineEdit(parent=Form)
self.frequency_stepField.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter) self.frequencystepEdit.setText("")
self.frequency_stepField.setObjectName("frequency_stepField") self.frequencystepEdit.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.gridLayout_3.addWidget(self.frequency_stepField, 2, 2, 1, 1) self.frequencystepEdit.setObjectName("frequencystepEdit")
self.gridLayout_3.addWidget(self.frequencystepEdit, 2, 2, 1, 1)
self.start_frequencyField = QtWidgets.QLineEdit(parent=Form) self.start_frequencyField = QtWidgets.QLineEdit(parent=Form)
self.start_frequencyField.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) self.start_frequencyField.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight)
self.start_frequencyField.setText("")
self.start_frequencyField.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter) self.start_frequencyField.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.start_frequencyField.setObjectName("start_frequencyField") self.start_frequencyField.setObjectName("start_frequencyField")
self.gridLayout_3.addWidget(self.start_frequencyField, 0, 2, 1, 1) self.gridLayout_3.addWidget(self.start_frequencyField, 0, 2, 1, 1)
@ -62,6 +64,7 @@ class Ui_Form(object):
self.label.setObjectName("label") self.label.setObjectName("label")
self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1) self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1)
self.stop_frequencyField = QtWidgets.QLineEdit(parent=Form) self.stop_frequencyField = QtWidgets.QLineEdit(parent=Form)
self.stop_frequencyField.setText("")
self.stop_frequencyField.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter) self.stop_frequencyField.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.stop_frequencyField.setObjectName("stop_frequencyField") self.stop_frequencyField.setObjectName("stop_frequencyField")
self.gridLayout_3.addWidget(self.stop_frequencyField, 1, 2, 1, 1) self.gridLayout_3.addWidget(self.stop_frequencyField, 1, 2, 1, 1)
@ -72,6 +75,7 @@ class Ui_Form(object):
self.label_7.setObjectName("label_7") self.label_7.setObjectName("label_7")
self.gridLayout_3.addWidget(self.label_7, 3, 0, 1, 1) self.gridLayout_3.addWidget(self.label_7, 3, 0, 1, 1)
self.averagesEdit = QtWidgets.QLineEdit(parent=Form) self.averagesEdit = QtWidgets.QLineEdit(parent=Form)
self.averagesEdit.setText("")
self.averagesEdit.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter) self.averagesEdit.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.averagesEdit.setObjectName("averagesEdit") self.averagesEdit.setObjectName("averagesEdit")
self.gridLayout_3.addWidget(self.averagesEdit, 3, 2, 1, 1) self.gridLayout_3.addWidget(self.averagesEdit, 3, 2, 1, 1)
@ -177,13 +181,9 @@ class Ui_Form(object):
self.label_5.setText(_translate("Form", "Frequency Step:")) self.label_5.setText(_translate("Form", "Frequency Step:"))
self.label_2.setText(_translate("Form", "MHz")) self.label_2.setText(_translate("Form", "MHz"))
self.label_3.setText(_translate("Form", "Stop Frequency:")) self.label_3.setText(_translate("Form", "Stop Frequency:"))
self.frequency_stepField.setText(_translate("Form", "0.1"))
self.start_frequencyField.setText(_translate("Form", "50.0"))
self.label.setText(_translate("Form", "Start Frequency:")) self.label.setText(_translate("Form", "Start Frequency:"))
self.stop_frequencyField.setText(_translate("Form", "70.0"))
self.label_4.setText(_translate("Form", "MHz")) self.label_4.setText(_translate("Form", "MHz"))
self.label_7.setText(_translate("Form", "Averages:")) self.label_7.setText(_translate("Form", "Averages:"))
self.averagesEdit.setText(_translate("Form", "1000"))
self.start_measurementButton.setText(_translate("Form", "Start Measurement")) self.start_measurementButton.setText(_translate("Form", "Start Measurement"))
self.label_10.setText(_translate("Form", "Sequence Settings:")) self.label_10.setText(_translate("Form", "Sequence Settings:"))
self.label_9.setText(_translate("Form", "Info Box:")) self.label_9.setText(_translate("Form", "Info Box:"))