2020-06-09 15:56:53 +00:00
|
|
|
# NanoVNASaver
|
2020-06-25 17:48:03 +00:00
|
|
|
#
|
2020-06-09 15:56:53 +00:00
|
|
|
# A python program to view and export Touchstone data from a NanoVNA
|
2020-06-25 17:52:30 +00:00
|
|
|
# Copyright (C) 2019, 2020 Rune B. Broberg
|
2021-06-30 05:21:14 +00:00
|
|
|
# Copyright (C) 2020,2021 NanoVNA-Saver Authors
|
2019-08-29 13:10:35 +00:00
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2022-10-06 16:15:59 +00:00
|
|
|
import contextlib
|
2019-09-16 13:47:37 +00:00
|
|
|
import logging
|
2019-09-13 15:32:13 +00:00
|
|
|
import sys
|
2019-08-28 18:20:07 +00:00
|
|
|
import threading
|
2021-07-05 14:35:36 +00:00
|
|
|
from time import strftime, localtime
|
2019-08-28 18:20:07 +00:00
|
|
|
|
|
|
|
from PyQt5 import QtWidgets, QtCore, QtGui
|
|
|
|
|
2022-05-24 15:05:59 +00:00
|
|
|
from NanoVNASaver import Defaults
|
2020-06-21 18:54:23 +00:00
|
|
|
from .Windows import (
|
2023-03-08 08:40:39 +00:00
|
|
|
AboutWindow,
|
|
|
|
AnalysisWindow,
|
|
|
|
CalibrationWindow,
|
|
|
|
DeviceSettingsWindow,
|
|
|
|
DisplaySettingsWindow,
|
|
|
|
SweepSettingsWindow,
|
|
|
|
TDRWindow,
|
|
|
|
FilesWindow,
|
2020-06-21 18:54:23 +00:00
|
|
|
)
|
2022-10-09 15:50:37 +00:00
|
|
|
from .Controls.MarkerControl import MarkerControl
|
|
|
|
from .Controls.SweepControl import SweepControl
|
|
|
|
from .Controls.SerialControl import SerialControl
|
2020-07-28 19:04:43 +00:00
|
|
|
from .Formatting import format_frequency, format_vswr, format_gain
|
2021-07-05 14:16:33 +00:00
|
|
|
from .Hardware.Hardware import Interface
|
2020-07-04 12:26:20 +00:00
|
|
|
from .Hardware.VNA import VNA
|
2021-06-22 20:07:36 +00:00
|
|
|
from .RFTools import corr_att_data
|
2020-06-09 15:56:53 +00:00
|
|
|
from .Charts.Chart import Chart
|
2020-06-21 18:54:23 +00:00
|
|
|
from .Charts import (
|
|
|
|
CapacitanceChart,
|
2023-03-08 08:40:39 +00:00
|
|
|
CombinedLogMagChart,
|
|
|
|
GroupDelayChart,
|
|
|
|
InductanceChart,
|
|
|
|
LogMagChart,
|
|
|
|
PhaseChart,
|
|
|
|
MagnitudeChart,
|
|
|
|
MagnitudeZChart,
|
|
|
|
MagnitudeZShuntChart,
|
2022-09-15 18:08:23 +00:00
|
|
|
MagnitudeZSeriesChart,
|
2023-03-08 08:40:39 +00:00
|
|
|
QualityFactorChart,
|
|
|
|
VSWRChart,
|
|
|
|
PermeabilityChart,
|
|
|
|
PolarChart,
|
2023-02-10 17:40:23 +00:00
|
|
|
RealImaginaryMuChart,
|
2023-03-08 08:40:39 +00:00
|
|
|
RealImaginaryZChart,
|
|
|
|
RealImaginaryZShuntChart,
|
|
|
|
RealImaginaryZSeriesChart,
|
|
|
|
SmithChart,
|
|
|
|
SParameterChart,
|
|
|
|
TDRChart,
|
2020-06-21 18:54:23 +00:00
|
|
|
)
|
2020-06-15 07:52:32 +00:00
|
|
|
from .Calibration import Calibration
|
2022-10-06 16:15:59 +00:00
|
|
|
from .Marker.Widget import Marker
|
|
|
|
from .Marker.Delta import DeltaMarker
|
2019-09-04 16:12:38 +00:00
|
|
|
from .SweepWorker import SweepWorker
|
2022-10-06 16:15:59 +00:00
|
|
|
from .Settings.Bands import BandsModel
|
|
|
|
from .Settings.Sweep import Sweep
|
2021-06-22 20:07:36 +00:00
|
|
|
from .Touchstone import Touchstone
|
2020-06-28 15:37:23 +00:00
|
|
|
from .About import VERSION
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2019-09-16 13:47:37 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2019-09-03 20:04:08 +00:00
|
|
|
|
2019-08-28 18:20:07 +00:00
|
|
|
class NanoVNASaver(QtWidgets.QWidget):
|
2020-06-28 15:37:23 +00:00
|
|
|
version = VERSION
|
2019-11-01 15:58:38 +00:00
|
|
|
dataAvailable = QtCore.pyqtSignal()
|
2019-11-03 18:27:49 +00:00
|
|
|
scaleFactor = 1
|
2019-11-01 15:58:38 +00:00
|
|
|
|
2019-08-28 18:20:07 +00:00
|
|
|
def __init__(self):
|
|
|
|
super().__init__()
|
2020-03-12 19:14:22 +00:00
|
|
|
self.s21att = 0.0
|
2023-03-08 08:40:39 +00:00
|
|
|
if getattr(sys, "frozen", False):
|
2019-10-02 08:07:38 +00:00
|
|
|
logger.debug("Running from pyinstaller bundle")
|
2022-05-06 12:49:31 +00:00
|
|
|
self.icon = QtGui.QIcon(
|
2023-03-08 08:40:39 +00:00
|
|
|
f"{sys._MEIPASS}/icon_48x48.png"
|
|
|
|
) # pylint: disable=no-member
|
2019-10-02 08:07:38 +00:00
|
|
|
else:
|
|
|
|
self.icon = QtGui.QIcon("icon_48x48.png")
|
|
|
|
self.setWindowIcon(self.icon)
|
2022-09-15 18:08:23 +00:00
|
|
|
self.settings = Defaults.AppSettings(
|
|
|
|
QtCore.QSettings.IniFormat,
|
|
|
|
QtCore.QSettings.UserScope,
|
|
|
|
"NanoVNASaver",
|
2023-03-08 08:40:39 +00:00
|
|
|
"NanoVNASaver",
|
|
|
|
)
|
2021-07-05 14:16:33 +00:00
|
|
|
logger.info("Settings from: %s", self.settings.fileName())
|
2022-05-24 15:05:59 +00:00
|
|
|
Defaults.cfg = Defaults.restore(self.settings)
|
2019-08-28 18:20:07 +00:00
|
|
|
self.threadpool = QtCore.QThreadPool()
|
2020-07-27 15:05:11 +00:00
|
|
|
self.sweep = Sweep()
|
2019-08-28 22:56:54 +00:00
|
|
|
self.worker = SweepWorker(self)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2019-10-09 12:46:08 +00:00
|
|
|
self.worker.signals.updated.connect(self.dataUpdated)
|
|
|
|
self.worker.signals.finished.connect(self.sweepFinished)
|
|
|
|
self.worker.signals.sweepError.connect(self.showSweepError)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-07-17 19:57:03 +00:00
|
|
|
self.markers = []
|
2022-05-06 12:49:31 +00:00
|
|
|
self.marker_ref = False
|
2020-07-17 19:57:03 +00:00
|
|
|
|
|
|
|
self.marker_column = QtWidgets.QVBoxLayout()
|
|
|
|
self.marker_frame = QtWidgets.QFrame()
|
|
|
|
self.marker_column.setContentsMargins(0, 0, 0, 0)
|
|
|
|
self.marker_frame.setLayout(self.marker_column)
|
|
|
|
|
2020-07-12 21:49:01 +00:00
|
|
|
self.sweep_control = SweepControl(self)
|
2020-07-17 19:57:03 +00:00
|
|
|
self.marker_control = MarkerControl(self)
|
2021-07-05 14:16:33 +00:00
|
|
|
self.serial_control = SerialControl(self)
|
2020-07-12 21:49:01 +00:00
|
|
|
|
2019-09-26 20:57:34 +00:00
|
|
|
self.bands = BandsModel()
|
|
|
|
|
2020-07-04 10:08:54 +00:00
|
|
|
self.interface = Interface("serial", "None")
|
2022-10-06 16:15:59 +00:00
|
|
|
self.vna = VNA(self.interface)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2019-08-28 22:56:54 +00:00
|
|
|
self.dataLock = threading.Lock()
|
2021-06-22 20:07:36 +00:00
|
|
|
self.data = Touchstone()
|
|
|
|
self.ref_data = Touchstone()
|
2019-09-02 13:20:02 +00:00
|
|
|
|
2019-09-05 18:42:02 +00:00
|
|
|
self.sweepSource = ""
|
|
|
|
self.referenceSource = ""
|
|
|
|
|
2019-09-03 13:36:42 +00:00
|
|
|
self.calibration = Calibration()
|
|
|
|
|
2019-09-16 19:41:01 +00:00
|
|
|
logger.debug("Building user interface")
|
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
self.baseTitle = f"NanoVNA Saver {NanoVNASaver.version}"
|
2019-09-05 18:42:02 +00:00
|
|
|
self.updateTitle()
|
2020-07-22 11:37:06 +00:00
|
|
|
layout = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.LeftToRight)
|
|
|
|
|
2019-09-03 18:34:32 +00:00
|
|
|
scrollarea = QtWidgets.QScrollArea()
|
|
|
|
outer = QtWidgets.QVBoxLayout()
|
|
|
|
outer.addWidget(scrollarea)
|
|
|
|
self.setLayout(outer)
|
|
|
|
scrollarea.setWidgetResizable(True)
|
2023-03-08 08:40:39 +00:00
|
|
|
self.resize(
|
|
|
|
Defaults.cfg.gui.window_width, Defaults.cfg.gui.window_height
|
|
|
|
)
|
2020-06-12 20:16:26 +00:00
|
|
|
scrollarea.setSizePolicy(
|
2022-09-15 18:08:23 +00:00
|
|
|
QtWidgets.QSizePolicy.MinimumExpanding,
|
2023-03-08 08:40:39 +00:00
|
|
|
QtWidgets.QSizePolicy.MinimumExpanding,
|
|
|
|
)
|
|
|
|
self.setSizePolicy(
|
|
|
|
QtWidgets.QSizePolicy.MinimumExpanding,
|
|
|
|
QtWidgets.QSizePolicy.MinimumExpanding,
|
|
|
|
)
|
2019-09-03 18:34:32 +00:00
|
|
|
widget = QtWidgets.QWidget()
|
|
|
|
widget.setLayout(layout)
|
|
|
|
scrollarea.setWidget(widget)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-06-28 15:37:23 +00:00
|
|
|
self.charts = {
|
2022-09-15 18:08:23 +00:00
|
|
|
"s11": {
|
|
|
|
"capacitance": CapacitanceChart("S11 Serial C"),
|
|
|
|
"group_delay": GroupDelayChart("S11 Group Delay"),
|
|
|
|
"inductance": InductanceChart("S11 Serial L"),
|
|
|
|
"log_mag": LogMagChart("S11 Return Loss"),
|
|
|
|
"magnitude": MagnitudeChart("|S11|"),
|
|
|
|
"magnitude_z": MagnitudeZChart("S11 |Z|"),
|
|
|
|
"permeability": PermeabilityChart(
|
2020-06-28 15:37:23 +00:00
|
|
|
"S11 R/\N{GREEK SMALL LETTER OMEGA} &"
|
2023-03-08 08:40:39 +00:00
|
|
|
" X/\N{GREEK SMALL LETTER OMEGA}"
|
|
|
|
),
|
2022-09-15 18:08:23 +00:00
|
|
|
"phase": PhaseChart("S11 Phase"),
|
|
|
|
"q_factor": QualityFactorChart("S11 Quality Factor"),
|
2023-02-10 15:30:21 +00:00
|
|
|
"real_imag": RealImaginaryZChart("S11 R+jX"),
|
2023-03-08 08:40:39 +00:00
|
|
|
"real_imag_mu": RealImaginaryMuChart(
|
|
|
|
"S11 \N{GREEK SMALL LETTER MU}"
|
|
|
|
),
|
2022-09-15 18:08:23 +00:00
|
|
|
"smith": SmithChart("S11 Smith Chart"),
|
|
|
|
"s_parameter": SParameterChart("S11 Real/Imaginary"),
|
|
|
|
"vswr": VSWRChart("S11 VSWR"),
|
|
|
|
},
|
|
|
|
"s21": {
|
2023-03-08 08:40:39 +00:00
|
|
|
"group_delay": GroupDelayChart(
|
|
|
|
"S21 Group Delay", reflective=False
|
|
|
|
),
|
2022-09-15 18:08:23 +00:00
|
|
|
"log_mag": LogMagChart("S21 Gain"),
|
|
|
|
"magnitude": MagnitudeChart("|S21|"),
|
|
|
|
"magnitude_z_shunt": MagnitudeZShuntChart("S21 |Z| shunt"),
|
|
|
|
"magnitude_z_series": MagnitudeZSeriesChart("S21 |Z| series"),
|
2023-02-10 15:30:21 +00:00
|
|
|
"real_imag_shunt": RealImaginaryZShuntChart("S21 R+jX shunt"),
|
|
|
|
"real_imag_series": RealImaginaryZSeriesChart(
|
2023-03-08 08:40:39 +00:00
|
|
|
"S21 R+jX series"
|
|
|
|
),
|
2022-09-15 18:08:23 +00:00
|
|
|
"phase": PhaseChart("S21 Phase"),
|
|
|
|
"polar": PolarChart("S21 Polar Plot"),
|
|
|
|
"s_parameter": SParameterChart("S21 Real/Imaginary"),
|
|
|
|
},
|
|
|
|
"combined": {
|
|
|
|
"log_mag": CombinedLogMagChart("S11 & S21 LogMag"),
|
|
|
|
},
|
2020-06-28 15:37:23 +00:00
|
|
|
}
|
2019-10-13 07:58:26 +00:00
|
|
|
self.tdr_chart = TDRChart("TDR")
|
2019-10-14 06:43:06 +00:00
|
|
|
self.tdr_mainwindow_chart = TDRChart("TDR")
|
2019-09-05 12:56:40 +00:00
|
|
|
|
2019-10-13 07:58:26 +00:00
|
|
|
# List of all the S11 charts, for selecting
|
2020-06-28 15:37:23 +00:00
|
|
|
self.s11charts = list(self.charts["s11"].values())
|
2019-09-05 12:56:40 +00:00
|
|
|
|
2019-10-13 07:58:26 +00:00
|
|
|
# List of all the S21 charts, for selecting
|
2020-06-28 15:37:23 +00:00
|
|
|
self.s21charts = list(self.charts["s21"].values())
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2019-10-20 21:28:52 +00:00
|
|
|
# List of all charts that use both S11 and S21
|
2020-06-28 15:37:23 +00:00
|
|
|
self.combinedCharts = list(self.charts["combined"].values())
|
2019-10-20 21:28:52 +00:00
|
|
|
|
2019-10-13 07:58:26 +00:00
|
|
|
# List of all charts that can be selected for display
|
2021-07-05 14:16:33 +00:00
|
|
|
self.selectable_charts = (
|
2023-03-08 08:40:39 +00:00
|
|
|
self.s11charts
|
|
|
|
+ self.s21charts
|
|
|
|
+ self.combinedCharts
|
|
|
|
+ [
|
|
|
|
self.tdr_mainwindow_chart,
|
|
|
|
]
|
|
|
|
)
|
2019-09-13 15:08:20 +00:00
|
|
|
|
2019-10-13 07:58:26 +00:00
|
|
|
# List of all charts that subscribe to updates (including duplicates!)
|
|
|
|
self.subscribing_charts = []
|
2019-10-13 08:37:14 +00:00
|
|
|
self.subscribing_charts.extend(self.selectable_charts)
|
2019-10-14 06:43:06 +00:00
|
|
|
self.subscribing_charts.append(self.tdr_chart)
|
|
|
|
|
|
|
|
for c in self.subscribing_charts:
|
|
|
|
c.popoutRequested.connect(self.popoutChart)
|
2019-10-13 07:58:26 +00:00
|
|
|
|
2019-09-09 18:06:01 +00:00
|
|
|
self.charts_layout = QtWidgets.QGridLayout()
|
|
|
|
|
2021-06-29 19:42:31 +00:00
|
|
|
QtWidgets.QShortcut(QtGui.QKeySequence("Ctrl+Q"), self, self.close)
|
|
|
|
|
2020-07-23 13:27:53 +00:00
|
|
|
###############################################################
|
|
|
|
# Create main layout
|
|
|
|
###############################################################
|
|
|
|
|
2019-08-28 18:20:07 +00:00
|
|
|
left_column = QtWidgets.QVBoxLayout()
|
|
|
|
right_column = QtWidgets.QVBoxLayout()
|
2019-09-09 18:06:01 +00:00
|
|
|
right_column.addLayout(self.charts_layout)
|
2022-05-24 15:05:59 +00:00
|
|
|
self.marker_frame.setHidden(Defaults.cfg.gui.markers_hidden)
|
2020-07-23 13:27:53 +00:00
|
|
|
chart_widget = QtWidgets.QWidget()
|
|
|
|
chart_widget.setLayout(right_column)
|
2020-08-14 17:03:14 +00:00
|
|
|
self.splitter = QtWidgets.QSplitter()
|
|
|
|
self.splitter.addWidget(self.marker_frame)
|
|
|
|
self.splitter.addWidget(chart_widget)
|
|
|
|
|
2022-05-24 15:05:59 +00:00
|
|
|
self.splitter.restoreState(Defaults.cfg.gui.splitter_sizes)
|
2020-07-22 11:37:06 +00:00
|
|
|
|
|
|
|
layout.addLayout(left_column)
|
2020-08-14 17:03:14 +00:00
|
|
|
layout.addWidget(self.splitter, 2)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-06-28 16:48:41 +00:00
|
|
|
###############################################################
|
|
|
|
# Windows
|
|
|
|
###############################################################
|
|
|
|
|
|
|
|
self.windows = {
|
|
|
|
"about": AboutWindow(self),
|
|
|
|
# "analysis": AnalysisWindow(self),
|
|
|
|
"calibration": CalibrationWindow(self),
|
|
|
|
"device_settings": DeviceSettingsWindow(self),
|
2021-06-22 14:07:37 +00:00
|
|
|
"file": FilesWindow(self),
|
2020-06-28 16:48:41 +00:00
|
|
|
"sweep_settings": SweepSettingsWindow(self),
|
|
|
|
"setup": DisplaySettingsWindow(self),
|
|
|
|
"tdr": TDRWindow(self),
|
|
|
|
}
|
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-08-28 18:20:07 +00:00
|
|
|
# Sweep control
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-07-12 21:49:01 +00:00
|
|
|
left_column.addWidget(self.sweep_control)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-07-12 21:49:01 +00:00
|
|
|
# ###############################################################
|
2019-08-28 18:20:07 +00:00
|
|
|
# Marker control
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-07-17 19:57:03 +00:00
|
|
|
left_column.addWidget(self.marker_control)
|
2019-09-11 19:59:48 +00:00
|
|
|
|
2019-10-13 07:58:26 +00:00
|
|
|
for c in self.subscribing_charts:
|
2019-09-05 12:56:40 +00:00
|
|
|
c.setMarkers(self.markers)
|
2019-09-26 20:57:34 +00:00
|
|
|
c.setBands(self.bands)
|
2019-09-04 12:40:37 +00:00
|
|
|
|
2019-10-19 22:03:22 +00:00
|
|
|
self.marker_data_layout = QtWidgets.QVBoxLayout()
|
|
|
|
self.marker_data_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
2019-10-23 07:36:34 +00:00
|
|
|
for m in self.markers:
|
2020-07-19 14:38:03 +00:00
|
|
|
self.marker_data_layout.addWidget(m.get_data_layout())
|
2020-07-22 11:37:06 +00:00
|
|
|
|
|
|
|
scroll2 = QtWidgets.QScrollArea()
|
2022-05-06 12:49:31 +00:00
|
|
|
# scroll2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
|
2020-07-22 11:37:06 +00:00
|
|
|
scroll2.setWidgetResizable(True)
|
|
|
|
scroll2.setVisible(True)
|
|
|
|
|
|
|
|
widget2 = QtWidgets.QWidget()
|
|
|
|
widget2.setLayout(self.marker_data_layout)
|
|
|
|
scroll2.setWidget(widget2)
|
|
|
|
self.marker_column.addWidget(scroll2)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-07-19 14:38:03 +00:00
|
|
|
# init delta marker (but assume only one marker exists)
|
2020-07-22 11:37:06 +00:00
|
|
|
self.delta_marker = DeltaMarker("Delta Marker 2 - Marker 1")
|
2020-07-19 14:38:03 +00:00
|
|
|
self.delta_marker_layout = self.delta_marker.get_data_layout()
|
|
|
|
self.delta_marker_layout.hide()
|
|
|
|
self.marker_column.addWidget(self.delta_marker_layout)
|
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-08-30 16:41:22 +00:00
|
|
|
# Statistics/analysis
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-08-30 16:41:22 +00:00
|
|
|
|
|
|
|
s11_control_box = QtWidgets.QGroupBox()
|
|
|
|
s11_control_box.setTitle("S11")
|
|
|
|
s11_control_layout = QtWidgets.QFormLayout()
|
2021-07-01 16:47:33 +00:00
|
|
|
s11_control_layout.setVerticalSpacing(0)
|
2019-08-30 16:41:22 +00:00
|
|
|
s11_control_box.setLayout(s11_control_layout)
|
2019-10-11 17:13:46 +00:00
|
|
|
|
2019-08-30 16:41:22 +00:00
|
|
|
self.s11_min_swr_label = QtWidgets.QLabel()
|
|
|
|
s11_control_layout.addRow("Min VSWR:", self.s11_min_swr_label)
|
|
|
|
self.s11_min_rl_label = QtWidgets.QLabel()
|
|
|
|
s11_control_layout.addRow("Return loss:", self.s11_min_rl_label)
|
|
|
|
|
2019-10-19 22:03:22 +00:00
|
|
|
self.marker_column.addWidget(s11_control_box)
|
2019-08-30 16:41:22 +00:00
|
|
|
|
|
|
|
s21_control_box = QtWidgets.QGroupBox()
|
|
|
|
s21_control_box.setTitle("S21")
|
|
|
|
s21_control_layout = QtWidgets.QFormLayout()
|
2021-07-01 16:47:33 +00:00
|
|
|
s21_control_layout.setVerticalSpacing(0)
|
2019-08-30 16:41:22 +00:00
|
|
|
s21_control_box.setLayout(s21_control_layout)
|
2019-10-11 17:13:46 +00:00
|
|
|
|
2019-08-30 16:41:22 +00:00
|
|
|
self.s21_min_gain_label = QtWidgets.QLabel()
|
|
|
|
s21_control_layout.addRow("Min gain:", self.s21_min_gain_label)
|
|
|
|
|
|
|
|
self.s21_max_gain_label = QtWidgets.QLabel()
|
|
|
|
s21_control_layout.addRow("Max gain:", self.s21_max_gain_label)
|
|
|
|
|
2019-10-19 22:03:22 +00:00
|
|
|
self.marker_column.addWidget(s21_control_box)
|
2019-09-04 12:40:37 +00:00
|
|
|
|
2020-07-22 11:37:06 +00:00
|
|
|
# self.marker_column.addStretch(1)
|
2019-10-04 10:51:20 +00:00
|
|
|
|
2020-06-28 16:48:41 +00:00
|
|
|
self.windows["analysis"] = AnalysisWindow(self)
|
2019-10-04 10:51:20 +00:00
|
|
|
btn_show_analysis = QtWidgets.QPushButton("Analysis ...")
|
2021-06-29 19:42:31 +00:00
|
|
|
btn_show_analysis.setMinimumHeight(20)
|
2020-06-28 16:48:41 +00:00
|
|
|
btn_show_analysis.clicked.connect(
|
2023-03-08 08:40:39 +00:00
|
|
|
lambda: self.display_window("analysis")
|
|
|
|
)
|
2019-10-19 22:03:22 +00:00
|
|
|
self.marker_column.addWidget(btn_show_analysis)
|
2019-10-04 10:51:20 +00:00
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-09-04 12:40:37 +00:00
|
|
|
# TDR
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-09-04 12:40:37 +00:00
|
|
|
|
2020-06-28 16:48:41 +00:00
|
|
|
self.tdr_chart.tdrWindow = self.windows["tdr"]
|
|
|
|
self.tdr_mainwindow_chart.tdrWindow = self.windows["tdr"]
|
|
|
|
self.windows["tdr"].updated.connect(self.tdr_chart.update)
|
|
|
|
self.windows["tdr"].updated.connect(self.tdr_mainwindow_chart.update)
|
2019-09-13 15:08:20 +00:00
|
|
|
|
2019-09-01 13:14:25 +00:00
|
|
|
tdr_control_box = QtWidgets.QGroupBox()
|
|
|
|
tdr_control_box.setTitle("TDR")
|
|
|
|
tdr_control_layout = QtWidgets.QFormLayout()
|
|
|
|
tdr_control_box.setLayout(tdr_control_layout)
|
2021-06-25 10:21:29 +00:00
|
|
|
tdr_control_box.setMaximumWidth(240)
|
2019-09-01 13:14:25 +00:00
|
|
|
|
|
|
|
self.tdr_result_label = QtWidgets.QLabel()
|
2021-06-29 19:42:31 +00:00
|
|
|
self.tdr_result_label.setMinimumHeight(20)
|
2020-12-23 12:27:53 +00:00
|
|
|
tdr_control_layout.addRow(
|
2023-03-08 08:40:39 +00:00
|
|
|
"Estimated cable length:", self.tdr_result_label
|
|
|
|
)
|
2019-09-01 13:14:25 +00:00
|
|
|
|
2023-03-08 08:40:39 +00:00
|
|
|
self.tdr_button = QtWidgets.QPushButton("Time Domain Reflectometry ...")
|
2021-06-29 19:42:31 +00:00
|
|
|
self.tdr_button.setMinimumHeight(20)
|
2020-06-28 16:48:41 +00:00
|
|
|
self.tdr_button.clicked.connect(lambda: self.display_window("tdr"))
|
2019-09-13 15:08:20 +00:00
|
|
|
|
|
|
|
tdr_control_layout.addRow(self.tdr_button)
|
|
|
|
|
2019-09-01 13:14:25 +00:00
|
|
|
left_column.addWidget(tdr_control_box)
|
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-08-30 16:41:22 +00:00
|
|
|
# Spacer
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-08-30 16:41:22 +00:00
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
left_column.addSpacerItem(
|
2023-03-08 08:40:39 +00:00
|
|
|
QtWidgets.QSpacerItem(
|
|
|
|
1,
|
|
|
|
1,
|
|
|
|
QtWidgets.QSizePolicy.Fixed,
|
|
|
|
QtWidgets.QSizePolicy.Expanding,
|
|
|
|
)
|
|
|
|
)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-09-01 21:13:21 +00:00
|
|
|
# Reference control
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-09-01 21:13:21 +00:00
|
|
|
|
|
|
|
reference_control_box = QtWidgets.QGroupBox()
|
2021-06-25 10:21:29 +00:00
|
|
|
reference_control_box.setMaximumWidth(240)
|
2019-09-01 21:13:21 +00:00
|
|
|
reference_control_box.setTitle("Reference sweep")
|
|
|
|
reference_control_layout = QtWidgets.QFormLayout(reference_control_box)
|
|
|
|
|
2019-11-12 10:26:42 +00:00
|
|
|
btn_set_reference = QtWidgets.QPushButton("Set current as reference")
|
2021-06-29 19:42:31 +00:00
|
|
|
btn_set_reference.setMinimumHeight(20)
|
2019-11-12 10:26:42 +00:00
|
|
|
btn_set_reference.clicked.connect(self.setReference)
|
2019-09-01 21:13:21 +00:00
|
|
|
self.btnResetReference = QtWidgets.QPushButton("Reset reference")
|
2021-06-29 19:42:31 +00:00
|
|
|
self.btnResetReference.setMinimumHeight(20)
|
2019-09-01 21:13:21 +00:00
|
|
|
self.btnResetReference.clicked.connect(self.resetReference)
|
|
|
|
self.btnResetReference.setDisabled(True)
|
|
|
|
|
2019-11-12 10:26:42 +00:00
|
|
|
reference_control_layout.addRow(btn_set_reference)
|
2019-09-01 21:13:21 +00:00
|
|
|
reference_control_layout.addRow(self.btnResetReference)
|
|
|
|
|
|
|
|
left_column.addWidget(reference_control_box)
|
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-08-28 18:20:07 +00:00
|
|
|
# Serial control
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2021-07-05 14:16:33 +00:00
|
|
|
left_column.addWidget(self.serial_control)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-09-10 10:47:18 +00:00
|
|
|
# Calibration
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-09-10 10:47:18 +00:00
|
|
|
|
|
|
|
btnOpenCalibrationWindow = QtWidgets.QPushButton("Calibration ...")
|
2021-06-29 19:42:31 +00:00
|
|
|
btnOpenCalibrationWindow.setMinimumHeight(20)
|
2019-09-10 10:47:18 +00:00
|
|
|
self.calibrationWindow = CalibrationWindow(self)
|
2020-06-28 16:48:41 +00:00
|
|
|
btnOpenCalibrationWindow.clicked.connect(
|
2023-03-08 08:40:39 +00:00
|
|
|
lambda: self.display_window("calibration")
|
|
|
|
)
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-09-05 12:56:40 +00:00
|
|
|
# Display setup
|
2020-06-12 20:16:26 +00:00
|
|
|
###############################################################
|
2019-09-05 12:56:40 +00:00
|
|
|
|
2019-09-19 12:15:47 +00:00
|
|
|
btn_display_setup = QtWidgets.QPushButton("Display setup ...")
|
2021-06-29 19:42:31 +00:00
|
|
|
btn_display_setup.setMinimumHeight(20)
|
2021-06-25 10:21:29 +00:00
|
|
|
btn_display_setup.setMaximumWidth(240)
|
2023-03-08 08:40:39 +00:00
|
|
|
btn_display_setup.clicked.connect(lambda: self.display_window("setup"))
|
2019-10-09 12:08:48 +00:00
|
|
|
|
2019-09-05 12:56:40 +00:00
|
|
|
btn_about = QtWidgets.QPushButton("About ...")
|
2021-06-29 19:42:31 +00:00
|
|
|
btn_about.setMinimumHeight(20)
|
2021-06-25 10:21:29 +00:00
|
|
|
btn_about.setMaximumWidth(240)
|
2019-10-09 12:08:48 +00:00
|
|
|
|
2023-03-08 08:40:39 +00:00
|
|
|
btn_about.clicked.connect(lambda: self.display_window("about"))
|
2019-09-19 12:15:47 +00:00
|
|
|
|
2021-06-22 14:07:37 +00:00
|
|
|
btn_open_file_window = QtWidgets.QPushButton("Files")
|
2021-06-29 19:42:31 +00:00
|
|
|
btn_open_file_window.setMinimumHeight(20)
|
2021-06-25 10:21:29 +00:00
|
|
|
btn_open_file_window.setMaximumWidth(240)
|
2021-06-22 14:07:37 +00:00
|
|
|
|
|
|
|
btn_open_file_window.clicked.connect(
|
2023-03-08 08:40:39 +00:00
|
|
|
lambda: self.display_window("file")
|
|
|
|
)
|
2021-06-22 14:07:37 +00:00
|
|
|
|
2019-09-19 12:15:47 +00:00
|
|
|
button_grid = QtWidgets.QGridLayout()
|
2019-09-26 11:14:42 +00:00
|
|
|
button_grid.addWidget(btn_open_file_window, 0, 0)
|
2019-09-19 12:15:47 +00:00
|
|
|
button_grid.addWidget(btnOpenCalibrationWindow, 0, 1)
|
|
|
|
button_grid.addWidget(btn_display_setup, 1, 0)
|
|
|
|
button_grid.addWidget(btn_about, 1, 1)
|
|
|
|
left_column.addLayout(button_grid)
|
2019-09-05 12:56:40 +00:00
|
|
|
|
2019-09-16 19:41:01 +00:00
|
|
|
logger.debug("Finished building interface")
|
|
|
|
|
2023-03-06 07:51:21 +00:00
|
|
|
def _sweep_control(self, start: bool = True) -> None:
|
|
|
|
self.sweep_control.progress_bar.setValue(0 if start else 100)
|
|
|
|
self.sweep_control.btn_start.setDisabled(start)
|
|
|
|
self.sweep_control.btn_stop.setDisabled(not start)
|
|
|
|
self.sweep_control.toggle_settings(start)
|
|
|
|
|
2020-07-12 21:49:01 +00:00
|
|
|
def sweep_start(self):
|
2020-07-04 10:08:54 +00:00
|
|
|
# Run the device data update
|
2020-07-05 11:00:03 +00:00
|
|
|
if not self.vna.connected():
|
2019-08-28 18:20:07 +00:00
|
|
|
return
|
2019-09-10 10:47:18 +00:00
|
|
|
self.worker.stopped = False
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2023-03-06 07:51:21 +00:00
|
|
|
self._sweep_control(start=True)
|
2020-07-12 21:49:01 +00:00
|
|
|
|
2019-09-09 11:21:54 +00:00
|
|
|
for m in self.markers:
|
|
|
|
m.resetLabels()
|
2019-09-01 17:38:01 +00:00
|
|
|
self.s11_min_rl_label.setText("")
|
|
|
|
self.s11_min_swr_label.setText("")
|
|
|
|
self.s21_min_gain_label.setText("")
|
|
|
|
self.s21_max_gain_label.setText("")
|
|
|
|
self.tdr_result_label.setText("")
|
2019-08-28 18:20:07 +00:00
|
|
|
|
2020-07-16 06:27:18 +00:00
|
|
|
self.settings.setValue("Segments", self.sweep_control.get_segments())
|
2019-09-18 11:45:53 +00:00
|
|
|
|
2019-10-07 19:24:18 +00:00
|
|
|
logger.debug("Starting worker thread")
|
2019-08-28 22:56:54 +00:00
|
|
|
self.threadpool.start(self.worker)
|
|
|
|
|
2020-07-12 21:49:01 +00:00
|
|
|
def sweep_stop(self):
|
2019-09-10 10:47:18 +00:00
|
|
|
self.worker.stopped = True
|
|
|
|
|
2020-06-30 19:46:47 +00:00
|
|
|
def saveData(self, data, data21, source=None):
|
2020-07-07 18:14:10 +00:00
|
|
|
with self.dataLock:
|
2021-06-22 20:07:36 +00:00
|
|
|
self.data.s11 = data
|
|
|
|
self.data.s21 = data21
|
2020-03-12 19:14:22 +00:00
|
|
|
if self.s21att > 0:
|
2021-06-22 20:07:36 +00:00
|
|
|
self.data.s21 = corr_att_data(self.data.s21, self.s21att)
|
2019-09-05 18:42:02 +00:00
|
|
|
if source is not None:
|
|
|
|
self.sweepSource = source
|
|
|
|
else:
|
2020-06-12 20:16:26 +00:00
|
|
|
self.sweepSource = (
|
2020-07-27 15:05:11 +00:00
|
|
|
f"{self.sweep.properties.name}"
|
2020-06-12 20:16:26 +00:00
|
|
|
f" {strftime('%Y-%m-%d %H:%M:%S', localtime())}"
|
|
|
|
).lstrip()
|
2019-08-28 22:56:54 +00:00
|
|
|
|
2019-10-26 13:52:54 +00:00
|
|
|
def markerUpdated(self, marker: Marker):
|
2020-07-07 18:14:10 +00:00
|
|
|
with self.dataLock:
|
2021-06-22 20:07:36 +00:00
|
|
|
marker.findLocation(self.data.s11)
|
2020-07-24 10:17:03 +00:00
|
|
|
marker.resetLabels()
|
2021-06-22 20:07:36 +00:00
|
|
|
marker.updateLabels(self.data.s11, self.data.s21)
|
2019-10-26 13:52:54 +00:00
|
|
|
for c in self.subscribing_charts:
|
|
|
|
c.update()
|
2022-05-06 12:49:31 +00:00
|
|
|
if not self.delta_marker_layout.isHidden():
|
|
|
|
m1 = self.markers[0]
|
|
|
|
m2 = None
|
|
|
|
if self.marker_ref:
|
|
|
|
if self.ref_data:
|
2022-05-06 13:17:22 +00:00
|
|
|
m2 = Marker("Reference")
|
2022-05-06 12:49:31 +00:00
|
|
|
m2.location = self.markers[0].location
|
|
|
|
m2.resetLabels()
|
2023-03-08 08:40:39 +00:00
|
|
|
m2.updateLabels(self.ref_data.s11, self.ref_data.s21)
|
2022-05-06 12:49:31 +00:00
|
|
|
else:
|
|
|
|
logger.warning("No reference data for marker")
|
|
|
|
|
|
|
|
elif Marker.count() >= 2:
|
|
|
|
m2 = self.markers[1]
|
|
|
|
|
|
|
|
if m2 is None:
|
|
|
|
logger.error("No data for delta, missing marker or reference")
|
|
|
|
else:
|
|
|
|
self.delta_marker.set_markers(m1, m2)
|
|
|
|
self.delta_marker.resetLabels()
|
2022-10-06 16:15:59 +00:00
|
|
|
with contextlib.suppress(IndexError):
|
2022-05-06 12:49:31 +00:00
|
|
|
self.delta_marker.updateLabels()
|
2019-10-26 13:52:54 +00:00
|
|
|
|
2019-08-28 22:56:54 +00:00
|
|
|
def dataUpdated(self):
|
2020-07-07 18:14:10 +00:00
|
|
|
with self.dataLock:
|
2021-06-22 20:07:36 +00:00
|
|
|
s11 = self.data.s11[:]
|
|
|
|
s21 = self.data.s21[:]
|
2020-07-29 11:04:42 +00:00
|
|
|
|
|
|
|
for m in self.markers:
|
|
|
|
m.resetLabels()
|
2021-06-22 20:07:36 +00:00
|
|
|
m.updateLabels(s11, s21)
|
2020-07-29 11:04:42 +00:00
|
|
|
|
|
|
|
for c in self.s11charts:
|
2021-06-22 20:07:36 +00:00
|
|
|
c.setData(s11)
|
2020-07-29 11:04:42 +00:00
|
|
|
|
|
|
|
for c in self.s21charts:
|
2021-06-22 20:07:36 +00:00
|
|
|
c.setData(s21)
|
2020-07-29 11:04:42 +00:00
|
|
|
|
|
|
|
for c in self.combinedCharts:
|
2021-06-22 20:07:36 +00:00
|
|
|
c.setCombinedData(s11, s21)
|
2020-07-29 11:04:42 +00:00
|
|
|
|
2022-01-17 07:50:04 +00:00
|
|
|
self.sweep_control.progress_bar.setValue(int(self.worker.percentage))
|
2020-07-29 11:04:42 +00:00
|
|
|
self.windows["tdr"].updateTDR()
|
|
|
|
|
2021-06-22 20:07:36 +00:00
|
|
|
if s11:
|
|
|
|
min_vswr = min(s11, key=lambda data: data.vswr)
|
2020-07-29 11:04:42 +00:00
|
|
|
self.s11_min_swr_label.setText(
|
2022-09-15 18:08:23 +00:00
|
|
|
f"{format_vswr(min_vswr.vswr)} @"
|
2023-03-08 08:40:39 +00:00
|
|
|
f" {format_frequency(min_vswr.freq)}"
|
|
|
|
)
|
2020-07-29 11:04:42 +00:00
|
|
|
self.s11_min_rl_label.setText(format_gain(min_vswr.gain))
|
|
|
|
else:
|
|
|
|
self.s11_min_swr_label.setText("")
|
|
|
|
self.s11_min_rl_label.setText("")
|
|
|
|
|
2021-06-22 20:07:36 +00:00
|
|
|
if s21:
|
|
|
|
min_gain = min(s21, key=lambda data: data.gain)
|
|
|
|
max_gain = max(s21, key=lambda data: data.gain)
|
2020-07-29 11:04:42 +00:00
|
|
|
self.s21_min_gain_label.setText(
|
|
|
|
f"{format_gain(min_gain.gain)}"
|
2023-03-08 08:40:39 +00:00
|
|
|
f" @ {format_frequency(min_gain.freq)}"
|
|
|
|
)
|
2020-07-29 11:04:42 +00:00
|
|
|
self.s21_max_gain_label.setText(
|
|
|
|
f"{format_gain(max_gain.gain)}"
|
2023-03-08 08:40:39 +00:00
|
|
|
f" @ {format_frequency(max_gain.freq)}"
|
|
|
|
)
|
2020-07-29 11:04:42 +00:00
|
|
|
else:
|
|
|
|
self.s21_min_gain_label.setText("")
|
|
|
|
self.s21_max_gain_label.setText("")
|
2019-08-30 16:41:22 +00:00
|
|
|
|
2019-09-08 18:30:20 +00:00
|
|
|
self.updateTitle()
|
2019-11-01 15:58:38 +00:00
|
|
|
self.dataAvailable.emit()
|
2019-08-28 22:56:54 +00:00
|
|
|
|
|
|
|
def sweepFinished(self):
|
2023-03-06 07:51:21 +00:00
|
|
|
self._sweep_control(start=False)
|
2019-09-12 21:12:32 +00:00
|
|
|
|
2020-07-13 11:49:23 +00:00
|
|
|
for marker in self.markers:
|
2023-03-08 08:40:39 +00:00
|
|
|
marker.frequencyInput.textEdited.emit(marker.frequencyInput.text())
|
2019-09-01 21:13:21 +00:00
|
|
|
|
2021-06-22 20:07:36 +00:00
|
|
|
def setReference(self, s11=None, s21=None, source=None):
|
|
|
|
if not s11:
|
2020-07-29 11:04:42 +00:00
|
|
|
with self.dataLock:
|
2021-06-22 20:07:36 +00:00
|
|
|
s11 = self.data.s11[:]
|
|
|
|
s21 = self.data.s21[:]
|
2020-07-14 10:00:03 +00:00
|
|
|
|
2021-06-22 20:07:36 +00:00
|
|
|
self.ref_data.s11 = s11
|
2019-09-05 12:56:40 +00:00
|
|
|
for c in self.s11charts:
|
2021-06-22 20:07:36 +00:00
|
|
|
c.setReference(s11)
|
2019-09-01 21:13:21 +00:00
|
|
|
|
2021-06-22 20:07:36 +00:00
|
|
|
self.ref_data.s21 = s21
|
2019-09-05 12:56:40 +00:00
|
|
|
for c in self.s21charts:
|
2021-06-22 20:07:36 +00:00
|
|
|
c.setReference(s21)
|
2019-10-20 21:28:52 +00:00
|
|
|
|
|
|
|
for c in self.combinedCharts:
|
2021-06-22 20:07:36 +00:00
|
|
|
c.setCombinedReference(s11, s21)
|
2019-10-20 21:28:52 +00:00
|
|
|
|
2019-09-01 21:13:21 +00:00
|
|
|
self.btnResetReference.setDisabled(False)
|
|
|
|
|
2022-10-06 16:15:59 +00:00
|
|
|
self.referenceSource = source or self.sweepSource
|
2019-09-05 18:42:02 +00:00
|
|
|
self.updateTitle()
|
|
|
|
|
|
|
|
def updateTitle(self):
|
2020-07-29 11:04:42 +00:00
|
|
|
insert = "("
|
2019-09-05 18:42:02 +00:00
|
|
|
if self.sweepSource != "":
|
2020-07-29 11:04:42 +00:00
|
|
|
insert += (
|
2021-06-22 20:07:36 +00:00
|
|
|
f"Sweep: {self.sweepSource} @ {len(self.data.s11)} points"
|
2023-03-08 08:40:39 +00:00
|
|
|
f"{', ' if self.referenceSource else ''}"
|
|
|
|
)
|
2019-09-05 18:42:02 +00:00
|
|
|
if self.referenceSource != "":
|
2020-07-29 11:04:42 +00:00
|
|
|
insert += (
|
|
|
|
f"Reference: {self.referenceSource} @"
|
2023-03-08 08:40:39 +00:00
|
|
|
f" {len(self.ref_data.s11)} points"
|
|
|
|
)
|
2020-07-29 11:04:42 +00:00
|
|
|
insert += ")"
|
2022-10-06 16:15:59 +00:00
|
|
|
title = f"{self.baseTitle} {insert or ''}"
|
2019-09-05 18:42:02 +00:00
|
|
|
self.setWindowTitle(title)
|
|
|
|
|
2019-09-01 21:13:21 +00:00
|
|
|
def resetReference(self):
|
2021-06-22 20:07:36 +00:00
|
|
|
self.ref_data = Touchstone()
|
2019-09-05 18:42:02 +00:00
|
|
|
self.referenceSource = ""
|
2019-09-21 10:55:22 +00:00
|
|
|
self.updateTitle()
|
2019-10-13 07:58:26 +00:00
|
|
|
for c in self.subscribing_charts:
|
2019-09-01 21:13:21 +00:00
|
|
|
c.resetReference()
|
|
|
|
self.btnResetReference.setDisabled(True)
|
|
|
|
|
2019-09-03 18:34:32 +00:00
|
|
|
def sizeHint(self) -> QtCore.QSize:
|
|
|
|
return QtCore.QSize(1100, 950)
|
2019-09-05 12:56:40 +00:00
|
|
|
|
2020-06-28 16:48:41 +00:00
|
|
|
def display_window(self, name):
|
|
|
|
self.windows[name].show()
|
|
|
|
QtWidgets.QApplication.setActiveWindow(self.windows[name])
|
2019-10-09 12:08:48 +00:00
|
|
|
|
2019-09-22 19:19:08 +00:00
|
|
|
def showError(self, text):
|
2019-10-09 12:46:08 +00:00
|
|
|
QtWidgets.QMessageBox.warning(self, "Error", text)
|
2019-09-26 13:14:28 +00:00
|
|
|
|
2019-11-12 09:36:57 +00:00
|
|
|
def showSweepError(self):
|
|
|
|
self.showError(self.worker.error_message)
|
2022-10-06 16:15:59 +00:00
|
|
|
with contextlib.suppress(IOError):
|
2020-07-24 19:11:34 +00:00
|
|
|
self.vna.flushSerialBuffers() # Remove any left-over data
|
2023-03-08 08:40:39 +00:00
|
|
|
self.vna.reconnect() # try reconnection
|
2019-11-12 09:36:57 +00:00
|
|
|
self.sweepFinished()
|
|
|
|
|
2019-10-13 08:37:14 +00:00
|
|
|
def popoutChart(self, chart: Chart):
|
|
|
|
logger.debug("Requested popout for chart: %s", chart.name)
|
2019-10-13 09:19:11 +00:00
|
|
|
new_chart = self.copyChart(chart)
|
2019-10-14 17:14:10 +00:00
|
|
|
new_chart.isPopout = True
|
2019-10-13 09:19:11 +00:00
|
|
|
new_chart.show()
|
|
|
|
new_chart.setWindowTitle(new_chart.name)
|
|
|
|
|
|
|
|
def copyChart(self, chart: Chart):
|
2019-10-13 08:37:14 +00:00
|
|
|
new_chart = chart.copy()
|
|
|
|
self.subscribing_charts.append(new_chart)
|
2019-10-13 09:19:11 +00:00
|
|
|
if chart in self.s11charts:
|
|
|
|
self.s11charts.append(new_chart)
|
|
|
|
if chart in self.s21charts:
|
|
|
|
self.s21charts.append(new_chart)
|
2019-10-20 21:28:52 +00:00
|
|
|
if chart in self.combinedCharts:
|
|
|
|
self.combinedCharts.append(new_chart)
|
2019-10-13 08:37:14 +00:00
|
|
|
new_chart.popoutRequested.connect(self.popoutChart)
|
2019-10-13 09:19:11 +00:00
|
|
|
return new_chart
|
2019-10-13 08:37:14 +00:00
|
|
|
|
2019-09-09 18:06:01 +00:00
|
|
|
def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
|
2019-09-10 10:47:18 +00:00
|
|
|
self.worker.stopped = True
|
2020-02-15 17:14:00 +00:00
|
|
|
for marker in self.markers:
|
|
|
|
marker.update_settings()
|
2019-09-09 18:06:01 +00:00
|
|
|
self.settings.sync()
|
2019-09-26 20:57:34 +00:00
|
|
|
self.bands.saveSettings()
|
2019-09-10 10:47:18 +00:00
|
|
|
self.threadpool.waitForDone(2500)
|
2022-05-24 15:05:59 +00:00
|
|
|
|
|
|
|
Defaults.cfg.chart.marker_count = Marker.count()
|
|
|
|
Defaults.cfg.gui.window_width = self.width()
|
|
|
|
Defaults.cfg.gui.window_height = self.height()
|
2022-05-27 16:39:36 +00:00
|
|
|
Defaults.cfg.gui.splitter_sizes = self.splitter.saveState()
|
2022-05-24 15:05:59 +00:00
|
|
|
Defaults.store(self.settings, Defaults.cfg)
|
|
|
|
|
2019-09-09 18:06:01 +00:00
|
|
|
a0.accept()
|
2019-10-23 07:57:40 +00:00
|
|
|
sys.exit()
|
2019-09-09 18:06:01 +00:00
|
|
|
|
2019-11-03 18:27:49 +00:00
|
|
|
def changeFont(self, font: QtGui.QFont) -> None:
|
|
|
|
qf_new = QtGui.QFontMetricsF(font)
|
|
|
|
normal_font = QtGui.QFont(font)
|
|
|
|
normal_font.setPointSize(8)
|
|
|
|
qf_normal = QtGui.QFontMetricsF(normal_font)
|
2020-06-12 20:16:26 +00:00
|
|
|
# Characters we would normally display
|
|
|
|
standard_string = "0.123456789 0.123456789 MHz \N{OHM SIGN}"
|
2021-07-06 15:01:20 +00:00
|
|
|
new_width = qf_new.horizontalAdvance(standard_string)
|
|
|
|
old_width = qf_normal.horizontalAdvance(standard_string)
|
2019-11-03 18:27:49 +00:00
|
|
|
self.scaleFactor = new_width / old_width
|
2023-03-08 08:40:39 +00:00
|
|
|
logger.debug(
|
|
|
|
"New font width: %f, normal font: %f, factor: %f",
|
|
|
|
new_width,
|
|
|
|
old_width,
|
|
|
|
self.scaleFactor,
|
|
|
|
)
|
2019-11-03 18:27:49 +00:00
|
|
|
# TODO: Update all the fixed widths to account for the scaling
|
|
|
|
for m in self.markers:
|
2020-07-19 14:38:03 +00:00
|
|
|
m.get_data_layout().setFont(font)
|
2019-11-03 18:27:49 +00:00
|
|
|
m.setScale(self.scaleFactor)
|
|
|
|
|
2020-07-27 15:05:11 +00:00
|
|
|
def update_sweep_title(self):
|
2019-12-12 14:16:37 +00:00
|
|
|
for c in self.subscribing_charts:
|
2020-07-27 15:05:11 +00:00
|
|
|
c.setSweepTitle(self.sweep.properties.name)
|