mirror of
https://github.com/nqrduck/nqrduck-broadband.git
synced 2025-01-03 13:18:10 +00:00
Started implementation of broadband acquisition.
This commit is contained in:
parent
5e5c2da12a
commit
e8e55682c9
5 changed files with 216 additions and 42 deletions
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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:"))
|
||||
|
|
Loading…
Reference in a new issue