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
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.module.module_controller import ModuleController
logger = logging.getLogger(__name__)
class BroadbandController(ModuleController):
MIN_FREQUENCY = 30.0
MAX_FREQUENCY = 200.0
start_measurement = pyqtSignal()
start_broadband_measurement = pyqtSignal()
set_averages_failure = pyqtSignal()
set_frequency_step_failure = pyqtSignal()
def __init__(self, module):
super().__init__(module)
@ -19,18 +19,23 @@ class BroadbandController(ModuleController):
@pyqtSlot(str, object)
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.")
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():
logger.debug("Received set averages failure.")
self.set_averages_failure.emit()
@pyqtSlot(str)
def set_frequency(self, value):
logger.debug("Setting frequency to: " + value)
self.module.nqrduck_signal.emit("set_frequency", value)
try:
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)
def set_averages(self, value):
@ -40,20 +45,62 @@ class BroadbandController(ModuleController):
@pyqtSlot(str)
def change_start_frequency(self, value):
value = float(value)
if value > self.MIN_FREQUENCY:
self.module._model.start_frequency = value
if value > self.module.model.MIN_FREQUENCY:
self.module.model.start_frequency = value * 1e6
else:
self.module._model.start_frequency = self.MIN_FREQUENCY
self.module.model.start_frequency = self.module.model.MIN_FREQUENCY
@pyqtSlot(str)
def change_stop_frequency(self, value):
value = float(value)
if value < self.MAX_FREQUENCY:
self.module._model.stop_frequency = value
if value < self.module.model.MAX_FREQUENCY:
self.module._model.stop_frequency = value * 1e6
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()
def start_measurement(self):
def start_broadband_measurement(self):
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
logger = logging.getLogger(__name__)
class BroadbandModel(ModuleModel):
MIN_FREQUENCY = 30.0
MAX_FREQUENCY = 200.0
DEFAULT_FREQUENCY_STEP = 0.1
start_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
def start_frequency(self):
return self._start_frequency
@ -23,3 +38,78 @@ class BroadbandModel(ModuleModel):
def stop_frequency(self, value):
self._stop_frequency = 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>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="frequency_stepField">
<widget class="QLineEdit" name="frequencystepEdit">
<property name="text">
<string>0.1</string>
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -91,7 +91,7 @@
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>50.0</string>
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -108,7 +108,7 @@
<item row="1" column="2">
<widget class="QLineEdit" name="stop_frequencyField">
<property name="text">
<string>70.0</string>
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -132,7 +132,7 @@
<item row="3" column="2">
<widget class="QLineEdit" name="averagesEdit">
<property name="text">
<string>1000</string>
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>

View file

@ -1,6 +1,6 @@
import logging
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 .widget import Ui_Form
@ -10,7 +10,7 @@ logger = logging.getLogger(__name__)
class BroadbandView(ModuleView):
start_measurement = pyqtSignal()
start_broadband_measurement = pyqtSignal()
def __init__(self, module):
super().__init__(module)
@ -28,25 +28,32 @@ class BroadbandView(ModuleView):
def _connect_signals(self) -> None:
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.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.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.frequencystepEdit.editingFinished.connect(
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.start_measurement.connect(lambda: self.module._controller.start_measurement())
self._ui_form.start_measurementButton.clicked.connect(self._start_measurement_clicked)
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.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):
# Create a QMessageBox object
@ -62,7 +69,7 @@ class BroadbandView(ModuleView):
# Process the user's choice
if choice == QMessageBox.StandardButton.Yes:
self.start_measurement.emit()
self.start_broadband_measurement.emit()
def init_plots(self):
@ -89,19 +96,23 @@ class BroadbandView(ModuleView):
@pyqtSlot(float)
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.draw()
self._ui_form.broadbandPlot.canvas.flush_events()
self._ui_form.start_frequencyField.setText(str(start_frequency* 1e-6))
@pyqtSlot(float)
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.draw()
self._ui_form.broadbandPlot.canvas.flush_events()
self._ui_form.stop_frequencyField.setText(str(stop_frequency* 1e-6))
@pyqtSlot()
def on_editing_finished(self, value):
logger.debug("Averages editing finished.")
logger.debug("Editing finished by.")
self.sender().setStyleSheet("")
if self.sender() == self._ui_form.averagesEdit:
self.module.controller.set_averages(value)
@ -109,4 +120,30 @@ class BroadbandView(ModuleView):
@pyqtSlot()
def on_set_averages_failure(self):
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.setObjectName("label_3")
self.gridLayout_3.addWidget(self.label_3, 1, 0, 1, 1)
self.frequency_stepField = QtWidgets.QLineEdit(parent=Form)
self.frequency_stepField.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.frequency_stepField.setObjectName("frequency_stepField")
self.gridLayout_3.addWidget(self.frequency_stepField, 2, 2, 1, 1)
self.frequencystepEdit = QtWidgets.QLineEdit(parent=Form)
self.frequencystepEdit.setText("")
self.frequencystepEdit.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.frequencystepEdit.setObjectName("frequencystepEdit")
self.gridLayout_3.addWidget(self.frequencystepEdit, 2, 2, 1, 1)
self.start_frequencyField = QtWidgets.QLineEdit(parent=Form)
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.setObjectName("start_frequencyField")
self.gridLayout_3.addWidget(self.start_frequencyField, 0, 2, 1, 1)
@ -62,6 +64,7 @@ class Ui_Form(object):
self.label.setObjectName("label")
self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1)
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.setObjectName("stop_frequencyField")
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.gridLayout_3.addWidget(self.label_7, 3, 0, 1, 1)
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.setObjectName("averagesEdit")
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_2.setText(_translate("Form", "MHz"))
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.stop_frequencyField.setText(_translate("Form", "70.0"))
self.label_4.setText(_translate("Form", "MHz"))
self.label_7.setText(_translate("Form", "Averages:"))
self.averagesEdit.setText(_translate("Form", "1000"))
self.start_measurementButton.setText(_translate("Form", "Start Measurement"))
self.label_10.setText(_translate("Form", "Sequence Settings:"))
self.label_9.setText(_translate("Form", "Info Box:"))