From e93d17dce3a3b10d66d949b732f0f05ee1083302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Tue, 28 Jul 2020 17:07:53 +0200 Subject: [PATCH] SweepControl refactoring --- NanoVNASaver/Controls/SweepControl.py | 1 - NanoVNASaver/Windows/DeviceSettings.py | 5 +- NanoVNASaver/Windows/SweepSettings.py | 254 ++++++++++++------------- test/test_sweep.py | 3 + 4 files changed, 132 insertions(+), 131 deletions(-) diff --git a/NanoVNASaver/Controls/SweepControl.py b/NanoVNASaver/Controls/SweepControl.py index eb953dd..61aca4f 100644 --- a/NanoVNASaver/Controls/SweepControl.py +++ b/NanoVNASaver/Controls/SweepControl.py @@ -210,5 +210,4 @@ class SweepControl(QtWidgets.QGroupBox): with sweep.lock: sweep.start = self.get_start() sweep.end = self.get_end() - sweep.points = self.app.vna.datapoints sweep.segments = self.get_segments() diff --git a/NanoVNASaver/Windows/DeviceSettings.py b/NanoVNASaver/Windows/DeviceSettings.py index 8560de6..8fc7c70 100644 --- a/NanoVNASaver/Windows/DeviceSettings.py +++ b/NanoVNASaver/Windows/DeviceSettings.py @@ -85,8 +85,6 @@ class DeviceSettingsWindow(QtWidgets.QWidget): self.datapoints = QtWidgets.QComboBox() self.datapoints.addItem(str(self.app.vna.datapoints)) self.datapoints.currentIndexChanged.connect(self.updateNrDatapoints) - self.datapoints.currentIndexChanged.connect( - self.app.sweep_control.update_step_size) self.bandwidth = QtWidgets.QComboBox() self.bandwidth.addItem(str(self.app.vna.bandwidth)) @@ -172,6 +170,9 @@ class DeviceSettingsWindow(QtWidgets.QWidget): return logger.debug("DP: %s", self.datapoints.itemText(i)) self.app.vna.datapoints = int(self.datapoints.itemText(i)) + with self.app.sweep.lock: + self.app.sweep.points = self.app.vna.datapoints + self.app.sweep_control.update_step_size() def updateBandwidth(self, i): if i < 0 or self.app.worker.running: diff --git a/NanoVNASaver/Windows/SweepSettings.py b/NanoVNASaver/Windows/SweepSettings.py index 8d5082e..3153430 100644 --- a/NanoVNASaver/Windows/SweepSettings.py +++ b/NanoVNASaver/Windows/SweepSettings.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import logging - +from functools import partial from PyQt5 import QtWidgets, QtCore from NanoVNASaver.Formatting import ( @@ -31,8 +31,9 @@ logger = logging.getLogger(__name__) class SweepSettingsWindow(QtWidgets.QWidget): def __init__(self, app: QtWidgets.QWidget): super().__init__() - self.app = app + self.padding = 0 + self.setWindowTitle("Sweep settings") self.setWindowIcon(self.app.icon) @@ -41,163 +42,131 @@ class SweepSettingsWindow(QtWidgets.QWidget): layout = QtWidgets.QVBoxLayout() self.setLayout(layout) - title_box = QtWidgets.QGroupBox("Sweep name") - title_layout = QtWidgets.QFormLayout(title_box) - self.sweep_title_input = QtWidgets.QLineEdit() - title_layout.addRow("Sweep name", self.sweep_title_input) - title_button_layout = QtWidgets.QHBoxLayout() - btn_set_sweep_title = QtWidgets.QPushButton("Set") - btn_set_sweep_title.clicked.connect( - lambda: self.update_title(self.sweep_title_input.text())) - btn_reset_sweep_title = QtWidgets.QPushButton("Reset") - btn_reset_sweep_title.clicked.connect(lambda: self.update_title("")) + layout.addWidget(self.title_box()) + layout.addWidget(self.settings_box()) + layout.addWidget(self.sweep_box()) + self.update_band() - title_button_layout.addWidget(btn_set_sweep_title) - title_button_layout.addWidget(btn_reset_sweep_title) - title_layout.addRow(title_button_layout) - layout.addWidget(title_box) + def title_box(self): + box = QtWidgets.QGroupBox("Sweep name") + layout = QtWidgets.QFormLayout(box) - settings_box = QtWidgets.QGroupBox("Settings") - settings_layout = QtWidgets.QFormLayout(settings_box) + input_title = QtWidgets.QLineEdit(self.app.sweep.properties.name) + input_title.editingFinished.connect( + lambda: self.update_title(input_title.text())) + layout.addRow(input_title) + return box - self.single_sweep_radiobutton = QtWidgets.QRadioButton("Single sweep") - self.continuous_sweep_radiobutton = QtWidgets.QRadioButton("Continuous sweep") - self.averaged_sweep_radiobutton = QtWidgets.QRadioButton("Averaged sweep") + def settings_box(self) -> 'QtWidgets.QWidget': + box = QtWidgets.QGroupBox("Settings") + layout = QtWidgets.QFormLayout(box) - settings_layout.addWidget(self.single_sweep_radiobutton) - self.single_sweep_radiobutton.setChecked(True) - self.single_sweep_radiobutton.clicked.connect( + # Sweep Mode + radio_button = QtWidgets.QRadioButton("Single sweep") + radio_button.setChecked( + self.app.sweep.properties.mode == SweepMode.SINGLE) + radio_button.clicked.connect( lambda: self.update_mode(SweepMode.SINGLE)) - settings_layout.addWidget(self.continuous_sweep_radiobutton) - settings_layout.addWidget(self.averaged_sweep_radiobutton) + layout.addWidget(radio_button) - self.averages = QtWidgets.QLineEdit("3") - self.truncates = QtWidgets.QLineEdit("0") + radio_button = QtWidgets.QRadioButton("Continous sweep") + radio_button.setChecked( + self.app.sweep.properties.mode == SweepMode.CONTINOUS) + radio_button.clicked.connect( + lambda: self.update_mode(SweepMode.CONTINOUS)) + layout.addWidget(radio_button) - settings_layout.addRow("Number of measurements to average", self.averages) - settings_layout.addRow("Number to discard", self.truncates) + radio_button = QtWidgets.QRadioButton("Averaged sweep") + radio_button.setChecked( + self.app.sweep.properties.mode == SweepMode.AVERAGE) + radio_button.clicked.connect( + lambda: self.update_mode(SweepMode.AVERAGE)) + layout.addWidget(radio_button) + + # Log sweep + checkbox = QtWidgets.QCheckBox("Logarithmic sweep") + checkbox.setCheckState(self.app.sweep.properties.logarithmic) + checkbox.toggled.connect( + lambda: self.update_logarithmic(checkbox.isChecked())) + layout.addWidget(checkbox) + + # Averaging label = QtWidgets.QLabel( "Averaging allows discarding outlying samples to get better" - "averages. Common values are 3/0, 5/2, 9/4 and 25/6.\n") + " averages. Common values are 3/0, 5/2, 9/4 and 25/6.") label.setWordWrap(True) - settings_layout.addRow(label) + layout.addRow(label) + averages = QtWidgets.QLineEdit( + str(self.app.sweep.properties.averages[0])) + truncates = QtWidgets.QLineEdit( + str(self.app.sweep.properties.averages[1])) + averages.editingFinished.connect( + lambda: self.update_averaging(averages, truncates)) + truncates.editingFinished.connect( + lambda: self.update_averaging(averages, truncates)) + layout.addRow("Number of measurements to average", averages) + layout.addRow("Number to discard", truncates) - self.s21att = QtWidgets.QLineEdit("0") + # TODO: is this more a device than a sweep property? label = QtWidgets.QLabel( "Some times when you measure amplifiers you need to use an" " attenuator in line with the S21 input (CH1) here you can" " specify it.") label.setWordWrap(True) - settings_layout.addRow(label) + layout.addRow(label) - settings_layout.addRow("Attenuator in port CH1 (s21) in dB", self.s21att) + input_att = QtWidgets.QLineEdit(str(self.app.s21att)) + input_att.editingFinished.connect( + lambda: self.update_attenuator(input_att)) + layout.addRow("Attenuator in port CH1 (s21) in dB", input_att) + return box - # settings_layout.addRow(QtWidgets.QLabel( - # "Common values with un-un are 16.9 (49:1 2450) 9.54 (9:1 450)")) - - self.continuous_sweep_radiobutton.clicked.connect( - lambda: self.update_mode(SweepMode.CONTINOUS)) - self.averaged_sweep_radiobutton.clicked.connect( - lambda: self.update_mode(SweepMode.AVERAGE)) - self.averages.editingFinished.connect(self.update_averaging) - self.truncates.editingFinished.connect(self.update_averaging) - self.s21att.editingFinished.connect(self.setS21Attenuator) - layout.addWidget(settings_box) - - band_sweep_box = QtWidgets.QGroupBox("Sweep band") - band_sweep_layout = QtWidgets.QFormLayout(band_sweep_box) + def sweep_box(self) -> 'QtWidgets.QWidget': + box = QtWidgets.QGroupBox("Sweep band") + layout = QtWidgets.QFormLayout(box) self.band_list = QtWidgets.QComboBox() self.band_list.setModel(self.app.bands) - self.band_list.currentIndexChanged.connect(self.updateCurrentBand) + # pylint: disable=unnecessary-lambda + self.band_list.currentIndexChanged.connect(lambda: self.update_band()) + layout.addRow("Select band", self.band_list) - band_sweep_layout.addRow("Select band", self.band_list) + for raw_label, btn_label, value in (("Pad band limits", "None", 0), + ("", "10%", 10), + ("", "25%", 25), + ("", "100%", 100),): + radio_button = QtWidgets.QRadioButton(btn_label) + radio_button.setChecked(self.padding == value) + radio_button.clicked.connect(partial(self.update_padding, value)) + layout.addRow(raw_label, radio_button) - self.band_pad_group = QtWidgets.QButtonGroup() - self.band_pad_0 = QtWidgets.QRadioButton("None") - self.band_pad_10 = QtWidgets.QRadioButton("10%") - self.band_pad_25 = QtWidgets.QRadioButton("25%") - self.band_pad_100 = QtWidgets.QRadioButton("100%") - self.band_pad_0.setChecked(True) - self.band_pad_group.addButton(self.band_pad_0) - self.band_pad_group.addButton(self.band_pad_10) - self.band_pad_group.addButton(self.band_pad_25) - self.band_pad_group.addButton(self.band_pad_100) - self.band_pad_group.buttonClicked.connect(self.updateCurrentBand) - band_sweep_layout.addRow("Pad band limits", self.band_pad_0) - band_sweep_layout.addRow("", self.band_pad_10) - band_sweep_layout.addRow("", self.band_pad_25) - band_sweep_layout.addRow("", self.band_pad_100) - - self.band_limit_label = QtWidgets.QLabel() - - band_sweep_layout.addRow(self.band_limit_label) + self.band_label = QtWidgets.QLabel() + layout.addRow(self.band_label) btn_set_band_sweep = QtWidgets.QPushButton("Set band sweep") - btn_set_band_sweep.clicked.connect(self.setBandSweep) - band_sweep_layout.addRow(btn_set_band_sweep) + btn_set_band_sweep.clicked.connect(lambda: self.update_band(True)) + layout.addRow(btn_set_band_sweep) + return box - self.updateCurrentBand() - - layout.addWidget(band_sweep_box) - - def updateCurrentBand(self): + def update_band(self, apply: bool = False): + logger.debug("update_band(%s)", apply) index_start = self.band_list.model().index(self.band_list.currentIndex(), 1) index_stop = self.band_list.model().index(self.band_list.currentIndex(), 2) start = int(self.band_list.model().data(index_start, QtCore.Qt.ItemDataRole).value()) stop = int(self.band_list.model().data(index_stop, QtCore.Qt.ItemDataRole).value()) - if self.band_pad_10.isChecked(): - padding = 10 - elif self.band_pad_25.isChecked(): - padding = 25 - elif self.band_pad_100.isChecked(): - padding = 100 - else: - padding = 0 - - if padding > 0: + if self.padding > 0: span = stop - start - start -= round(span * padding / 100) + start -= round(span * self.padding / 100) start = max(1, start) - stop += round(span * padding / 100) + stop += round(span * self.padding / 100) - self.band_limit_label.setText( + self.band_label.setText( f"Sweep span: {format_frequency_short(start)}" f" to {format_frequency_short(stop)}") - def setS21Attenuator(self): - try: - s21att = float(self.s21att.text()) - except ValueError: - s21att = 0 - if s21att < 0: - logger.warning("Values for attenuator are absolute and with no minus sign, resetting.") - self.s21att.setText("0") - self.app.s21att = 0 - logger.info("Setting an attenuator of %.2f dB inline with the CH1/S21 input", s21att) - self.app.s21att = s21att - - def setBandSweep(self): - index_start = self.band_list.model().index(self.band_list.currentIndex(), 1) - index_stop = self.band_list.model().index(self.band_list.currentIndex(), 2) - start = int(self.band_list.model().data(index_start, QtCore.Qt.ItemDataRole).value()) - stop = int(self.band_list.model().data(index_stop, QtCore.Qt.ItemDataRole).value()) - - if self.band_pad_10.isChecked(): - padding = 10 - elif self.band_pad_25.isChecked(): - padding = 25 - elif self.band_pad_100.isChecked(): - padding = 100 - else: - padding = 0 - - if padding > 0: - span = stop - start - start -= round(span * padding / 100) - start = max(1, start) - stop += round(span * padding / 100) + if not apply: + return self.app.sweep_control.input_start.setText( format_frequency_sweep(start)) @@ -206,25 +175,54 @@ class SweepSettingsWindow(QtWidgets.QWidget): self.app.sweep_control.input_end.textEdited.emit( self.app.sweep_control.input_end.text()) - def update_averaging(self): + def update_attenuator(self, value: 'QtWidgets.QLineEdit'): try: - amount = int(self.averages.text()) - truncates = int(self.truncates.text()) + att = float(value.text()) + assert att >= 0 + except (ValueError, AssertionError): + logger.warning("Values for attenuator are absolute and with no" + " minus sign, resetting.") + att = 0 + logger.debug("Attenuator %sdB inline with S21 input", att) + value.setText(str(att)) + self.app.s21att = att + + def update_averaging(self, + averages: 'QtWidgets.QLineEdit', + truncs: 'QtWidgets.QLineEdit'): + try: + amount = int(averages.text()) + truncates = int(truncs.text()) assert amount > 0 assert truncates >= 0 assert amount > truncates except (AssertionError, ValueError): + logger.warning("Illegal averaging values, set default") amount = 3 truncates = 0 - self.averages.setText("3") - self.truncates.setText("0") + logger.debug("update_averaging(%s, %s)", amount, truncates) + averages.setText(str(amount)) + truncs.setText(str(truncates)) with self.app.sweep.lock: self.app.sweep.properties.averages = (amount, truncates) + def update_logarithmic(self, logarithmic: bool): + logger.debug("update_logarithmic(%s)", logarithmic) + with self.app.sweep.lock: + self.app.sweep.properties.logarithmic = logarithmic + def update_mode(self, mode: 'SweepMode'): + logger.debug("update_mode(%s)", mode) with self.app.sweep.lock: self.app.sweep.properties.mode = mode + def update_padding(self, padding: int): + logger.debug("update_padding(%s)", padding) + self.padding = padding + self.update_band() + def update_title(self, title: str = ""): - self.app.sweep.properties.name = title + logger.debug("update_title(%s)", title) + with self.app.sweep.lock: + self.app.sweep.properties.name = title self.app.update_sweep_title() diff --git a/test/test_sweep.py b/test/test_sweep.py index 224ec14..9cd92f3 100644 --- a/test/test_sweep.py +++ b/test/test_sweep.py @@ -41,3 +41,6 @@ class TestCases(unittest.TestCase): data = list(sweep.get_frequencies()) self.assertEqual(data[0], 3600000) self.assertEqual(data[-1], 29869307) + + sweep2 = sweep.copy() + self.assertEqual(sweep, sweep2)