From 2f69f5c154dad5d2addb1e787b6a7dcb37e75eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Tue, 13 Sep 2022 18:46:02 +0200 Subject: [PATCH 01/11] More int float issues fixed. --- NanoVNASaver/Charts/Permeability.py | 24 ++++++++++++------------ NanoVNASaver/Charts/RI.py | 8 ++++---- NanoVNASaver/Charts/SParam.py | 12 +++++++++--- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/NanoVNASaver/Charts/Permeability.py b/NanoVNASaver/Charts/Permeability.py index d0b9d39c..159ed38a 100644 --- a/NanoVNASaver/Charts/Permeability.py +++ b/NanoVNASaver/Charts/Permeability.py @@ -46,15 +46,15 @@ def __init__(self, name=""): self.minDisplayValue = -100 def logarithmicYAllowed(self) -> bool: - return True; + return True def copy(self): - new_chart: PermeabilityChart = super().copy() - return new_chart + return super().copy() def drawChart(self, qp: QtGui.QPainter): qp.setPen(QtGui.QPen(Chart.color.text)) - qp.drawText(self.leftMargin + 5, 15, self.name + " (\N{MICRO SIGN}\N{OHM SIGN} / Hz)") + qp.drawText(self.leftMargin + 5, 15, self.name + + " (\N{MICRO SIGN}\N{OHM SIGN} / Hz)") qp.drawText(10, 15, "R") qp.drawText(self.leftMargin + self.dim.width + 10, 15, "X") qp.setPen(QtGui.QPen(Chart.color.foreground)) @@ -281,11 +281,11 @@ def getImYPosition(self, d: Datapoint) -> int: span = math.log(self.max) - math.log(min_val) else: return -1 - return self.topMargin + round( - (math.log(self.max) - math.log(im)) / + return int( + self.topMargin + (math.log(self.max) - math.log(im)) / span * self.dim.height) - return self.topMargin + round( - (self.max - im) / self.span * self.dim.height) + return int(self.topMargin + (self.max - im) / + self.span * self.dim.height) def getReYPosition(self, d: Datapoint) -> int: re = d.impedance().real @@ -296,11 +296,11 @@ def getReYPosition(self, d: Datapoint) -> int: span = math.log(self.max) - math.log(min_val) else: return -1 - return self.topMargin + round( - (math.log(self.max) - math.log(re)) / + return int( + self.topMargin + (math.log(self.max) - math.log(re)) / span * self.dim.height) - return self.topMargin + round( - (self.max - re) / self.span * self.dim.height) + return int( + self.topMargin + (self.max - re) / self.span * self.dim.height) def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin diff --git a/NanoVNASaver/Charts/RI.py b/NanoVNASaver/Charts/RI.py index 078ea0cc..96962dde 100644 --- a/NanoVNASaver/Charts/RI.py +++ b/NanoVNASaver/Charts/RI.py @@ -368,13 +368,13 @@ def drawValues(self, qp: QtGui.QPainter): def getImYPosition(self, d: Datapoint) -> int: im = self.impedance(d).imag - return (self.topMargin + int(self.max_imag - im) // self.span_imag - * self.dim.height) + return int(self.topMargin + (self.max_imag - im) / self.span_imag + * self.dim.height) def getReYPosition(self, d: Datapoint) -> int: re = self.impedance(d).real - return (self.topMargin + int(self.max_real - re) // self.span_real - * self.dim.height if math.isfinite(re) else self.topMargin) + return int(self.topMargin + (self.max_real - re) / self.span_real + * self.dim.height if math.isfinite(re) else self.topMargin) def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin diff --git a/NanoVNASaver/Charts/SParam.py b/NanoVNASaver/Charts/SParam.py index 7bd4e974..bf8e494e 100644 --- a/NanoVNASaver/Charts/SParam.py +++ b/NanoVNASaver/Charts/SParam.py @@ -107,13 +107,19 @@ def drawValues(self, qp: QtGui.QPainter): self.drawMarkers(qp, y_function=self.getImYPosition) def getYPosition(self, d: Datapoint) -> int: - return self.topMargin + (self.maxValue - d.re) // self.span * self.dim.height + return int( + self.topMargin + (self.maxValue - d.re) / self.span * + self.dim.height) def getReYPosition(self, d: Datapoint) -> int: - return self.topMargin + (self.maxValue - d.re) // self.span * self.dim.height + return int( + self.topMargin + (self.maxValue - d.re) / self.span * + self.dim.height) def getImYPosition(self, d: Datapoint) -> int: - return self.topMargin + (self.maxValue - d.im) // self.span * self.dim.height + return int( + self.topMargin + (self.maxValue - d.im) / self.span * + self.dim.height) def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin From 4159c705583926ac733ba55be78d099cb598b286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Wed, 14 Sep 2022 19:00:25 +0200 Subject: [PATCH 02/11] Imports and linebreaks adjusted --- NanoVNASaver/SITools.py | 52 ++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/NanoVNASaver/SITools.py b/NanoVNASaver/SITools.py index c2c75468..131ab607 100644 --- a/NanoVNASaver/SITools.py +++ b/NanoVNASaver/SITools.py @@ -18,8 +18,8 @@ # along with this program. If not, see . from __future__ import annotations import math -import decimal -from typing import NamedTuple, Union +from decimal import Context, Decimal, InvalidOperation +from typing import NamedTuple from numbers import Number, Real PREFIXES = ("y", "z", "a", "f", "p", "n", "ยต", "m", @@ -28,11 +28,7 @@ def clamp_value(value: Real, rmin: Real, rmax: Real) -> Real: assert rmin <= rmax - if value < rmin: - return rmin - if value > rmax: - return rmax - return value + return rmin if value < rmin else min(value, rmax) def round_ceil(value: Real, digits: int = 0) -> Real: @@ -65,12 +61,9 @@ class Format(NamedTuple): class Value: - CTX = decimal.Context(prec=60, Emin=-27, Emax=27) + CTX = Context(prec=60, Emin=-27, Emax=27) - def __init__(self, - value: Union[Number, str] = 0, - unit: str = "", - fmt=Format()): + def __init__(self, value: Real, unit: str = "", fmt=Format()): assert 1 <= fmt.max_nr_digits <= 30 assert -8 <= fmt.min_offset <= fmt.max_offset <= 8 assert fmt.parse_clamp_min < fmt.parse_clamp_max @@ -78,10 +71,10 @@ def __init__(self, self._unit = unit self.fmt = fmt if isinstance(value, str): - self._value = math.nan + self._value = Decimal(math.nan) self.parse(value) else: - self._value = decimal.Decimal(value, context=Value.CTX) + self._value = Decimal(value, context=Value.CTX) def __repr__(self) -> str: return (f"{self.__class__.__name__}(" @@ -89,18 +82,18 @@ def __repr__(self) -> str: def __str__(self) -> str: fmt = self.fmt - if fmt.assume_infinity and abs(self._value) >= 10 ** ((fmt.max_offset + 1) * 3): - return ("-" if self._value < 0 else "") + "\N{INFINITY}" + fmt.space_str + self._unit + if (fmt.assume_infinity and + abs(self._value) >= 10 ** ((fmt.max_offset + 1) * 3)): + return (("-" if self._value < 0 else "") + + "\N{INFINITY}" + fmt.space_str + self._unit) if self._value < fmt.printable_min: return fmt.unprintable_under + self._unit if self._value > fmt.printable_max: return fmt.unprintable_over + self._unit - if self._value == 0: - offset = 0 - else: - offset = clamp_value( - int(math.log10(abs(self._value)) // 3), fmt.min_offset, fmt.max_offset) + offset = clamp_value( + int(math.log10(abs(self._value)) // 3), + fmt.min_offset, fmt.max_offset) if self._value else 0 real = float(self._value) / (10 ** (offset * 3)) @@ -108,8 +101,8 @@ def __str__(self) -> str: formstr = ".0f" else: max_digits = fmt.max_nr_digits + ( - (1 if not fmt.fix_decimals and abs(real) < 10 else 0) + - (1 if not fmt.fix_decimals and abs(real) < 100 else 0)) + (1 if not fmt.fix_decimals and abs(real) < 10 else 0) + + (1 if not fmt.fix_decimals and abs(real) < 100 else 0)) formstr = f".{max_digits - 3}f" if self.fmt.allways_signed: @@ -136,7 +129,7 @@ def value(self): @value.setter def value(self, value: Number): - self._value = decimal.Decimal(value, context=Value.CTX) + self._value = Decimal(value, context=Value.CTX) def parse(self, value: str) -> "Value": if isinstance(value, Number): @@ -166,12 +159,13 @@ def parse(self, value: str) -> "Value": self._value = -math.inf else: try: - self._value = (decimal.Decimal(value, context=Value.CTX) - * decimal.Decimal(factor, context=Value.CTX)) - except decimal.InvalidOperation as exc: + self._value = (Decimal(value, context=Value.CTX) + * Decimal(factor, context=Value.CTX)) + except InvalidOperation as exc: raise ValueError() from exc - self._value = clamp_value( - self._value, self.fmt.parse_clamp_min, self.fmt.parse_clamp_max) + self._value = clamp_value(self._value, + self.fmt.parse_clamp_min, + self.fmt.parse_clamp_max) return self @property From d86cbec7c4d27659923e2e63f36e6c030dd87ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Thu, 15 Sep 2022 07:51:28 +0200 Subject: [PATCH 03/11] Cast varible type to int --- NanoVNASaver/Charts/Smith.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NanoVNASaver/Charts/Smith.py b/NanoVNASaver/Charts/Smith.py index 1f82dcd4..43b7c51b 100644 --- a/NanoVNASaver/Charts/Smith.py +++ b/NanoVNASaver/Charts/Smith.py @@ -39,7 +39,7 @@ def drawChart(self, qp: QtGui.QPainter) -> None: center_x + width_2, center_y) qp.drawEllipse( - QtCore.QPoint(center_x + int(self.dim.width/4), center_y), + QtCore.QPoint(center_x + int(self.dim.width / 4), center_y), self.dim.width // 4, self.dim.height // 4) # Re(Z) = 1 qp.drawEllipse( QtCore.QPoint(center_x + self.dim.width // 3, center_y), @@ -71,13 +71,13 @@ def drawChart(self, qp: QtGui.QPainter) -> None: -90 * 16, -127 * 16) # Im(Z) = 2 qp.drawArc(center_x, center_y, self.dim.width, self.dim.height, - 90*16, 90*16) # Im(Z) = -1 + 90 * 16, 90 * 16) # Im(Z) = -1 qp.drawArc(center_x, center_y, self.dim.width, - self.dim.height, -90 * 16, -90 * 16) # Im(Z) = 1 qp.drawArc(center_x - width_2, center_y, self.dim.width * 2, self.dim.height * 2, - int(99.5*16), int(43.5*16)) # Im(Z) = -0.5 + int(99.5 * 16), int(43.5 * 16)) # Im(Z) = -0.5 qp.drawArc(center_x - width_2, center_y, self.dim.width * 2, -self.dim.height * 2, int(-99.5 * 16), int(-43.5 * 16)) # Im(Z) = 0.5 @@ -94,8 +94,8 @@ def drawChart(self, qp: QtGui.QPainter) -> None: for swr in self.swrMarkers: if swr <= 1: continue - gamma = (swr - 1)/(swr + 1) - r = gamma * self.dim.width // 2 + gamma = (swr - 1) / (swr + 1) + r = int(gamma * self.dim.width / 2) qp.drawEllipse(QtCore.QPoint(center_x, center_y), r, r) qp.drawText( QtCore.QRect(center_x - 50, center_y - 4 + r, 100, 20), From 8bc452d48f0210141bf9d8eec0e4c7860bd4a3b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Thu, 15 Sep 2022 07:53:08 +0200 Subject: [PATCH 04/11] Linting Charts --- NanoVNASaver/Charts/Chart.py | 24 +++++---- NanoVNASaver/Charts/Frequency.py | 3 +- NanoVNASaver/Charts/GroupDelay.py | 10 ++-- NanoVNASaver/Charts/LogMag.py | 4 +- NanoVNASaver/Charts/Magnitude.py | 74 +++++++++++-------------- NanoVNASaver/Charts/MagnitudeZ.py | 12 +++-- NanoVNASaver/Charts/Permeability.py | 84 +++++++++++++---------------- NanoVNASaver/Charts/QFactor.py | 37 ++++++------- NanoVNASaver/Charts/RI.py | 50 ++++++++--------- NanoVNASaver/Charts/SParam.py | 3 +- NanoVNASaver/Charts/Square.py | 27 +++++----- NanoVNASaver/Charts/VSWR.py | 64 ++++++++++------------ 12 files changed, 188 insertions(+), 204 deletions(-) diff --git a/NanoVNASaver/Charts/Chart.py b/NanoVNASaver/Charts/Chart.py index dab7a402..4b8f037b 100644 --- a/NanoVNASaver/Charts/Chart.py +++ b/NanoVNASaver/Charts/Chart.py @@ -19,7 +19,7 @@ import logging from dataclasses import dataclass, replace -from typing import List, Set, Tuple, ClassVar, Any +from typing import List, Set, Tuple, ClassVar, Any, Optional from PyQt5 import QtWidgets, QtGui, QtCore from PyQt5.QtCore import pyqtSignal @@ -37,12 +37,13 @@ class ChartColors: # pylint: disable=too-many-instance-attributes foreground: QtGui.QColor = QtGui.QColor(QtCore.Qt.lightGray) reference: QtGui.QColor = QtGui.QColor(0, 0, 255, 64) reference_secondary: QtGui.QColor = QtGui.QColor(0, 0, 192, 48) - sweep: QtGui.QColor = QtGui.QColor(QtCore.Qt.darkYellow) + sweep: QtGui.QColor = QtGui.QColor(QtCore.Qt.darkYellow) sweep_secondary: QtGui.QColor = QtGui.QColor(QtCore.Qt.darkMagenta) swr: QtGui.QColor = QtGui.QColor(255, 0, 0, 128) text: QtGui.QColor = QtGui.QColor(QtCore.Qt.black) bands: QtGui.QColor = QtGui.QColor(128, 128, 128, 48) + @dataclass class ChartDimensions: height: int = 200 @@ -52,14 +53,16 @@ class ChartDimensions: line: int = 1 point: int = 2 + @dataclass class ChartDragBox: - pos: Tuple[int] = (-1, -1) + pos: Tuple[int] = (-1, -1) pos_start: Tuple[int] = (0, 0) state: bool = False move_x: int = -1 move_y: int = -1 + @dataclass class ChartFlags: draw_lines: bool = False @@ -121,7 +124,8 @@ def __init__(self, name): self.swrMarkers: Set[float] = set() self.action_popout = QtWidgets.QAction("Popout chart") - self.action_popout.triggered.connect(lambda: self.popoutRequested.emit(self)) + self.action_popout.triggered.connect( + lambda: self.popoutRequested.emit(self)) self.addAction(self.action_popout) self.action_save_screenshot = QtWidgets.QAction("Save image") @@ -176,8 +180,8 @@ def getActiveMarker(self) -> Marker: None, ) - def getNearestMarker(self, x, y) -> Marker: - if len(self.data) == 0: + def getNearestMarker(self, x, y) -> Optional[Marker]: + if not self.data: return None shortest = 10**6 nearest = None @@ -218,13 +222,13 @@ def mousePressEvent(self, event: QtGui.QMouseEvent) -> None: def mouseReleaseEvent(self, a0: QtGui.QMouseEvent): self.draggedMarker = None if self.dragbox.state: - self.zoomTo(self.dragbox.pos_start[0], self.dragbox.pos_start[1], a0.x(), a0.y()) + self.zoomTo( + self.dragbox.pos_start[0], self.dragbox.pos_start[1], a0.x(), a0.y()) self.dragbox.state = False self.dragbox.pos = (-1, -1) self.dragbox.pos_start = (0, 0) self.update() - def wheelEvent(self, a0: QtGui.QWheelEvent) -> None: delta = a0.angleDelta().y() if not delta or (not self.data and not self.reference): @@ -305,7 +309,7 @@ def clearSWRMarkers(self): @staticmethod def drawMarker(x: int, y: int, qp: QtGui.QPainter, color: QtGui.QColor, - number: int=0): + number: int = 0): cmarker = ChartMarker(qp) cmarker.draw(x, y, color, f"{number}") @@ -314,7 +318,7 @@ def drawTitle(self, qp: QtGui.QPainter, position: QtCore.QPoint = None): if position is None: qf = QtGui.QFontMetricsF(self.font()) width = qf.boundingRect(self.sweepTitle).width() - position = QtCore.QPointF(self.width()/2 - width/2, 15) + position = QtCore.QPointF(self.width() / 2 - width / 2, 15) qp.drawText(position, self.sweepTitle) def update(self): diff --git a/NanoVNASaver/Charts/Frequency.py b/NanoVNASaver/Charts/Frequency.py index cda2c850..0e925076 100644 --- a/NanoVNASaver/Charts/Frequency.py +++ b/NanoVNASaver/Charts/Frequency.py @@ -236,8 +236,7 @@ def setLogarithmicY(self, logarithmic: bool): self.logarithmicY = logarithmic and self.logarithmicYAllowed() self.update() - @staticmethod - def logarithmicYAllowed() -> bool: + def logarithmicYAllowed(self) -> bool: return False def setMinimumFrequency(self): diff --git a/NanoVNASaver/Charts/GroupDelay.py b/NanoVNASaver/Charts/GroupDelay.py index 1db1a912..ae58d83b 100644 --- a/NanoVNASaver/Charts/GroupDelay.py +++ b/NanoVNASaver/Charts/GroupDelay.py @@ -88,8 +88,8 @@ def calc_data(self, data: List[Datapoint]): phase_change = unwrapped[-1] - unwrapped[-2] freq_change = d.freq - data[-2].freq else: - phase_change = unwrapped[i+1] - unwrapped[i-1] - freq_change = data[i+1].freq - data[i-1].freq + phase_change = unwrapped[i + 1] - unwrapped[i - 1] + freq_change = data[i + 1].freq - data[i - 1].freq delay = (-phase_change / (freq_change * 360)) * 10e8 if not self.reflective: delay /= 2 @@ -124,7 +124,8 @@ def drawValues(self, qp: QtGui.QPainter): tickcount = math.floor(self.dim.height / 60) for i in range(tickcount): delay = min_delay + span * i / tickcount - y = self.topMargin + round((self.maxDelay - delay) / self.span * self.dim.height) + y = self.topMargin + \ + round((self.maxDelay - delay) / self.span * self.dim.height) if delay not in {min_delay, max_delay}: qp.setPen(QtGui.QPen(Chart.color.text)) # TODO use format class @@ -133,7 +134,8 @@ def drawValues(self, qp: QtGui.QPainter): delaystr = str(round(delay, digits if digits != 0 else None)) qp.drawText(3, y + 3, delaystr) qp.setPen(QtGui.QPen(Chart.color.foreground)) - qp.drawLine(self.leftMargin - 5, y, self.leftMargin + self.dim.width, y) + qp.drawLine(self.leftMargin - 5, y, + self.leftMargin + self.dim.width, y) qp.drawLine(self.leftMargin - 5, self.topMargin, diff --git a/NanoVNASaver/Charts/LogMag.py b/NanoVNASaver/Charts/LogMag.py index ee36aabe..c0852bd0 100644 --- a/NanoVNASaver/Charts/LogMag.py +++ b/NanoVNASaver/Charts/LogMag.py @@ -160,8 +160,8 @@ def draw_swr_markers(self, qp) -> None: def getYPosition(self, d: Datapoint) -> int: logMag = self.logMag(d) if math.isinf(logMag): - return None - return self.topMargin + round( + return self.topMargin + return self.topMargin + int( (self.maxValue - logMag) / self.span * self.dim.height) def valueAtPosition(self, y) -> List[float]: diff --git a/NanoVNASaver/Charts/Magnitude.py b/NanoVNASaver/Charts/Magnitude.py index 18be21c6..2c885134 100644 --- a/NanoVNASaver/Charts/Magnitude.py +++ b/NanoVNASaver/Charts/Magnitude.py @@ -33,18 +33,15 @@ def __init__(self, name=""): super().__init__(name) self.minDisplayValue = 0 - self.maxDisplayValue = 1 self.fixedValues = True self.y_action_fixed_span.setChecked(True) self.y_action_automatic.setChecked(False) self.minValue = 0 - self.maxValue = 1 - self.span = 1 def drawValues(self, qp: QtGui.QPainter): - if len(self.data) == 0 and len(self.reference) == 0: + if not self.data and not self.reference: return self._set_start_stop() @@ -54,71 +51,62 @@ def drawValues(self, qp: QtGui.QPainter): self.drawBands(qp, self.fstart, self.fstop) if self.fixedValues: - maxValue = self.maxDisplayValue - minValue = self.minDisplayValue - self.maxValue = maxValue - self.minValue = minValue + max_value = self.maxDisplayValue + min_value = self.minDisplayValue else: # Find scaling - minValue = 100 - maxValue = 0 + min_value = 100 + max_value = 0 for d in self.data: mag = self.magnitude(d) - if mag > maxValue: - maxValue = mag - if mag < minValue: - minValue = mag + max_value = max(max_value, mag) + min_value = min(min_value, mag) for d in self.reference: # Also check min/max for the reference sweep if d.freq < self.fstart or d.freq > self.fstop: continue - mag = self.magnitude(d) - if mag > maxValue: - maxValue = mag - if mag < minValue: - minValue = mag - - minValue = 10*math.floor(minValue/10) - self.minValue = minValue - maxValue = 10*math.ceil(maxValue/10) - self.maxValue = maxValue + max_value = max(max_value, mag) + min_value = min(min_value, mag) + min_value = 10 * math.floor(min_value / 10) + max_value = 10 * math.ceil(max_value / 10) - span = maxValue-minValue - if span == 0: - span = 0.01 - self.span = span + self.maxValue = max_value + self.minValue = min_value - target_ticks = math.floor(self.dim.height / 60) + self.span = (max_value - min_value) or 0.01 + target_ticks = int(self.dim.height // 60) for i in range(target_ticks): - val = minValue + i / target_ticks * span - y = self.topMargin + round((self.maxValue - val) / self.span * self.dim.height) + val = min_value + i / target_ticks * self.span + y = self.topMargin + int((self.maxValue - val) / self.span + * self.dim.height) qp.setPen(Chart.color.text) - if val != minValue: + if val != min_value: digits = max(0, min(2, math.floor(3 - math.log10(abs(val))))) - if digits == 0: - vswrstr = str(round(val)) - else: - vswrstr = str(round(val, digits)) + vswrstr = (str(round(val)) if digits == 0 else + str(round(val, digits))) qp.drawText(3, y + 3, vswrstr) qp.setPen(QtGui.QPen(Chart.color.foreground)) - qp.drawLine(self.leftMargin - 5, y, self.leftMargin + self.dim.width, y) + qp.drawLine(self.leftMargin - 5, y, + self.leftMargin + self.dim.width, y) qp.setPen(QtGui.QPen(Chart.color.foreground)) qp.drawLine(self.leftMargin - 5, self.topMargin, self.leftMargin + self.dim.width, self.topMargin) qp.setPen(Chart.color.text) - qp.drawText(3, self.topMargin + 4, str(maxValue)) - qp.drawText(3, self.dim.height+self.topMargin, str(minValue)) + qp.drawText(3, self.topMargin + 4, str(max_value)) + qp.drawText(3, self.dim.height + self.topMargin, str(min_value)) self.drawFrequencyTicks(qp) qp.setPen(Chart.color.swr) for vswr in self.swrMarkers: if vswr <= 1: continue - mag = (vswr-1)/(vswr+1) - y = self.topMargin + round((self.maxValue - mag) / self.span * self.dim.height) - qp.drawLine(self.leftMargin, y, self.leftMargin + self.dim.width, y) - qp.drawText(self.leftMargin + 3, y - 1, "VSWR: " + str(vswr)) + mag = (vswr - 1) / (vswr + 1) + y = self.topMargin + int((self.maxValue - mag) / self.span + * self.dim.height) + qp.drawLine(self.leftMargin, y, + self.leftMargin + self.dim.width, y) + qp.drawText(self.leftMargin + 3, y - 1, f"VSWR: {vswr}") self.drawData(qp, self.data, Chart.color.sweep) self.drawData(qp, self.reference, Chart.color.reference) diff --git a/NanoVNASaver/Charts/MagnitudeZ.py b/NanoVNASaver/Charts/MagnitudeZ.py index d325b126..9f1e43de 100644 --- a/NanoVNASaver/Charts/MagnitudeZ.py +++ b/NanoVNASaver/Charts/MagnitudeZ.py @@ -45,7 +45,7 @@ def __init__(self, name=""): self.span = 1 def drawValues(self, qp: QtGui.QPainter): - if len(self.data) == 0 and len(self.reference) == 0: + if not self.data and not self.reference: return self._set_start_stop() @@ -56,8 +56,9 @@ def drawValues(self, qp: QtGui.QPainter): if self.fixedValues: self.maxValue = self.maxDisplayValue - self.minValue = max( - self.minDisplayValue, 0.01) if self.logarithmicY else self.minDisplayValue + self.minValue = ( + max(self.minDisplayValue, 0.01) if self.logarithmicY else + self.minDisplayValue) else: # Find scaling self.minValue = 100 @@ -85,7 +86,7 @@ def drawValues(self, qp: QtGui.QPainter): self.span = (self.maxValue - self.minValue) or 0.01 # We want one horizontal tick per 50 pixels, at most - horizontal_ticks = math.floor(self.dim.height/50) + horizontal_ticks = int(self.dim.height / 50) fmt = Format(max_nr_digits=4) for i in range(horizontal_ticks): y = self.topMargin + round(i * self.dim.height / horizontal_ticks) @@ -122,7 +123,8 @@ def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin if self.logarithmicY: span = math.log(self.maxValue) - math.log(self.minValue) - val = math.exp(math.log(self.maxValue) - absy * span / self.dim.height) + val = math.exp(math.log(self.maxValue) - + absy * span / self.dim.height) else: val = self.maxValue - (absy / self.dim.height * self.span) return [val] diff --git a/NanoVNASaver/Charts/Permeability.py b/NanoVNASaver/Charts/Permeability.py index 159ed38a..cb95323a 100644 --- a/NanoVNASaver/Charts/Permeability.py +++ b/NanoVNASaver/Charts/Permeability.py @@ -48,9 +48,6 @@ def __init__(self, name=""): def logarithmicYAllowed(self) -> bool: return True - def copy(self): - return super().copy() - def drawChart(self, qp: QtGui.QPainter): qp.setPen(QtGui.QPen(Chart.color.text)) qp.drawText(self.leftMargin + 5, 15, self.name + @@ -58,15 +55,20 @@ def drawChart(self, qp: QtGui.QPainter): qp.drawText(10, 15, "R") qp.drawText(self.leftMargin + self.dim.width + 10, 15, "X") qp.setPen(QtGui.QPen(Chart.color.foreground)) - qp.drawLine(self.leftMargin, self.topMargin - 5, - self.leftMargin, self.topMargin + self.dim.height + 5) - qp.drawLine(self.leftMargin-5, self.topMargin + self.dim.height, - self.leftMargin + self.dim.width + 5, self.topMargin + self.dim.height) + qp.drawLine(self.leftMargin, + self.topMargin - 5, + self.leftMargin, + self.topMargin + self.dim.height + 5) + qp.drawLine(self.leftMargin - 5, + self.topMargin + self.dim.height, + self.leftMargin + self.dim.width + 5, + self.topMargin + self.dim.height) self.drawTitle(qp) def drawValues(self, qp: QtGui.QPainter): - if len(self.data) == 0 and len(self.reference) == 0: + if not self.data and not self.reference: return + pen = QtGui.QPen(Chart.color.sweep) pen.setWidth(self.dim.point) line_pen = QtGui.QPen(Chart.color.sweep) @@ -90,14 +92,10 @@ def drawValues(self, qp: QtGui.QPainter): re, im = imp.real, imp.imag re = re * 10e6 / d.freq im = im * 10e6 / d.freq - if re > max_val: - max_val = re - if re < min_val: - min_val = re - if im > max_val: - max_val = im - if im < min_val: - min_val = im + max_val = max(max_val, re) + max_val = max(max_val, im) + min_val = min(min_val, re) + min_val = min(min_val, im) for d in self.reference: # Also check min/max for the reference sweep if d.freq < self.fstart or d.freq > self.fstop: continue @@ -105,27 +103,19 @@ def drawValues(self, qp: QtGui.QPainter): re, im = imp.real, imp.imag re = re * 10e6 / d.freq im = im * 10e6 / d.freq - if re > max_val: - max_val = re - if re < min_val: - min_val = re - if im > max_val: - max_val = im - if im < min_val: - min_val = im + max_val = max(max_val, re) + max_val = max(max_val, im) + min_val = min(min_val, re) + min_val = min(min_val, im) if self.logarithmicY: min_val = max(0.01, min_val) self.max = max_val - - span = max_val - min_val - if span == 0: - span = 0.01 - self.span = span + self.span = (max_val - min_val) or 0.01 # We want one horizontal tick per 50 pixels, at most - horizontal_ticks = math.floor(self.dim.height/50) + horizontal_ticks = math.floor(self.dim.height / 50) fmt = Format(max_nr_digits=4) for i in range(horizontal_ticks): y = self.topMargin + round(i * self.dim.height / horizontal_ticks) @@ -163,10 +153,10 @@ def drawValues(self, qp: QtGui.QPainter): secondary_pen.setWidth(self.dim.point) line_pen.setWidth(self.dim.line) - for i in range(len(self.data)): - x = self.getXPosition(self.data[i]) - y_re = self.getReYPosition(self.data[i]) - y_im = self.getImYPosition(self.data[i]) + for i, data in enumerate(self.data): + x = self.getXPosition(data) + y_re = self.getReYPosition(data) + y_im = self.getImYPosition(data) qp.setPen(primary_pen) if self.isPlotable(x, y_re): qp.drawPoint(x, y_re) @@ -175,8 +165,8 @@ def drawValues(self, qp: QtGui.QPainter): qp.drawPoint(x, y_im) if self.flag.draw_lines and i > 0: prev_x = self.getXPosition(self.data[i - 1]) - prev_y_re = self.getReYPosition(self.data[i-1]) - prev_y_im = self.getImYPosition(self.data[i-1]) + prev_y_re = self.getReYPosition(self.data[i - 1]) + prev_y_im = self.getImYPosition(self.data[i - 1]) # Real part first line_pen.setColor(Chart.color.sweep) @@ -221,12 +211,12 @@ def drawValues(self, qp: QtGui.QPainter): qp.drawLine(self.leftMargin + self.dim.width, 14, self.leftMargin + self.dim.width + 5, 14) - for i in range(len(self.reference)): - if self.reference[i].freq < self.fstart or self.reference[i].freq > self.fstop: + for i, reference in enumerate(self.reference): + if reference.freq < self.fstart or reference.freq > self.fstop: continue - x = self.getXPosition(self.reference[i]) - y_re = self.getReYPosition(self.reference[i]) - y_im = self.getImYPosition(self.reference[i]) + x = self.getXPosition(reference) + y_re = self.getReYPosition(reference) + y_im = self.getImYPosition(reference) qp.setPen(primary_pen) if self.isPlotable(x, y_re): qp.drawPoint(x, y_re) @@ -235,8 +225,8 @@ def drawValues(self, qp: QtGui.QPainter): qp.drawPoint(x, y_im) if self.flag.draw_lines and i > 0: prev_x = self.getXPosition(self.reference[i - 1]) - prev_y_re = self.getReYPosition(self.reference[i-1]) - prev_y_im = self.getImYPosition(self.reference[i-1]) + prev_y_re = self.getReYPosition(self.reference[i - 1]) + prev_y_im = self.getImYPosition(self.reference[i - 1]) line_pen.setColor(Chart.color.reference) qp.setPen(line_pen) @@ -269,8 +259,10 @@ def drawValues(self, qp: QtGui.QPainter): y_re = self.getReYPosition(self.data[m.location]) y_im = self.getImYPosition(self.data[m.location]) - self.drawMarker(x, y_re, qp, m.color, self.markers.index(m)+1) - self.drawMarker(x, y_im, qp, m.color, self.markers.index(m)+1) + self.drawMarker(x, y_re, qp, m.color, + self.markers.index(m) + 1) + self.drawMarker(x, y_im, qp, m.color, + self.markers.index(m) + 1) def getImYPosition(self, d: Datapoint) -> int: im = d.impedance().imag @@ -326,7 +318,7 @@ def getNearestMarker(self, x, y) -> Marker: myr = self.getReYPosition(self.data[m.location]) myi = self.getImYPosition(self.data[m.location]) dx = abs(x - mx) - dy = min(abs(y - myr), abs(y-myi)) + dy = min(abs(y - myr), abs(y - myi)) distance = math.sqrt(dx**2 + dy**2) if distance < shortest: shortest = distance diff --git a/NanoVNASaver/Charts/QFactor.py b/NanoVNASaver/Charts/QFactor.py index ed955464..b8e620ed 100644 --- a/NanoVNASaver/Charts/QFactor.py +++ b/NanoVNASaver/Charts/QFactor.py @@ -49,19 +49,17 @@ def drawChart(self, qp: QtGui.QPainter): # Make up some sensible scaling here if self.fixedValues: maxQ = self.maxDisplayValue - minQ = self.minDisplayValue else: - minQ = 0 maxQ = 0 for d in self.data: Q = d.qFactor() - if Q > maxQ: - maxQ = Q + maxQ = max(maxQ, Q) scale = 0 if maxQ > 0: scale = max(scale, math.floor(math.log10(maxQ))) maxQ = math.ceil(maxQ / 10 ** scale) * 10 ** scale - self.minQ = minQ + + self.minQ = self.minDisplayValue self.maxQ = maxQ self.span = self.maxQ - self.minQ if self.span == 0: @@ -71,28 +69,30 @@ def drawChart(self, qp: QtGui.QPainter): for i in range(tickcount): q = self.minQ + i * self.span / tickcount - y = self.topMargin + round((self.maxQ - q) / self.span * self.dim.height) + y = self.topMargin + int((self.maxQ - q) / self.span * + self.dim.height) + q = round(q) if q < 10: q = round(q, 2) - elif q < 20: + if q < 20: q = round(q, 1) - else: - q = round(q) qp.setPen(QtGui.QPen(Chart.color.text)) - qp.drawText(3, y+3, str(q)) + qp.drawText(3, y + 3, str(q)) qp.setPen(QtGui.QPen(Chart.color.foreground)) - qp.drawLine(self.leftMargin-5, y, self.leftMargin + self.dim.width, y) + qp.drawLine(self.leftMargin - 5, y, + self.leftMargin + self.dim.width, y) qp.drawLine(self.leftMargin - 5, self.topMargin, - self.leftMargin + self.dim.width, self.topMargin) + self.leftMargin + self.dim.width, + self.topMargin) qp.setPen(Chart.color.text) + + max_q = round(maxQ) if maxQ < 10: - qstr = str(round(maxQ, 2)) + max_q = round(maxQ, 2) elif maxQ < 20: - qstr = str(round(maxQ, 1)) - else: - qstr = str(round(maxQ)) - qp.drawText(3, 35, qstr) + max_q = round(maxQ, 1) + qp.drawText(3, 35, f"{max_q}") def drawValues(self, qp: QtGui.QPainter): if len(self.data) == 0 and len(self.reference) == 0: @@ -119,7 +119,8 @@ def drawValues(self, qp: QtGui.QPainter): def getYPosition(self, d: Datapoint) -> int: Q = d.qFactor() - return self.topMargin + round((self.maxQ - Q) / self.span * self.dim.height) + return self.topMargin + int((self.maxQ - Q) / self.span * + self.dim.height) def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin diff --git a/NanoVNASaver/Charts/RI.py b/NanoVNASaver/Charts/RI.py index 96962dde..567781b9 100644 --- a/NanoVNASaver/Charts/RI.py +++ b/NanoVNASaver/Charts/RI.py @@ -18,7 +18,7 @@ # along with this program. If not, see . import math import logging -from typing import List +from typing import List, Optional from PyQt5 import QtWidgets, QtGui @@ -120,7 +120,7 @@ def drawChart(self, qp: QtGui.QPainter): self.topMargin - 5, self.leftMargin, self.topMargin + self.dim.height + 5) - qp.drawLine(self.leftMargin-5, + qp.drawLine(self.leftMargin - 5, self.topMargin + self.dim.height, self.leftMargin + self.dim.width + 5, self.topMargin + self.dim.height) @@ -195,13 +195,13 @@ def drawValues(self, qp: QtGui.QPainter): step_size = span / 8 if max_imag < step_size: # The 0 line is the first step after the top. Scale accordingly. - max_imag = -min_imag/7 + max_imag = -min_imag / 7 elif -min_imag < step_size: # The 0 line is the last step before the bottom. Scale accordingly. - min_imag = -max_imag/7 + min_imag = -max_imag / 7 else: # Scale max_imag to be a whole factor of min_imag - num_min = math.floor(min_imag/step_size * -1) + num_min = math.floor(min_imag / step_size * -1) num_max = 8 - num_min max_imag = num_max * (min_imag / num_min) * -1 @@ -257,10 +257,10 @@ def drawValues(self, qp: QtGui.QPainter): secondary_pen.setWidth(self.dim.point) line_pen.setWidth(self.dim.line) - for i in range(len(self.data)): - x = self.getXPosition(self.data[i]) - y_re = self.getReYPosition(self.data[i]) - y_im = self.getImYPosition(self.data[i]) + for i, data in enumerate(self.data): + x = self.getXPosition(data) + y_re = self.getReYPosition(data) + y_im = self.getImYPosition(data) qp.setPen(primary_pen) if self.isPlotable(x, y_re): qp.drawPoint(x, y_re) @@ -269,8 +269,8 @@ def drawValues(self, qp: QtGui.QPainter): qp.drawPoint(x, y_im) if self.flag.draw_lines and i > 0: prev_x = self.getXPosition(self.data[i - 1]) - prev_y_re = self.getReYPosition(self.data[i-1]) - prev_y_im = self.getImYPosition(self.data[i-1]) + prev_y_re = self.getReYPosition(self.data[i - 1]) + prev_y_im = self.getImYPosition(self.data[i - 1]) # Real part first line_pen.setColor(Chart.color.sweep) @@ -315,12 +315,12 @@ def drawValues(self, qp: QtGui.QPainter): qp.drawLine(self.leftMargin + self.dim.width, 14, self.leftMargin + self.dim.width + 5, 14) - for i in range(len(self.reference)): - if self.reference[i].freq < self.fstart or self.reference[i].freq > self.fstop: + for i, reference in enumerate(self.reference): + if reference.freq < self.fstart or reference.freq > self.fstop: continue - x = self.getXPosition(self.reference[i]) - y_re = self.getReYPosition(self.reference[i]) - y_im = self.getImYPosition(self.reference[i]) + x = self.getXPosition(reference) + y_re = self.getReYPosition(reference) + y_im = self.getImYPosition(reference) qp.setPen(primary_pen) if self.isPlotable(x, y_re): qp.drawPoint(x, y_re) @@ -329,8 +329,8 @@ def drawValues(self, qp: QtGui.QPainter): qp.drawPoint(x, y_im) if self.flag.draw_lines and i > 0: prev_x = self.getXPosition(self.reference[i - 1]) - prev_y_re = self.getReYPosition(self.reference[i-1]) - prev_y_im = self.getImYPosition(self.reference[i-1]) + prev_y_re = self.getReYPosition(self.reference[i - 1]) + prev_y_im = self.getImYPosition(self.reference[i - 1]) line_pen.setColor(Chart.color.reference) qp.setPen(line_pen) @@ -363,8 +363,10 @@ def drawValues(self, qp: QtGui.QPainter): y_re = self.getReYPosition(self.data[m.location]) y_im = self.getImYPosition(self.data[m.location]) - self.drawMarker(x, y_re, qp, m.color, self.markers.index(m)+1) - self.drawMarker(x, y_im, qp, m.color, self.markers.index(m)+1) + self.drawMarker(x, y_re, qp, m.color, + self.markers.index(m) + 1) + self.drawMarker(x, y_im, qp, m.color, + self.markers.index(m) + 1) def getImYPosition(self, d: Datapoint) -> int: im = self.impedance(d).imag @@ -405,17 +407,17 @@ def zoomTo(self, x1, y1, x2, y2): self.update() - def getNearestMarker(self, x, y) -> Marker: - if len(self.data) == 0: + def getNearestMarker(self, x, y) -> Optional[Marker]: + if not self.data: return None - shortest = 10**6 + shortest = 10e6 nearest = None for m in self.markers: mx, _ = self.getPosition(self.data[m.location]) myr = self.getReYPosition(self.data[m.location]) myi = self.getImYPosition(self.data[m.location]) dx = abs(x - mx) - dy = min(abs(y - myr), abs(y-myi)) + dy = min(abs(y - myr), abs(y - myi)) distance = math.sqrt(dx**2 + dy**2) if distance < shortest: shortest = distance diff --git a/NanoVNASaver/Charts/SParam.py b/NanoVNASaver/Charts/SParam.py index bf8e494e..832d00b9 100644 --- a/NanoVNASaver/Charts/SParam.py +++ b/NanoVNASaver/Charts/SParam.py @@ -16,7 +16,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import math import logging from typing import List @@ -54,7 +53,7 @@ def drawChart(self, qp: QtGui.QPainter): qp.drawText(self.leftMargin + self.dim.width - 15, 15, "Imag") qp.setPen(QtGui.QPen(Chart.color.foreground)) qp.drawLine(self.leftMargin, self.topMargin - 5, - self.leftMargin, self.topMargin + self.dim.height+5) + self.leftMargin, self.topMargin + self.dim.height + 5) qp.drawLine(self.leftMargin - 5, self.topMargin + self.dim.height, self.leftMargin + self.dim.width, self.topMargin + self.dim.height) diff --git a/NanoVNASaver/Charts/Square.py b/NanoVNASaver/Charts/Square.py index dbb4fab2..5213b20b 100644 --- a/NanoVNASaver/Charts/Square.py +++ b/NanoVNASaver/Charts/Square.py @@ -20,8 +20,7 @@ import math from typing import List -from PyQt5 import QtGui, QtCore -from PyQt5 import QtWidgets, QtGui +from PyQt5 import QtGui, QtCore, QtWidgets from NanoVNASaver.Charts.Chart import Chart from NanoVNASaver.RFTools import Datapoint @@ -55,7 +54,7 @@ def drawChart(self, qp: QtGui.QPainter) -> None: raise NotImplementedError() def draw_data(self, qp: QtGui.QPainter, color: QtGui.QColor, - data: List[Datapoint], fstart: int=0, fstop: int=0): + data: List[Datapoint], fstart: int = 0, fstop: int = 0): if not data: return fstop = fstop or data[-1].freq @@ -66,10 +65,11 @@ def draw_data(self, qp: QtGui.QPainter, color: QtGui.QColor, qp.setPen(pen) prev_x = self.getXPosition(data[0]) - prev_y = int(self.height() / 2 + data[0].im * -1 * self.dim.height / 2) + prev_y = int(self.height() / 2 + data[0].im * -1 * + self.dim.height / 2) for i, d in enumerate(data): x = self.getXPosition(d) - y = int(self.height()/2 + d.im * -1 * self.dim.height/2) + y = int(self.height() / 2 + d.im * -1 * self.dim.height / 2) if d.freq > fstart and d.freq < fstop: qp.drawPoint(x, y) if self.flag.draw_lines and i > 0: @@ -85,19 +85,21 @@ def drawValues(self, qp: QtGui.QPainter): fstart = self.data[0].freq if self.data else 0 fstop = self.data[-1].freq if self.data else 0 - self.draw_data(qp, Chart.color.reference, self.reference, fstart, fstop) + self.draw_data(qp, Chart.color.reference, + self.reference, fstart, fstop) for m in self.markers: if m.location != -1 and m.location < len(self.data): x = self.getXPosition(self.data[m.location]) - y = self.height() / 2 + self.data[m.location].im * -1 * self.dim.height / 2 - self.drawMarker(x, y, qp, m.color, self.markers.index(m)+1) + y = self.height() / 2 + \ + self.data[m.location].im * -1 * self.dim.height / 2 + self.drawMarker(x, y, qp, m.color, self.markers.index(m) + 1) def resizeEvent(self, a0: QtGui.QResizeEvent) -> None: if not self.flag.is_popout: self.setFixedWidth(a0.size().height()) - self.dim.width = a0.size().height()-40 - self.dim.height = a0.size().height()-40 + self.dim.width = a0.size().height() - 40 + self.dim.height = a0.size().height() - 40 else: min_dimension = min(a0.size().height(), a0.size().width()) self.dim.width = self.dim.height = min_dimension - 40 @@ -138,12 +140,11 @@ def mouseMoveEvent(self, a0: QtGui.QMouseEvent): m.setFrequency(str(round(target[minimum_position].freq))) m.frequencyInput.setText(str(round(target[minimum_position].freq))) - def getXPosition(self, d: Datapoint) -> int: - return int(self.width()/2 + d.re * self.dim.width/2) + return int(self.width() / 2 + d.re * self.dim.width / 2) def getYPosition(self, d: Datapoint) -> int: - return int(self.height()/2 + d.im * -1 * self.dim.height/2) + return int(self.height() / 2 + d.im * -1 * self.dim.height / 2) def zoomTo(self, x1, y1, x2, y2): pass diff --git a/NanoVNASaver/Charts/VSWR.py b/NanoVNASaver/Charts/VSWR.py index 56d3d4cc..e5e3ab4c 100644 --- a/NanoVNASaver/Charts/VSWR.py +++ b/NanoVNASaver/Charts/VSWR.py @@ -44,14 +44,15 @@ def logarithmicYAllowed(self) -> bool: return True def drawValues(self, qp: QtGui.QPainter): - if len(self.data) == 0 and len(self.reference) == 0: + if not self.data and not self.reference: return + if self.fixedSpan: fstart = self.minFrequency fstop = self.maxFrequency elif len(self.data) > 0: fstart = self.data[0].freq - fstop = self.data[len(self.data)-1].freq + fstop = self.data[len(self.data) - 1].freq else: fstart = self.reference[0].freq fstop = self.reference[len(self.reference) - 1].freq @@ -78,10 +79,7 @@ def drawValues(self, qp: QtGui.QPainter): except OverflowError: maxVSWR = self.maxDisplayValue self.maxVSWR = maxVSWR - span = maxVSWR-minVSWR - if span == 0: - span = 0.01 - self.span = span + self.span = (maxVSWR - minVSWR) or 0.01 target_ticks = math.floor(self.dim.height / 60) @@ -91,53 +89,49 @@ def drawValues(self, qp: QtGui.QPainter): vswr = self.valueAtPosition(y)[0] qp.setPen(Chart.color.text) if vswr != 0: - digits = max(0, min(2, math.floor(3 - math.log10(abs(vswr))))) - if digits == 0: - vswrstr = str(round(vswr)) - else: - vswrstr = str(round(vswr, digits)) - qp.drawText(3, y+3, vswrstr) + digits = max( + 0, min(2, math.floor(3 - math.log10(abs(vswr))))) + v_text = f"{round(vswr, digits)}" if digits else "0" + qp.drawText(3, y + 3, v_text) qp.setPen(QtGui.QPen(Chart.color.foreground)) - qp.drawLine(self.leftMargin-5, y, self.leftMargin+self.dim.width, y) - qp.drawLine(self.leftMargin - 5, self.topMargin + self.dim.height, - self.leftMargin + self.dim.width, self.topMargin + self.dim.height) + qp.drawLine(self.leftMargin - 5, y, + self.leftMargin + self.dim.width, y) + qp.drawLine(self.leftMargin - 5, + self.topMargin + self.dim.height, + self.leftMargin + self.dim.width, + self.topMargin + self.dim.height) qp.setPen(Chart.color.text) - digits = max(0, min(2, math.floor(3 - math.log10(abs(minVSWR))))) - if digits == 0: - vswrstr = str(round(minVSWR)) - else: - vswrstr = str(round(minVSWR, digits)) - qp.drawText(3, self.topMargin + self.dim.height, vswrstr) + digits = max( + 0, min(2, math.floor(3 - math.log10(abs(minVSWR))))) + v_text = f"{round(minVSWR, digits)}" if digits else "0" + qp.drawText(3, self.topMargin + self.dim.height, v_text) else: for i in range(target_ticks): - vswr = minVSWR + i * self.span/target_ticks + vswr = minVSWR + i * self.span / target_ticks y = self.getYPositionFromValue(vswr) qp.setPen(Chart.color.text) if vswr != 0: - digits = max(0, min(2, math.floor(3 - math.log10(abs(vswr))))) - if digits == 0: - vswrstr = str(round(vswr)) - else: - vswrstr = str(round(vswr, digits)) - qp.drawText(3, y+3, vswrstr) + digits = max( + 0, min(2, math.floor(3 - math.log10(abs(vswr))))) + vswrstr = f"{round(vswr, digits)}" if digits else "0" + qp.drawText(3, y + 3, vswrstr) qp.setPen(QtGui.QPen(Chart.color.foreground)) - qp.drawLine(self.leftMargin-5, y, self.leftMargin+self.dim.width, y) + qp.drawLine(self.leftMargin - 5, y, + self.leftMargin + self.dim.width, y) qp.drawLine(self.leftMargin - 5, self.topMargin, self.leftMargin + self.dim.width, self.topMargin) qp.setPen(Chart.color.text) digits = max(0, min(2, math.floor(3 - math.log10(abs(maxVSWR))))) - if digits == 0: - vswrstr = str(round(maxVSWR)) - else: - vswrstr = str(round(maxVSWR, digits)) - qp.drawText(3, 35, vswrstr) + v_text = f"{round(maxVSWR, digits)}" if digits else "0" + qp.drawText(3, 35, v_text) qp.setPen(Chart.color.swr) for vswr in self.swrMarkers: y = self.getYPositionFromValue(vswr) - qp.drawLine(self.leftMargin, y, self.leftMargin + self.dim.width, y) + qp.drawLine(self.leftMargin, y, + self.leftMargin + self.dim.width, y) qp.drawText(self.leftMargin + 3, y - 1, str(vswr)) self.drawFrequencyTicks(qp) From 36bff6a09de50ca7b12e748ef977df33fd556f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Thu, 15 Sep 2022 08:03:26 +0200 Subject: [PATCH 05/11] fixed default for SITools::Value --- NanoVNASaver/SITools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NanoVNASaver/SITools.py b/NanoVNASaver/SITools.py index 131ab607..28d81c12 100644 --- a/NanoVNASaver/SITools.py +++ b/NanoVNASaver/SITools.py @@ -63,7 +63,7 @@ class Format(NamedTuple): class Value: CTX = Context(prec=60, Emin=-27, Emax=27) - def __init__(self, value: Real, unit: str = "", fmt=Format()): + def __init__(self, value: Real = Decimal(0), unit: str = "", fmt=Format()): assert 1 <= fmt.max_nr_digits <= 30 assert -8 <= fmt.min_offset <= fmt.max_offset <= 8 assert fmt.parse_clamp_min < fmt.parse_clamp_max From 3f8151aad72b9cb4155e85299f2d2f64f1b50570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Thu, 15 Sep 2022 17:37:41 +0200 Subject: [PATCH 06/11] ensure int type in draw coordinates --- NanoVNASaver/Charts/CLogMag.py | 3 ++- NanoVNASaver/Charts/Chart.py | 5 +++-- NanoVNASaver/Charts/Frequency.py | 4 ++-- NanoVNASaver/Charts/TDR.py | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/NanoVNASaver/Charts/CLogMag.py b/NanoVNASaver/Charts/CLogMag.py index 55bb48c1..2975b16c 100644 --- a/NanoVNASaver/Charts/CLogMag.py +++ b/NanoVNASaver/Charts/CLogMag.py @@ -61,7 +61,8 @@ def resetDisplayLimits(self): def drawChart(self, qp: QtGui.QPainter): qp.setPen(QtGui.QPen(Chart.color.text)) - qp.drawText(int(round(self.dim.width / 2)) - 20, 15, + qp.drawText(int(self.dim.width // 2) - 20, + 15, f"{self.name} {self.name_unit}") qp.drawText(10, 15, "S11") qp.drawText(self.leftMargin + self.dim.width - 8, 15, "S21") diff --git a/NanoVNASaver/Charts/Chart.py b/NanoVNASaver/Charts/Chart.py index 4b8f037b..1129d725 100644 --- a/NanoVNASaver/Charts/Chart.py +++ b/NanoVNASaver/Charts/Chart.py @@ -75,7 +75,7 @@ def __init__(self, qp: QtGui.QPaintDevice): self.qp = qp def draw(self, x: int, y: int, color: QtGui.QColor, text: str = ""): - offset = Defaults.cfg.chart.marker_size // 2 + offset = int(Defaults.cfg.chart.marker_size // 2) if Defaults.cfg.chart.marker_at_tip: y -= offset pen = QtGui.QPen(color) @@ -93,7 +93,8 @@ def draw(self, x: int, y: int, color: QtGui.QColor, text: str = ""): if text and Defaults.cfg.chart.marker_label: text_width = self.qp.fontMetrics().horizontalAdvance(text) - self.qp.drawText(x - text_width // 2, y - 3 - offset, text) + self.qp.drawText(x - int(text_width // 2), + y - 3 - offset, text) class Chart(QtWidgets.QWidget): diff --git a/NanoVNASaver/Charts/Frequency.py b/NanoVNASaver/Charts/Frequency.py index 0e925076..8235c78c 100644 --- a/NanoVNASaver/Charts/Frequency.py +++ b/NanoVNASaver/Charts/Frequency.py @@ -458,8 +458,8 @@ def _check_frequency_boundaries(self, qp: QtGui.QPainter): qp.setBackgroundMode(QtCore.Qt.OpaqueMode) qp.setBackground(Chart.color.background) qp.setPen(Chart.color.text) - qp.drawText(self.leftMargin + self.dim.width // 2 - 70, - self.topMargin + self.dim.height // 2 - 20, + qp.drawText(self.leftMargin + int(self.dim.width // 2) - 70, + self.topMargin + int(self.dim.height // 2) - 20, "Data outside frequency span") def drawDragbog(self, qp: QtGui.QPainter): diff --git a/NanoVNASaver/Charts/TDR.py b/NanoVNASaver/Charts/TDR.py index 1ed26fdb..65d98af3 100644 --- a/NanoVNASaver/Charts/TDR.py +++ b/NanoVNASaver/Charts/TDR.py @@ -370,8 +370,8 @@ def paintEvent(self, _: QtGui.QPaintEvent) -> None: continue x = self.leftMargin + int((i - min_index) / x_step) - y = (self.topMargin + height) - \ - int(self.tdrWindow.td[i] / y_step) + y = (self.topMargin + height) - int( + self.tdrWindow.td[i] / y_step) if self.isPlotable(x, y): pen.setColor(Chart.color.sweep) qp.setPen(pen) From 1609295bd97a15d7b0f66e7f3d4a16bc1bcfc820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Thu, 15 Sep 2022 20:08:23 +0200 Subject: [PATCH 07/11] pycodestyle changes --- NanoVNASaver/Analysis/PeakSearchAnalysis.py | 19 +- NanoVNASaver/Analysis/VSWRAnalysis.py | 128 ++++------- NanoVNASaver/Calibration.py | 29 ++- NanoVNASaver/Defaults.py | 17 +- NanoVNASaver/Hardware/VNA.py | 27 ++- NanoVNASaver/Marker/Values.py | 14 +- NanoVNASaver/Marker/Widget.py | 19 +- NanoVNASaver/NanoVNASaver.py | 83 +++---- NanoVNASaver/Windows/CalibrationSettings.py | 234 ++++++++++++-------- NanoVNASaver/Windows/DisplaySettings.py | 61 +++-- 10 files changed, 328 insertions(+), 303 deletions(-) diff --git a/NanoVNASaver/Analysis/PeakSearchAnalysis.py b/NanoVNASaver/Analysis/PeakSearchAnalysis.py index 0a522df0..63a0e612 100644 --- a/NanoVNASaver/Analysis/PeakSearchAnalysis.py +++ b/NanoVNASaver/Analysis/PeakSearchAnalysis.py @@ -97,21 +97,16 @@ def runAnalysis(self): count = self.input_number_of_peaks.value() if self.rbtn_data_vswr.isChecked(): fn = format_vswr - for d in self.app.data.s11: - data.append(d.vswr) + data.extend(d.vswr for d in self.app.data.s11) elif self.rbtn_data_s21_gain.isChecked(): fn = format_gain - for d in self.app.data.s21: - data.append(d.gain) + data.extend(d.gain for d in self.app.data.s21) elif self.rbtn_data_resistance.isChecked(): fn = format_resistance - for d in self.app.data.s11: - data.append(d.impedance().real) + data.extend(d.impedance().real for d in self.app.data.s11) elif self.rbtn_data_reactance.isChecked(): fn = str - for d in self.app.data.s11: - data.append(d.impedance().imag) - + data.extend(d.impedance().imag for d in self.app.data.s11) else: logger.warning("Searching for peaks on unknown data") return @@ -125,8 +120,10 @@ def runAnalysis(self): peaks, _ = signal.find_peaks( data, width=3, distance=3, prominence=1) # elif self.rbtn_peak_both.isChecked(): - # peaks_max, _ = signal.find_peaks(data, width=3, distance=3, prominence=1) - # peaks_min, _ = signal.find_peaks(np.array(data)*-1, width=3, distance=3, prominence=1) + # peaks_max, _ = signal.find_peaks( + # data, width=3, distance=3, prominence=1) + # peaks_min, _ = signal.find_peaks( + # np.array(data)*-1, width=3, distance=3, prominence=1) # peaks = np.concatenate((peaks_max, peaks_min)) else: # Both is not yet in diff --git a/NanoVNASaver/Analysis/VSWRAnalysis.py b/NanoVNASaver/Analysis/VSWRAnalysis.py index bd8be17d..bbf1b8bf 100644 --- a/NanoVNASaver/Analysis/VSWRAnalysis.py +++ b/NanoVNASaver/Analysis/VSWRAnalysis.py @@ -19,7 +19,6 @@ import os import csv import logging -from collections import OrderedDict import numpy as np from PyQt5 import QtWidgets @@ -74,39 +73,27 @@ def __init__(self, app): def runAnalysis(self): max_dips_shown = self.max_dips_shown - data = [d.vswr for d in self.app.data.s11] - - # min_idx = np.argmin(data) - # - # logger.debug("Minimum at %d", min_idx) - # logger.debug("Value at minimum: %f", data[min_idx]) - # logger.debug("Frequency: %d", self.app.data.s11[min_idx].freq) - # - # if self.checkbox_move_marker.isChecked(): - # self.app.markers[0].setFrequency(str(self.app.data.s11[min_idx].freq)) - # self.app.markers[0].frequencyInput.setText(str(self.app.data.s11[min_idx].freq)) - threshold = self.input_vswr_limit.value() minimums = self.find_minimums(data, threshold) - logger.debug("Found %d sections under %f threshold", len(minimums), threshold) - results_header = self.layout.indexOf(self.results_label) logger.debug("Results start at %d, out of %d", results_header, self.layout.rowCount()) + for _ in range(results_header, self.layout.rowCount()): self.layout.removeRow(self.layout.rowCount() - 1) - if len(minimums) > max_dips_shown: - self.layout.addRow(QtWidgets.QLabel("More than " + str(max_dips_shown) + - " dips found. Lowest shown.")) + self.layout.addRow( + QtWidgets.QLabel( + f"More than {str(max_dips_shown)} dips found." + " Lowest shown.")) + dips = [] for m in minimums: start, lowest, end = m dips.append(data[lowest]) - best_dips = [] for _ in range(max_dips_shown): min_idx = np.argmin(dips) @@ -123,27 +110,26 @@ def runAnalysis(self): "Section from %d to %d, lowest at %d", start, end, lowest) self.layout.addRow("Start", QtWidgets.QLabel( format_frequency(self.app.data.s11[start].freq))) - self.layout.addRow( - "Minimum", - QtWidgets.QLabel( - f"{format_frequency(self.app.data.s11[lowest].freq)}" - f" ({round(data[lowest], 2)})")) + + self.layout.addRow("Minimum", QtWidgets.QLabel( + f"{format_frequency(self.app.data.s11[lowest].freq)} ({round(data[lowest], 2)})")) + self.layout.addRow("End", QtWidgets.QLabel( format_frequency(self.app.data.s11[end].freq))) - self.layout.addRow( - "Span", - QtWidgets.QLabel( - format_frequency(self.app.data.s11[end].freq - - self.app.data.s11[start].freq))) + + self.layout.addRow("Span", QtWidgets.QLabel(format_frequency( + (self.app.data.s11[end].freq - self.app.data.s11[start].freq)))) + else: self.layout.addRow("Low spot", QtWidgets.QLabel( format_frequency(self.app.data.s11[lowest].freq))) + self.layout.addWidget(PeakSearchAnalysis.QHLine()) - # Remove the final separator line self.layout.removeRow(self.layout.rowCount() - 1) else: - self.layout.addRow(QtWidgets.QLabel( - "No areas found with VSWR below " + str(round(threshold, 2)) + ".")) + self.layout.addRow( + QtWidgets.QLabel( + f"No areas found with VSWR below {round(threshold, 2)}.")) class ResonanceAnalysis(Analysis): @@ -153,9 +139,7 @@ class ResonanceAnalysis(Analysis): def vswr_transformed(cls, z, ratio=49) -> float: refl = reflection_coefficient(z / ratio) mag = abs(refl) - if mag == 1: - return 1 - return (1 + mag) / (1 - mag) + return 1 if mag == 1 else (1 + mag) / (1 - mag) class QHLine(QtWidgets.QFrame): def __init__(self): @@ -203,11 +187,10 @@ def runAnalysis(self): self.reset() # self.results_label = QtWidgets.QLabel("Results") # max_dips_shown = self.max_dips_shown - description = self.input_description.text() - if description: - filename = os.path.join("/tmp/", "{}.csv".format(description)) - else: - filename = None + filename = ( + os.path.join("/tmp/", f"{self.input_description.text()}.csv") + if self.input_description.text() + else None) crossing = self._get_crossing() @@ -272,42 +255,29 @@ def reset(self): def runAnalysis(self): self.reset() - # self.results_label = QtWidgets.QLabel("Results") - # max_dips_shown = self.max_dips_shown - description = self.input_description.text() - if description: - filename = os.path.join("/tmp/", "{}.csv".format(description)) + if description := self.input_description.text(): + filename = os.path.join("/tmp/", f"{description}.csv") else: filename = None - crossing = self._get_crossing() - - data = [] - for d in self.app.data.s11: - data.append(d.impedance().real) - + data = [d.impedance().real for d in self.app.data.s11] maximums = sorted(self.find_maximums(data, threshold=500)) - results_header = self.layout.indexOf(self.results_label) logger.debug("Results start at %d, out of %d", results_header, self.layout.rowCount()) - for i in range(results_header, self.layout.rowCount()): - self.layout.removeRow(self.layout.rowCount() - 1) - extended_data = OrderedDict() - - # both = np.intersect1d([i[1] for i in crossing], maximums) + for _ in range(results_header, self.layout.rowCount()): + self.layout.removeRow(self.layout.rowCount() - 1) + extended_data = {} both = [] - tolerance = 2 for i in maximums: - for l, _, h in crossing: - if l - tolerance <= i <= h + tolerance: + for low, _, high in crossing: + if low - tolerance <= i <= high + tolerance: both.append(i) continue - if l > i: + if low > i: continue - if both: logger.info("%i crossing HW", len(both)) logger.info(crossing) @@ -320,67 +290,45 @@ def runAnalysis(self): else: extended_data[m] = my_data for i in range(min(len(both), len(self.app.markers))): - # self.app.markers[i].label = {} - # for l in TYPES: - # self.app.markers[i][l.label_id] = MarkerLabel(l.name) - # self.app.markers[i].label['actualfreq'].setMinimumWidth( - # 100) - # self.app.markers[i].label['returnloss'].setMinimumWidth(80) - self.app.markers[i].setFrequency( str(self.app.data.s11[both[i]].freq)) self.app.markers[i].frequencyInput.setText( str(self.app.data.s11[both[i]].freq)) + else: logger.info("TO DO: find near data") for _, lowest, _ in crossing: my_data = self._get_data(lowest) - if lowest in extended_data: extended_data[lowest].update(my_data) else: extended_data[lowest] = my_data - logger.debug("maximumx %s of type %s", maximums, type(maximums)) for m in maximums: logger.debug("m %s of type %s", m, type(m)) - my_data = self._get_data(m) if m in extended_data: extended_data[m].update(my_data) else: extended_data[m] = my_data - - # saving and comparing - fields = [("freq", format_frequency_short), - ("r", format_resistence_neg), - ("lambda", round_2), - ] + ("r", format_resistence_neg), ("lambda", round_2)] + if self.old_data: diff = self.compare( self.old_data[-1], extended_data, fields=fields) else: diff = self.compare({}, extended_data, fields=fields) self.old_data.append(extended_data) - for i, index in enumerate(sorted(extended_data.keys())): - self.layout.addRow( - f"{format_frequency_short(self.app.data.s11[index].freq)}", - QtWidgets.QLabel(f" ({diff[i]['freq']})" - f" {format_complex_imp(self.app.data.s11[index].impedance())}" - f" ({diff[i]['r']})" - f" {diff[i]['lambda']} m")) - - # Remove the final separator line - # self.layout.removeRow(self.layout.rowCount() - 1) - if filename and extended_data: + self.layout.addRow(f"{format_frequency_short(self.app.data.s11[index].freq)}", QtWidgets.QLabel( + f" ({diff[i]['freq']}) {format_complex_imp(self.app.data.s11[index].impedance())} ({diff[i]['r']}) {diff[i]['lambda']} m")) + if filename and extended_data: with open(filename, 'w', newline='') as csvfile: fieldnames = extended_data[sorted( extended_data.keys())[0]].keys() writer = csv.DictWriter(csvfile, fieldnames=fieldnames) - writer.writeheader() for index in sorted(extended_data.keys()): row = extended_data[index] diff --git a/NanoVNASaver/Calibration.py b/NanoVNASaver/Calibration.py index b084bf82..51002107 100644 --- a/NanoVNASaver/Calibration.py +++ b/NanoVNASaver/Calibration.py @@ -120,7 +120,8 @@ def complete1port(self) -> bool: def complete2port(self) -> bool: for val in self.data.values(): - for name in ("short", "open", "load", "through", "thrurefl", "isolation"): + for name in ("short", "open", "load", "through", "thrurefl", + "isolation"): if val[name] is None: return False return any(self.data) @@ -218,9 +219,9 @@ def _calc_port_2(self, freq: int, cal: CalData): cal["e30"] = cal["isolation"].z cal["e10e01"] = cal["e00"] * cal["e11"] - cal["delta_e"] cal["e22"] = gm7 / ( - gm7 * cal["e11"] * gt ** 2 + cal["e10e01"] * gt ** 2) + gm7 * cal["e11"] * gt ** 2 + cal["e10e01"] * gt ** 2) cal["e10e32"] = (gm4 - gm6) * ( - 1 - cal["e11"] * cal["e22"] * gt ** 2) / gt + 1 - cal["e11"] * cal["e22"] * gt ** 2) / gt def calc_corrections(self): if not self.isValid1Port(): @@ -254,8 +255,8 @@ def gamma_short(self, freq: int) -> complex: if not self.useIdealShort: logger.debug("Using short calibration set values.") Zsp = complex(0, 2 * math.pi * freq * ( - self.shortL0 + self.shortL1 * freq + - self.shortL2 * freq ** 2 + self.shortL3 * freq ** 3)) + self.shortL0 + self.shortL1 * freq + + self.shortL2 * freq ** 2 + self.shortL3 * freq ** 3)) # Referencing https://arxiv.org/pdf/1606.02446.pdf (18) - (21) g = (Zsp / 50 - 1) / (Zsp / 50 + 1) * cmath.exp( complex(0, 2 * math.pi * 2 * freq * self.shortLength * -1)) @@ -266,8 +267,8 @@ def gamma_open(self, freq: int) -> complex: if not self.useIdealOpen: logger.debug("Using open calibration set values.") Zop = complex(0, 2 * math.pi * freq * ( - self.openC0 + self.openC1 * freq + - self.openC2 * freq ** 2 + self.openC3 * freq ** 3)) + self.openC0 + self.openC1 * freq + + self.openC2 * freq ** 2 + self.openC3 * freq ** 3)) g = ((1 - 50 * Zop) / (1 + 50 * Zop)) * cmath.exp( complex(0, 2 * math.pi * 2 * freq * self.openLength * -1)) return g @@ -278,7 +279,8 @@ def gamma_load(self, freq: int) -> complex: logger.debug("Using load calibration set values.") Zl = complex(self.loadR, 0) if self.loadC > 0: - Zl = self.loadR / complex(1, 2 * self.loadR * math.pi * freq * self.loadC) + Zl = self.loadR / \ + complex(1, 2 * self.loadR * math.pi * freq * self.loadC) if self.loadL > 0: Zl = Zl + complex(0, 2 * math.pi * freq * self.loadL) g = (Zl / 50 - 1) / (Zl / 50 + 1) * cmath.exp( @@ -340,13 +342,14 @@ def gen_interpolation(self): def correct11(self, dp: Datapoint): i = self.interp s11 = (dp.z - i["e00"](dp.freq)) / ( - (dp.z * i["e11"](dp.freq)) - i["delta_e"](dp.freq)) + (dp.z * i["e11"](dp.freq)) - i["delta_e"](dp.freq)) return Datapoint(dp.freq, s11.real, s11.imag) def correct21(self, dp: Datapoint, dp11: Datapoint): i = self.interp s21 = (dp.z - i["e30"](dp.freq)) / i["e10e32"](dp.freq) - s21 = s21 * (i["e10e01"](dp.freq) / (i["e11"](dp.freq) * dp11.z - i["delta_e"](dp.freq))) + s21 = s21 * (i["e10e01"](dp.freq) / (i["e11"](dp.freq) + * dp11.z - i["delta_e"](dp.freq))) return Datapoint(dp.freq, s21.real, s21.imag) # TODO: implement tests @@ -360,7 +363,8 @@ def save(self, filename: str): calfile.write(f"! {note}\n") calfile.write( "# Hz ShortR ShortI OpenR OpenI LoadR LoadI" - " ThroughR ThroughI ThrureflR ThrureflI IsolationR IsolationI\n") + " ThroughR ThroughI ThrureflR ThrureflI" + " IsolationR IsolationI\n") for freq in self.dataset.frequencies(): calfile.write(f"{self.dataset.get(freq)}\n") @@ -382,7 +386,8 @@ def load(self, filename): if line.startswith("#"): if not parsed_header and line == ( "# Hz ShortR ShortI OpenR OpenI LoadR LoadI" - " ThroughR ThroughI ThrureflR ThrureflI IsolationR IsolationI"): + " ThroughR ThroughI ThrureflR ThrureflI" + " IsolationR IsolationI"): parsed_header = True continue if not parsed_header: diff --git a/NanoVNASaver/Defaults.py b/NanoVNASaver/Defaults.py index 51fa66ad..1deb8239 100644 --- a/NanoVNASaver/Defaults.py +++ b/NanoVNASaver/Defaults.py @@ -65,6 +65,7 @@ class Chart: show_bands: bool = False vswr_lines: list = DC.field(default_factory=lambda: []) + @DC.dataclass class ChartColors: # pylint: disable=too-many-instance-attributes background: QColor = QColor(QtCore.Qt.white) @@ -131,11 +132,11 @@ def from_type(data) -> str: type_map = { bytearray: lambda x: x.hex(), QColor: lambda x: x.getRgb(), - QByteArray: lambda x: x.toHex(), + QByteArray: lambda x: x.toHex() } - if type(data) in type_map: - return str(type_map[type(data)](data)) - return str(data) + return (f"{type_map[type(data)](data)}" if + type(data) in type_map else + f"{data}") def to_type(data: object, data_type: type) -> object: @@ -145,11 +146,11 @@ def to_type(data: object, data_type: type) -> object: list: literal_eval, tuple: literal_eval, QColor: lambda x: QColor.fromRgb(*literal_eval(x)), - QByteArray: lambda x: QByteArray.fromHex(literal_eval(x)), + QByteArray: lambda x: QByteArray.fromHex(literal_eval(x)) } - if data_type in type_map: - return type_map[data_type](data) - return data_type(data) + return (type_map[data_type](data) if + data_type in type_map else + data_type(data)) # noinspection PyDataclass diff --git a/NanoVNASaver/Hardware/VNA.py b/NanoVNASaver/Hardware/VNA.py index 04301c5c..edf04fab 100644 --- a/NanoVNASaver/Hardware/VNA.py +++ b/NanoVNASaver/Hardware/VNA.py @@ -17,7 +17,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . import logging -from collections import OrderedDict from time import sleep from typing import List, Iterator, Set @@ -28,19 +27,19 @@ logger = logging.getLogger(__name__) -DISLORD_BW = OrderedDict(( - (10, 363), - (33, 117), - (50, 78), - (100, 39), - (200, 19), - (250, 15), - (333, 11), - (500, 7), - (1000, 3), - (2000, 1), - (4000, 0), -)) +DISLORD_BW = { + 10: 363, + 33: 117, + 50: 78, + 100: 39, + 200: 19, + 250: 15, + 333: 11, + 500: 7, + 1000: 3, + 2000: 1, + 4000: 0, +} WAIT = 0.05 diff --git a/NanoVNASaver/Marker/Values.py b/NanoVNASaver/Marker/Values.py index 34ef5869..44d4a6ec 100644 --- a/NanoVNASaver/Marker/Values.py +++ b/NanoVNASaver/Marker/Values.py @@ -56,17 +56,20 @@ class Label(NamedTuple): Label("s21groupdelay", "S21 Group Delay", "S21 Group Delay", False), Label("s21magshunt", "S21 |Z| shunt", "S21 Z Magnitude shunt", False), Label("s21magseries", "S21 |Z| series", "S21 Z Magnitude series", False), - Label("s21realimagshunt", "S21 R+jX shunt", "S21 Z Real+Imag shunt", False), - Label("s21realimagseries", "S21 R+jX series", "S21 Z Real+Imag series", False), + Label("s21realimagshunt", "S21 R+jX shunt", + "S21 Z Real+Imag shunt", False), + Label("s21realimagseries", "S21 R+jX series", + "S21 Z Real+Imag series", False), ) def default_label_ids() -> str: - return [l.label_id for l in TYPES if l.default_active] + return [label.label_id for label in TYPES if label.default_active] class Value(): """Contains the data area to calculate marker values from""" + def __init__(self, freq: int = 0, s11: List[Datapoint] = None, s21: List[Datapoint] = None): @@ -87,7 +90,8 @@ def store(self, index: int, s11 += [s11[-1], ] if s21: s21 += [s21[-1], ] + self.freq = s11[1].freq - self.s11 = s11[index-1:index+2] + self.s11 = s11[index - 1:index + 2] if s21: - self.s21 = s21[index-1:index+2] + self.s21 = s21[index - 1:index + 2] diff --git a/NanoVNASaver/Marker/Widget.py b/NanoVNASaver/Marker/Widget.py index 9d47f327..49b8dcf5 100644 --- a/NanoVNASaver/Marker/Widget.py +++ b/NanoVNASaver/Marker/Widget.py @@ -98,9 +98,9 @@ def __init__(self, name: str = "", qsettings: QtCore.QSettings = None): # Data display labels ############################################################### - self.label = {} - for l in TYPES: - self.label[l.label_id] = MarkerLabel(l.name) + self.label = { + label.label_id: MarkerLabel(label.name) for label in TYPES + } self.label['actualfreq'].setMinimumWidth(100) self.label['returnloss'].setMinimumWidth(80) @@ -201,7 +201,7 @@ def buildForm(self): for label_id in self.active_labels: self._add_active_labels(label_id, self.left_form) else: - left_half = math.ceil(len(self.active_labels)/2) + left_half = math.ceil(len(self.active_labels) / 2) right_half = len(self.active_labels) for i in range(left_half): label_id = self.active_labels[i] @@ -258,8 +258,8 @@ def findLocation(self, data: List[RFTools.Datapoint]): upper_stepsize = data[-1].freq - data[-2].freq # We are outside the bounds of the data, so we can't put in a marker - if (self.freq + lower_stepsize/2 < min_freq or - self.freq - upper_stepsize/2 > max_freq): + if (self.freq + lower_stepsize / 2 < min_freq or + self.freq - upper_stepsize / 2 > max_freq): return min_distance = max_freq @@ -268,11 +268,11 @@ def findLocation(self, data: List[RFTools.Datapoint]): min_distance = abs(item.freq - self.freq) else: # We have now started moving away from the nearest point - self.location = i-1 + self.location = i - 1 if i < datasize: self.frequencyInput.nextFrequency = item.freq if i >= 2: - self.frequencyInput.previousFrequency = data[i-2].freq + self.frequencyInput.previousFrequency = data[i - 2].freq return # If we still didn't find a best spot, it was the last value self.location = datasize - 1 @@ -292,7 +292,8 @@ def updateLabels(self, return if self.location == -1: # initial position try: - location = (self.index -1) / (self._instances - 1) * (len(s11) - 1) + location = (self.index - 1) / ( + (self._instances - 1) * (len(s11) - 1)) self.location = int(location) except ZeroDivisionError: self.location = 0 diff --git a/NanoVNASaver/NanoVNASaver.py b/NanoVNASaver/NanoVNASaver.py index 047df0b3..8182d812 100644 --- a/NanoVNASaver/NanoVNASaver.py +++ b/NanoVNASaver/NanoVNASaver.py @@ -19,7 +19,6 @@ import logging import sys import threading -from collections import OrderedDict from time import strftime, localtime from PyQt5 import QtWidgets, QtCore, QtGui @@ -40,7 +39,8 @@ CapacitanceChart, CombinedLogMagChart, GroupDelayChart, InductanceChart, LogMagChart, PhaseChart, - MagnitudeChart, MagnitudeZChart, MagnitudeZShuntChart, MagnitudeZSeriesChart, + MagnitudeChart, MagnitudeZChart, MagnitudeZShuntChart, + MagnitudeZSeriesChart, QualityFactorChart, VSWRChart, PermeabilityChart, PolarChart, RealImaginaryChart, RealImaginaryShuntChart, RealImaginarySeriesChart, SmithChart, SParameterChart, TDRChart, @@ -70,9 +70,11 @@ def __init__(self): else: self.icon = QtGui.QIcon("icon_48x48.png") self.setWindowIcon(self.icon) - self.settings = Defaults.AppSettings(QtCore.QSettings.IniFormat, - QtCore.QSettings.UserScope, - "NanoVNASaver", "NanoVNASaver") + self.settings = Defaults.AppSettings( + QtCore.QSettings.IniFormat, + QtCore.QSettings.UserScope, + "NanoVNASaver", + "NanoVNASaver") logger.info("Settings from: %s", self.settings.fileName()) Defaults.cfg = Defaults.restore(self.settings) self.threadpool = QtCore.QThreadPool() @@ -126,7 +128,8 @@ def __init__(self): self.resize(Defaults.cfg.gui.window_width, Defaults.cfg.gui.window_height) scrollarea.setSizePolicy( - QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) + QtWidgets.QSizePolicy.MinimumExpanding, + QtWidgets.QSizePolicy.MinimumExpanding) self.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) widget = QtWidgets.QWidget() @@ -134,39 +137,40 @@ def __init__(self): scrollarea.setWidget(widget) self.charts = { - "s11": OrderedDict(( - ("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( + "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( "S11 R/\N{GREEK SMALL LETTER OMEGA} &" - " X/\N{GREEK SMALL LETTER OMEGA}")), - ("phase", PhaseChart("S11 Phase")), - ("q_factor", QualityFactorChart("S11 Quality Factor")), - ("real_imag", RealImaginaryChart("S11 R+jX")), - ("smith", SmithChart("S11 Smith Chart")), - ("s_parameter", SParameterChart("S11 Real/Imaginary")), - ("vswr", VSWRChart("S11 VSWR")), - )), - "s21": OrderedDict(( - ("group_delay", GroupDelayChart("S21 Group Delay", - reflective=False)), - ("log_mag", LogMagChart("S21 Gain")), - ("magnitude", MagnitudeChart("|S21|")), - ("magnitude_z_shunt", MagnitudeZShuntChart("S21 |Z| shunt")), - ("magnitude_z_series", MagnitudeZSeriesChart("S21 |Z| series")), - ("real_imag_shunt", RealImaginaryShuntChart("S21 R+jX shunt")), - ("real_imag_series", RealImaginarySeriesChart("S21 R+jX series")), - ("phase", PhaseChart("S21 Phase")), - ("polar", PolarChart("S21 Polar Plot")), - ("s_parameter", SParameterChart("S21 Real/Imaginary")), - )), - "combined": OrderedDict(( - ("log_mag", CombinedLogMagChart("S11 & S21 LogMag")), - )), + " X/\N{GREEK SMALL LETTER OMEGA}"), + "phase": PhaseChart("S11 Phase"), + "q_factor": QualityFactorChart("S11 Quality Factor"), + "real_imag": RealImaginaryChart("S11 R+jX"), + "smith": SmithChart("S11 Smith Chart"), + "s_parameter": SParameterChart("S11 Real/Imaginary"), + "vswr": VSWRChart("S11 VSWR"), + }, + "s21": { + "group_delay": GroupDelayChart("S21 Group Delay", + reflective=False), + "log_mag": LogMagChart("S21 Gain"), + "magnitude": MagnitudeChart("|S21|"), + "magnitude_z_shunt": MagnitudeZShuntChart("S21 |Z| shunt"), + "magnitude_z_series": MagnitudeZSeriesChart("S21 |Z| series"), + "real_imag_shunt": RealImaginaryShuntChart("S21 R+jX shunt"), + "real_imag_series": RealImaginarySeriesChart( + "S21 R+jX series"), + "phase": PhaseChart("S21 Phase"), + "polar": PolarChart("S21 Polar Plot"), + "s_parameter": SParameterChart("S21 Real/Imaginary"), + }, + "combined": { + "log_mag": CombinedLogMagChart("S11 & S21 LogMag"), + }, } self.tdr_chart = TDRChart("TDR") self.tdr_mainwindow_chart = TDRChart("TDR") @@ -515,7 +519,8 @@ def dataUpdated(self): if s11: min_vswr = min(s11, key=lambda data: data.vswr) self.s11_min_swr_label.setText( - f"{format_vswr(min_vswr.vswr)} @ {format_frequency(min_vswr.freq)}") + f"{format_vswr(min_vswr.vswr)} @" + f" {format_frequency(min_vswr.freq)}") self.s11_min_rl_label.setText(format_gain(min_vswr.gain)) else: self.s11_min_swr_label.setText("") diff --git a/NanoVNASaver/Windows/CalibrationSettings.py b/NanoVNASaver/Windows/CalibrationSettings.py index 6fe58669..fb172508 100644 --- a/NanoVNASaver/Windows/CalibrationSettings.py +++ b/NanoVNASaver/Windows/CalibrationSettings.py @@ -58,13 +58,16 @@ def __init__(self, app: QtWidgets.QWidget): calibration_status_layout = QtWidgets.QFormLayout() self.calibration_status_label = QtWidgets.QLabel("Device calibration") self.calibration_source_label = QtWidgets.QLabel("NanoVNA") - calibration_status_layout.addRow("Calibration:", self.calibration_status_label) - calibration_status_layout.addRow("Source:", self.calibration_source_label) + calibration_status_layout.addRow("Calibration:", + self.calibration_status_label) + calibration_status_layout.addRow("Source:", + self.calibration_source_label) calibration_status_group.setLayout(calibration_status_layout) left_layout.addWidget(calibration_status_group) calibration_control_group = QtWidgets.QGroupBox("Calibrate") - calibration_control_layout = QtWidgets.QFormLayout(calibration_control_group) + calibration_control_layout = QtWidgets.QFormLayout( + calibration_control_group) cal_btn = {} self.cal_label = {} for label_name in Calibration.CAL_NAMES: @@ -72,7 +75,8 @@ def __init__(self, app: QtWidgets.QWidget): cal_btn[label_name] = QtWidgets.QPushButton( label_name.capitalize()) cal_btn[label_name].setMinimumHeight(20) - cal_btn[label_name].clicked.connect(partial(self.manual_save, label_name)) + cal_btn[label_name].clicked.connect( + partial(self.manual_save, label_name)) calibration_control_layout.addRow( cal_btn[label_name], self.cal_label[label_name]) @@ -85,7 +89,8 @@ def __init__(self, app: QtWidgets.QWidget): self.input_offset_delay.setRange(-10e6, 10e6) calibration_control_layout.addRow(QtWidgets.QLabel("")) - calibration_control_layout.addRow("Offset delay", self.input_offset_delay) + calibration_control_layout.addRow( + "Offset delay", self.input_offset_delay) self.btn_automatic = QtWidgets.QPushButton("Calibration assistant") self.btn_automatic.setMinimumHeight(20) @@ -110,7 +115,8 @@ def __init__(self, app: QtWidgets.QWidget): left_layout.addWidget(calibration_control_group) calibration_notes_group = QtWidgets.QGroupBox("Notes") - calibration_notes_layout = QtWidgets.QVBoxLayout(calibration_notes_group) + calibration_notes_layout = QtWidgets.QVBoxLayout( + calibration_notes_group) self.notes_textedit = QtWidgets.QPlainTextEdit() calibration_notes_layout.addWidget(self.notes_textedit) @@ -208,7 +214,8 @@ def __init__(self, app: QtWidgets.QWidget): cal_standard_layout.addWidget(self.cal_through_box) self.cal_standard_save_box = QtWidgets.QGroupBox("Saved settings") - cal_standard_save_layout = QtWidgets.QVBoxLayout(self.cal_standard_save_box) + cal_standard_save_layout = QtWidgets.QVBoxLayout( + self.cal_standard_save_box) self.cal_standard_save_box.setDisabled(True) self.cal_standard_save_selector = QtWidgets.QComboBox() @@ -237,15 +244,18 @@ def checkExpertUser(self): if not self.app.settings.value("ExpertCalibrationUser", False, bool): response = QtWidgets.QMessageBox.question( self, "Are you sure?", - "Use of the manual calibration buttons " + - "is non-intuitive, and primarily suited for users with very " + - "specialized needs. The buttons do not sweep for you, nor do " + - "they interact with the NanoVNA calibration.\n\n" + - "If you are trying to do a calibration of the NanoVNA, do so " + - "on the device itself instead. If you are trying to do a " + - "calibration with NanoVNA-Saver, use the Calibration Assistant " + - "if possible.\n\n" + - "If you are certain you know what you are doing, click Yes.", + ( + "Use of the manual calibration buttons is non-intuitive," + " and primarily suited for users with very specialized" + " needs. The buttons do not sweep for you, nor do" + " they interact with the NanoVNA calibration.\n\n" + "If you are trying to do a calibration of the NanoVNA, do" + "so on the device itself instead. If you are trying to do" + "a calibration with NanoVNA-Saver, use the Calibration" + "Assistant if possible.\n\n" + "If you are certain you know what you are doing, click" + " Yes." + ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Cancel) @@ -256,7 +266,7 @@ def checkExpertUser(self): return True def cal_save(self, name: str): - if name in ("through", "isolation"): + if name in {"through", "isolation"}: self.app.calibration.insert(name, self.app.data.s21) else: self.app.calibration.insert(name, self.app.data.s11) @@ -269,7 +279,8 @@ def manual_save(self, name: str): def listCalibrationStandards(self): self.cal_standard_save_selector.clear() - num_standards = self.app.settings.beginReadArray("CalibrationStandards") + num_standards = self.app.settings.beginReadArray( + "CalibrationStandards") for i in range(num_standards): self.app.settings.setArrayIndex(i) name = self.app.settings.value("Name", defaultValue="INVALID NAME") @@ -279,7 +290,8 @@ def listCalibrationStandards(self): self.cal_standard_save_selector.setCurrentText("New") def saveCalibrationStandard(self): - num_standards = self.app.settings.beginReadArray("CalibrationStandards") + num_standards = self.app.settings.beginReadArray( + "CalibrationStandards") self.app.settings.endArray() if self.cal_standard_save_selector.currentData() == -1: @@ -295,7 +307,8 @@ def saveCalibrationStandard(self): write_num = self.cal_standard_save_selector.currentData() name = self.cal_standard_save_selector.currentText() - self.app.settings.beginWriteArray("CalibrationStandards", num_standards) + self.app.settings.beginWriteArray( + "CalibrationStandards", num_standards) self.app.settings.setArrayIndex(write_num) self.app.settings.setValue("Name", name) @@ -338,7 +351,8 @@ def loadCalibrationStandard(self): self.short_l1_input.setText(str(self.app.settings.value("ShortL1", 0))) self.short_l2_input.setText(str(self.app.settings.value("ShortL2", 0))) self.short_l3_input.setText(str(self.app.settings.value("ShortL3", 0))) - self.short_length.setText(str(self.app.settings.value("ShortDelay", 0))) + self.short_length.setText( + str(self.app.settings.value("ShortDelay", 0))) self.open_c0_input.setText(str(self.app.settings.value("OpenC0", 50))) self.open_c1_input.setText(str(self.app.settings.value("OpenC1", 0))) @@ -351,7 +365,8 @@ def loadCalibrationStandard(self): self.load_capacitance.setText(str(self.app.settings.value("LoadC", 0))) self.load_length.setText(str(self.app.settings.value("LoadDelay", 0))) - self.through_length.setText(str(self.app.settings.value("ThroughDelay", 0))) + self.through_length.setText( + str(self.app.settings.value("ThroughDelay", 0))) self.app.settings.endArray() @@ -360,7 +375,8 @@ def deleteCalibrationStandard(self): return delete_num = self.cal_standard_save_selector.currentData() logger.debug("Deleting calibration no %d", delete_num) - num_standards = self.app.settings.beginReadArray("CalibrationStandards") + num_standards = self.app.settings.beginReadArray( + "CalibrationStandards") self.app.settings.endArray() logger.debug("Number of standards known: %d", num_standards) @@ -422,7 +438,8 @@ def deleteCalibrationStandard(self): self.app.settings.remove("") self.app.settings.endArray() - self.app.settings.beginWriteArray("CalibrationStandards", len(names)) + self.app.settings.beginWriteArray( + "CalibrationStandards", len(names)) for i, name in enumerate(names): self.app.settings.setArrayIndex(i) self.app.settings.setValue("Name", name) @@ -475,14 +492,21 @@ def setOffsetDelay(self, value: float): self.app.worker.applyCalibration( self.app.worker.rawData11, self.app.worker.rawData21) logger.debug("Saving and displaying corrected data.") - self.app.saveData(self.app.worker.data11, self.app.worker.data21, self.app.sweepSource) + self.app.saveData(self.app.worker.data11, + self.app.worker.data21, self.app.sweepSource) self.app.worker.signals.updated.emit() def calculate(self): + def _warn_ideal(cal_type: str) -> str: + return ( + 'Invalid data for "{cal_type}" calibration standard.' + ' Using ideal values.') + if self.app.sweep_control.btn_stop.isEnabled(): # Currently sweeping - self.app.showError("Unable to apply calibration while a sweep is running. " + - "Please stop the sweep and try again.") + self.app.showError( + "Unable to apply calibration while a sweep is running." + " Please stop the sweep and try again.") return if self.use_ideal_values.isChecked(): self.app.calibration.useIdealShort = True @@ -505,8 +529,7 @@ def calculate(self): self.app.calibration.useIdealShort = False except ValueError: self.app.calibration.useIdealShort = True - logger.warning( - 'Invalid data for "short" calibration standard. Using ideal values.') + logger.warning(_warn_ideal("short")) try: self.app.calibration.openC0 = self.getFloatValue( @@ -522,8 +545,7 @@ def calculate(self): self.app.calibration.useIdealOpen = False except ValueError: self.app.calibration.useIdealOpen = True - logger.warning( - 'Invalid data for "open" calibration standard. Using ideal values.') + logger.warning(_warn_ideal("open")) try: self.app.calibration.loadR = self.getFloatValue( @@ -537,18 +559,15 @@ def calculate(self): self.app.calibration.useIdealLoad = False except ValueError: self.app.calibration.useIdealLoad = True - logger.warning( - 'Invalid data for "load" calibration standard.' - ' Using ideal values.') + logger.warning(_warn_ideal("load")) + try: self.app.calibration.throughLength = self.getFloatValue( self.through_length.text()) / 10 ** 12 self.app.calibration.useIdealThrough = False except ValueError: self.app.calibration.useIdealThrough = True - logger.warning( - 'Invalid data for "through" calibration standard.' - ' Using ideal values.') + logger.warning(_warn_ideal("through")) logger.debug("Attempting calibration calculation.") try: @@ -557,32 +576,35 @@ def calculate(self): _format_cal_label(self.app.calibration.size(), "Application calibration")) if self.use_ideal_values.isChecked(): - self.calibration_source_label.setText(self.app.calibration.source) + self.calibration_source_label.setText( + self.app.calibration.source) else: self.calibration_source_label.setText( - self.app.calibration.source + " (Standards: Custom)") + f"{self.app.calibration.source} (Standards: Custom)") - if len(self.app.worker.rawData11) > 0: + if self.app.worker.rawData11: # There's raw data, so we can get corrected data logger.debug("Applying calibration to existing sweep data.") - self.app.worker.data11, self.app.worker.data21 = self.app.worker.applyCalibration( - self.app.worker.rawData11, self.app.worker.rawData21) + self.app.worker.data11, self.app.worker.data21 = ( + self.app.worker.applyCalibration( + self.app.worker.rawData11, + self.app.worker.rawData21)) logger.debug("Saving and displaying corrected data.") self.app.saveData(self.app.worker.data11, self.app.worker.data21, self.app.sweepSource) self.app.worker.signals.updated.emit() except ValueError as e: - # showError here hides the calibration window, so we need to pop up our own - QtWidgets.QMessageBox.warning(self, "Error applying calibration", str(e)) - self.calibration_status_label.setText("Applying calibration failed.") + # showError here hides the calibration window, + # so we need to pop up our own + QtWidgets.QMessageBox.warning( + self, "Error applying calibration", str(e)) + self.calibration_status_label.setText( + "Applying calibration failed.") self.calibration_source_label.setText(self.app.calibration.source) @staticmethod def getFloatValue(text: str) -> float: - if text == "": - # Default value is float - return 0 - return float(text) + return float(text) if text else 0.0 def loadCalibration(self): filename, _ = QtWidgets.QFileDialog.getOpenFileName( @@ -594,7 +616,8 @@ def loadCalibration(self): for i, name in enumerate( ("short", "open", "load", "through", "isolation", "thrurefl")): self.cal_label[name].setText( - _format_cal_label(self.app.calibration.data_size(name), "Loaded")) + _format_cal_label(self.app.calibration.data_size(name), + "Loaded")) if i == 2 and not self.app.calibration.isValid2Port(): break self.calculate() @@ -612,15 +635,15 @@ def saveCalibration(self): filedialog.setDefaultSuffix("cal") filedialog.setNameFilter("Calibration Files (*.cal);;All files (*.*)") filedialog.setAcceptMode(QtWidgets.QFileDialog.AcceptSave) - selected = filedialog.exec() - if selected: + if filedialog.exec(): filename = filedialog.selectedFiles()[0] else: return - if filename == "": + if not filename: logger.debug("No file name selected.") return - self.app.calibration.notes = self.notes_textedit.toPlainText().splitlines() + self.app.calibration.notes = self.notes_textedit.toPlainText( + ).splitlines() try: self.app.calibration.save(filename) self.app.settings.setValue("CalibrationFile", filename) @@ -633,25 +656,28 @@ def idealCheckboxChanged(self): self.cal_open_box.setDisabled(self.use_ideal_values.isChecked()) self.cal_load_box.setDisabled(self.use_ideal_values.isChecked()) self.cal_through_box.setDisabled(self.use_ideal_values.isChecked()) - self.cal_standard_save_box.setDisabled(self.use_ideal_values.isChecked()) + self.cal_standard_save_box.setDisabled( + self.use_ideal_values.isChecked()) def automaticCalibration(self): self.btn_automatic.setDisabled(True) introduction = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "Calibration assistant", - "This calibration assistant will help you create a calibration in the " - "NanoVNASaver application. It will sweep the standards for you, and " - "guide you through the process.

" - "Before starting, ensure you have Open, Short and Load standards " - "available, and the cables you wish to have calibrated with the device " - "connected.

" - "If you want a 2-port calibration, also have a \"through\" connector " - "to hand.

" - "The best results are achieved by having the NanoVNA calibrated " - "on-device for the full span of interest and saved to save slot 0 " - "before starting.

" - "Once you are ready to proceed, press Ok", + ( + "This calibration assistant will help you create a calibration" + " in the NanoVNASaver application. It will sweep the" + "standards for you, and guide you through the process.

" + "Before starting, ensure you have Open, Short and Load" + " standards available, and the cables you wish to have" + " calibrated with the device connected.

" + "If you want a 2-port calibration, also have a \"through\"" + " connector to hand.

" + "The best results are achieved by having the NanoVNA" + " calibrated on-device for the full span of interest and saved" + " to save slot 0 before starting.

" + "Once you are ready to proceed, press Ok." + ), QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) response = introduction.exec() if response != QtWidgets.QMessageBox.Ok: @@ -662,7 +688,8 @@ def automaticCalibration(self): QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "NanoVNA not connected", - "Please ensure the NanoVNA is connected before attempting calibration." + ("Please ensure the NanoVNA is connected before attempting" + " calibration.") ).exec() self.btn_automatic.setDisabled(False) return @@ -671,7 +698,8 @@ def automaticCalibration(self): QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "Continuous sweep enabled", - "Please disable continuous sweeping before attempting calibration." + ("Please disable continuous sweeping before attempting" + " calibration.") ).exec() self.btn_automatic.setDisabled(False) return @@ -679,8 +707,11 @@ def automaticCalibration(self): short_step = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "Calibrate short", - "Please connect the \"short\" standard to port 0 of the NanoVNA.\n\n" - "Press Ok when you are ready to continue.", + ( + "Please connect the \"short\" standard to port 0 of the" + " NanoVNA.\n\n" + "Press Ok when you are ready to continue." + ), QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) response = short_step.exec() @@ -696,7 +727,8 @@ def automaticCalibration(self): def automaticCalibrationStep(self): if self.nextStep == -1: - self.app.worker.signals.finished.disconnect(self.automaticCalibrationStep) + self.app.worker.signals.finished.disconnect( + self.automaticCalibrationStep) return if self.nextStep == 0: @@ -707,10 +739,13 @@ def automaticCalibrationStep(self): open_step = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "Calibrate open", - "Please connect the \"open\" standard to port 0 of the NanoVNA.\n\n" - "Either use a supplied open, or leave the end of the cable unconnected " - "if desired.\n\n" - "Press Ok when you are ready to continue.", + ( + "Please connect the \"open\" standard to port 0 of the" + " NanoVNA.\n\n" + "Either use a supplied open, or leave the end of the" + " cable unconnected if desired.\n\n" + "Press Ok when you are ready to continue." + ), QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) response = open_step.exec() @@ -730,8 +765,11 @@ def automaticCalibrationStep(self): load_step = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "Calibrate load", - "Please connect the \"load\" standard to port 0 of the NanoVNA.\n\n" - "Press Ok when you are ready to continue.", + ( + "Please connect the \"load\" standard to port 0 of the" + " NanoVNA.\n\n" + "Press Ok when you are ready to continue." + ), QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) response = load_step.exec() @@ -751,9 +789,13 @@ def automaticCalibrationStep(self): continue_step = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "1-port calibration complete", - "The required steps for a 1-port calibration are now complete.\n\n" - "If you wish to continue and perform a 2-port calibration, press " - "\"Yes\". To apply the 1-port calibration and stop, press \"Apply\"", + ( + "The required steps for a 1-port calibration are now" + " complete.\n\n" + "If you wish to continue and perform a 2-port calibration," + " press \"Yes\". To apply the 1-port calibration and stop," + " press \"Apply\"" + ), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Apply | QtWidgets.QMessageBox.Cancel) @@ -761,21 +803,27 @@ def automaticCalibrationStep(self): if response == QtWidgets.QMessageBox.Apply: self.calculate() self.nextStep = -1 - self.app.worker.signals.finished.disconnect(self.automaticCalibrationStep) + self.app.worker.signals.finished.disconnect( + self.automaticCalibrationStep) self.btn_automatic.setDisabled(False) return if response != QtWidgets.QMessageBox.Yes: self.btn_automatic.setDisabled(False) self.nextStep = -1 - self.app.worker.signals.finished.disconnect(self.automaticCalibrationStep) + self.app.worker.signals.finished.disconnect( + self.automaticCalibrationStep) return isolation_step = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "Calibrate isolation", - "Please connect the \"load\" standard to port 1 of the NanoVNA.\n\n" - "If available, also connect a load standard to port 0.\n\n" - "Press Ok when you are ready to continue.", + ( + "Please connect the \"load\" standard to port 1 of the" + " NanoVNA.\n\n" + "If available, also connect a load standard to" + " port 0.\n\n" + "Press Ok when you are ready to continue." + ), QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) response = isolation_step.exec() @@ -795,9 +843,11 @@ def automaticCalibrationStep(self): through_step = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "Calibrate through", - "Please connect the \"through\" standard between port 0 and port 1 " - "of the NanoVNA.\n\n" - "Press Ok when you are ready to continue.", + ( + "Please connect the \"through\" standard between" + " port 0 and port 1 of the NanoVNA.\n\n" + "Press Ok when you are ready to continue." + ), QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) response = through_step.exec() @@ -817,8 +867,10 @@ def automaticCalibrationStep(self): apply_step = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information, "Calibrate complete", - "The calibration process is now complete. Press \"Apply\" to apply " - "the calibration parameters.", + ( + "The calibration process is now complete. Press" + " \"Apply\" to apply the calibration parameters." + ), QtWidgets.QMessageBox.Apply | QtWidgets.QMessageBox.Cancel) response = apply_step.exec() diff --git a/NanoVNASaver/Windows/DisplaySettings.py b/NanoVNASaver/Windows/DisplaySettings.py index 27c892f4..b431bd54 100644 --- a/NanoVNASaver/Windows/DisplaySettings.py +++ b/NanoVNASaver/Windows/DisplaySettings.py @@ -58,7 +58,8 @@ def __init__(self, app: QtWidgets.QWidget): self.returnloss_group.addButton(self.returnloss_is_positive) self.returnloss_group.addButton(self.returnloss_is_negative) - display_options_layout.addRow("Return loss is:", self.returnloss_is_negative) + display_options_layout.addRow( + "Return loss is:", self.returnloss_is_negative) display_options_layout.addRow("", self.returnloss_is_positive) self.returnloss_is_positive.setChecked( @@ -70,7 +71,8 @@ def __init__(self, app: QtWidgets.QWidget): self.changeReturnLoss() self.show_lines_option = QtWidgets.QCheckBox("Show lines") - show_lines_label = QtWidgets.QLabel("Displays a thin line between data points") + show_lines_label = QtWidgets.QLabel( + "Displays a thin line between data points") self.show_lines_option.stateChanged.connect(self.changeShowLines) display_options_layout.addRow(self.show_lines_option, show_lines_label) @@ -103,7 +105,8 @@ def __init__(self, app: QtWidgets.QWidget): self.lineThicknessInput.setSuffix(" px") self.lineThicknessInput.setAlignment(QtCore.Qt.AlignRight) self.lineThicknessInput.valueChanged.connect(self.changeLineThickness) - display_options_layout.addRow("Line thickness", self.lineThicknessInput) + display_options_layout.addRow( + "Line thickness", self.lineThicknessInput) self.markerSizeInput = QtWidgets.QSpinBox() self.markerSizeInput.setMinimumHeight(20) @@ -117,18 +120,26 @@ def __init__(self, app: QtWidgets.QWidget): self.markerSizeInput.valueChanged.connect(self.changeMarkerSize) display_options_layout.addRow("Marker size", self.markerSizeInput) - self.show_marker_number_option = QtWidgets.QCheckBox("Show marker numbers") - show_marker_number_label = QtWidgets.QLabel("Displays the marker number next to the marker") - self.show_marker_number_option.stateChanged.connect(self.changeShowMarkerNumber) - display_options_layout.addRow(self.show_marker_number_option, show_marker_number_label) + self.show_marker_number_option = QtWidgets.QCheckBox( + "Show marker numbers") + show_marker_number_label = QtWidgets.QLabel( + "Displays the marker number next to the marker") + self.show_marker_number_option.stateChanged.connect( + self.changeShowMarkerNumber) + display_options_layout.addRow( + self.show_marker_number_option, show_marker_number_label) self.filled_marker_option = QtWidgets.QCheckBox("Filled markers") - filled_marker_label = QtWidgets.QLabel("Shows the marker as a filled triangle") - self.filled_marker_option.stateChanged.connect(self.changeFilledMarkers) - display_options_layout.addRow(self.filled_marker_option, filled_marker_label) + filled_marker_label = QtWidgets.QLabel( + "Shows the marker as a filled triangle") + self.filled_marker_option.stateChanged.connect( + self.changeFilledMarkers) + display_options_layout.addRow( + self.filled_marker_option, filled_marker_label) self.marker_tip_group = QtWidgets.QButtonGroup() - self.marker_at_center = QtWidgets.QRadioButton("At the center of the marker") + self.marker_at_center = QtWidgets.QRadioButton( + "At the center of the marker") self.marker_at_tip = QtWidgets.QRadioButton("At the tip of the marker") self.marker_tip_group.addButton(self.marker_at_center) self.marker_tip_group.addButton(self.marker_at_tip) @@ -170,7 +181,8 @@ def __init__(self, app: QtWidgets.QWidget): self.show_bands = QtWidgets.QCheckBox("Show bands") self.show_bands.setChecked(self.app.bands.enabled) - self.show_bands.stateChanged.connect(lambda: self.setShowBands(self.show_bands.isChecked())) + self.show_bands.stateChanged.connect( + lambda: self.setShowBands(self.show_bands.isChecked())) bands_layout.addRow(self.show_bands) bands_layout.addRow( "Chart bands", @@ -187,14 +199,15 @@ def __init__(self, app: QtWidgets.QWidget): vswr_marker_box = QtWidgets.QGroupBox("VSWR Markers") vswr_marker_layout = QtWidgets.QFormLayout(vswr_marker_box) - self.vswrMarkers: List[float] = self.app.settings.value("VSWRMarkers", [], float) + self.vswrMarkers: List[float] = self.app.settings.value( + "VSWRMarkers", [], float) if isinstance(self.vswrMarkers, float): # Single values from the .ini become floats rather than lists. Convert them. self.vswrMarkers = [] if self.vswrMarkers == 0.0 else [self.vswrMarkers] vswr_marker_layout.addRow( - "VSWR Markers",self.color_picker("VSWRColor", "swr")) + "VSWR Markers", self.color_picker("VSWRColor", "swr")) self.vswr_marker_dropdown = QtWidgets.QComboBox() self.vswr_marker_dropdown.setMinimumHeight(20) @@ -416,9 +429,7 @@ def changeChart(self, x, y, chart): for c in self.app.selectable_charts: if c.name == chart: found = c - - self.app.settings.setValue("Chart" + str(x) + str(y), chart) - + self.app.settings.setValue(f"Chart{x}{y}", chart) old_widget = self.app.charts_layout.itemAtPosition(x, y) if old_widget is not None: w = old_widget.widget() @@ -428,7 +439,6 @@ def changeChart(self, x, y, chart): if self.app.charts_layout.indexOf(found) > -1: logger.debug("%s is already shown, duplicating.", found.name) found = self.app.copyChart(found) - self.app.charts_layout.addWidget(found, x, y) if found.isHidden(): found.show() @@ -471,7 +481,7 @@ def changePointSize(self, size: int): c.setPointSize(size) def changeLineThickness(self, size: int): - Defaults.cfg.chart.line_thickness = int(size) + Defaults.cfg.chart.line_thickness = size for c in self.app.subscribing_charts: c.setLineThickness(size) @@ -551,7 +561,8 @@ def addMarker(self): new_marker.updated.connect(self.app.markerUpdated) label, layout = new_marker.getRow() - self.app.marker_control.layout.insertRow(Marker.count() - 1, label, layout) + self.app.marker_control.layout.insertRow( + Marker.count() - 1, label, layout) self.btn_remove_marker.setDisabled(False) if Marker.count() >= 2: @@ -569,7 +580,7 @@ def removeMarker(self): last_marker.updated.disconnect(self.app.markerUpdated) self.app.marker_data_layout.removeWidget(last_marker.get_data_layout()) - self.app.marker_control.layout.removeRow(Marker.count()-1) + self.app.marker_control.layout.removeRow(Marker.count() - 1) self.app.marker_frame.adjustSize() last_marker.get_data_layout().hide() @@ -579,7 +590,8 @@ def removeMarker(self): def addVSWRMarker(self): value, selected = QtWidgets.QInputDialog.getDouble( - self, "Add VSWR Marker", "VSWR value to show:", min=1.001, decimals=3) + self, "Add VSWR Marker", "VSWR value to show:", + min=1.001, decimals=3) if selected: self.vswrMarkers.append(value) if self.vswr_marker_dropdown.itemText(0) == "None": @@ -595,7 +607,8 @@ def removeVSWRMarker(self): if value_str != "None": value = float(value_str) self.vswrMarkers.remove(value) - self.vswr_marker_dropdown.removeItem(self.vswr_marker_dropdown.currentIndex()) + self.vswr_marker_dropdown.removeItem( + self.vswr_marker_dropdown.currentIndex()) if self.vswr_marker_dropdown.count() == 0: self.vswr_marker_dropdown.addItem("None") self.app.settings.remove("VSWRMarkers") @@ -607,4 +620,4 @@ def removeVSWRMarker(self): def updateCharts(self): for c in self.app.subscribing_charts: c.update() - Defaults.store(self.app.settings, Defaults.cfg) \ No newline at end of file + Defaults.store(self.app.settings, Defaults.cfg) From ef6a3c2d0a8f5b5a3865dd9bfd0aad286e5b7100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Thu, 15 Sep 2022 20:32:44 +0200 Subject: [PATCH 08/11] Another float glitched trough.. --- NanoVNASaver/Charts/Square.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NanoVNASaver/Charts/Square.py b/NanoVNASaver/Charts/Square.py index 5213b20b..72f56638 100644 --- a/NanoVNASaver/Charts/Square.py +++ b/NanoVNASaver/Charts/Square.py @@ -91,8 +91,8 @@ def drawValues(self, qp: QtGui.QPainter): for m in self.markers: if m.location != -1 and m.location < len(self.data): x = self.getXPosition(self.data[m.location]) - y = self.height() / 2 + \ - self.data[m.location].im * -1 * self.dim.height / 2 + y = int(self.height() // 2 - + self.data[m.location].im * self.dim.height // 2) self.drawMarker(x, y, qp, m.color, self.markers.index(m) + 1) def resizeEvent(self, a0: QtGui.QResizeEvent) -> None: From cabb8a43518969933a7ccc0664b7eb6e8cd9f4da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Thu, 15 Sep 2022 21:05:07 +0200 Subject: [PATCH 09/11] pycodestyle fixes --- NanoVNASaver/Charts/Chart.py | 4 +- NanoVNASaver/Charts/Frequency.py | 44 ++++++++++++------- NanoVNASaver/Charts/GroupDelay.py | 18 ++++---- NanoVNASaver/Charts/Magnitude.py | 6 ++- NanoVNASaver/Charts/MagnitudeZ.py | 11 +++-- NanoVNASaver/Charts/Permeability.py | 59 +++++++++++++++----------- NanoVNASaver/Charts/Phase.py | 50 ++++++++++------------ NanoVNASaver/Charts/RI.py | 65 +++++++++++++++++------------ NanoVNASaver/Charts/SParam.py | 12 ++++-- NanoVNASaver/Charts/Square.py | 7 +++- NanoVNASaver/Charts/TDR.py | 11 +++-- NanoVNASaver/Charts/VSWR.py | 8 ++-- NanoVNASaver/Marker/Widget.py | 6 ++- NanoVNASaver/Settings/Bands.py | 9 ++-- 14 files changed, 181 insertions(+), 129 deletions(-) diff --git a/NanoVNASaver/Charts/Chart.py b/NanoVNASaver/Charts/Chart.py index 1129d725..e3366816 100644 --- a/NanoVNASaver/Charts/Chart.py +++ b/NanoVNASaver/Charts/Chart.py @@ -224,7 +224,9 @@ def mouseReleaseEvent(self, a0: QtGui.QMouseEvent): self.draggedMarker = None if self.dragbox.state: self.zoomTo( - self.dragbox.pos_start[0], self.dragbox.pos_start[1], a0.x(), a0.y()) + self.dragbox.pos_start[0], + self.dragbox.pos_start[1], + a0.x(), a0.y()) self.dragbox.state = False self.dragbox.pos = (-1, -1) self.dragbox.pos_start = (0, 0) diff --git a/NanoVNASaver/Charts/Frequency.py b/NanoVNASaver/Charts/Frequency.py index 8235c78c..046f6f31 100644 --- a/NanoVNASaver/Charts/Frequency.py +++ b/NanoVNASaver/Charts/Frequency.py @@ -172,8 +172,9 @@ def __init__(self, name): self.menu.addAction(self.action_popout) self.setFocusPolicy(QtCore.Qt.ClickFocus) - self.setMinimumSize(self.dim.width + self.rightMargin + self.leftMargin, - self.dim.height + self.topMargin + self.bottomMargin) + self.setMinimumSize( + self.dim.width + self.rightMargin + self.leftMargin, + self.dim.height + self.topMargin + self.bottomMargin) self.setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)) @@ -435,8 +436,10 @@ def mouseMoveEvent(self, a0: QtGui.QMouseEvent): m.frequencyInput.setText(str(f)) def resizeEvent(self, a0: QtGui.QResizeEvent) -> None: - self.dim.width = a0.size().width() - self.rightMargin - self.leftMargin - self.dim.height = a0.size().height() - self.bottomMargin - self.topMargin + self.dim.width = ( + a0.size().width() - self.rightMargin - self.leftMargin) + self.dim.height = ( + a0.size().height() - self.bottomMargin - self.topMargin) self.update() def paintEvent(self, _: QtGui.QPaintEvent) -> None: @@ -478,10 +481,14 @@ def drawChart(self, qp: QtGui.QPainter): headline += f" ({self.name_unit})" qp.drawText(3, 15, headline) qp.setPen(QtGui.QPen(Chart.color.foreground)) - qp.drawLine(self.leftMargin, 20, - self.leftMargin, self.topMargin + self.dim.height + 5) - qp.drawLine(self.leftMargin - 5, self.topMargin + self.dim.height, - self.leftMargin + self.dim.width, self.topMargin + self.dim.height) + qp.drawLine(self.leftMargin, + 20, + self.leftMargin, + self.topMargin + self.dim.height + 5) + qp.drawLine(self.leftMargin - 5, + self.topMargin + self.dim.height, + self.leftMargin + self.dim.width, + self.topMargin + self.dim.height) self.drawTitle(qp) def drawValues(self, qp: QtGui.QPainter): @@ -506,7 +513,8 @@ def drawValues(self, qp: QtGui.QPainter): span = max_value - min_value if span == 0: logger.info( - "Span is zero for %s-Chart, setting to a small value.", self.name) + "Span is zero for %s-Chart, setting to a small value.", + self.name) span = 1e-15 self.span = span @@ -575,7 +583,9 @@ def drawFrequencyTicks(self, qp): if self.logarithmicX: fspan = math.log(self.fstop) - math.log(self.fstart) freq = round( - math.exp(((i + 1) * fspan / ticks) + math.log(self.fstart))) + math.exp( + ((i + 1) * fspan / ticks) + + math.log(self.fstart))) else: freq = round(fspan / ticks * (i + 1) + self.fstart) qp.setPen(QtGui.QPen(Chart.color.foreground)) @@ -629,12 +639,14 @@ def drawData(self, qp: QtGui.QPainter, data: List[Datapoint], if prevy is None: continue qp.setPen(line_pen) - if self.isPlotable(x, y) and self.isPlotable(prevx, prevy): - qp.drawLine(x, y, prevx, prevy) - elif self.isPlotable(x, y) and not self.isPlotable(prevx, prevy): - new_x, new_y = self.getPlotable(x, y, prevx, prevy) - qp.drawLine(x, y, new_x, new_y) - elif not self.isPlotable(x, y) and self.isPlotable(prevx, prevy): + if self.isPlotable(x, y): + if self.isPlotable(prevx, prevy): + qp.drawLine(x, y, prevx, prevy) + else: + new_x, new_y = self.getPlotable( + x, y, prevx, prevy) + qp.drawLine(x, y, new_x, new_y) + elif self.isPlotable(prevx, prevy): new_x, new_y = self.getPlotable(prevx, prevy, x, y) qp.drawLine(prevx, prevy, new_x, new_y) qp.setPen(pen) diff --git a/NanoVNASaver/Charts/GroupDelay.py b/NanoVNASaver/Charts/GroupDelay.py index ae58d83b..3ebac169 100644 --- a/NanoVNASaver/Charts/GroupDelay.py +++ b/NanoVNASaver/Charts/GroupDelay.py @@ -176,12 +176,13 @@ def draw_data(self, qp: QtGui.QPainter, color: QtGui.QColor, prevx = self.getXPosition(data[i - 1]) prevy = self.getYPositionFromDelay(delay[i - 1]) qp.setPen(line_pen) - if self.isPlotable(x, y) and self.isPlotable(prevx, prevy): - qp.drawLine(x, y, prevx, prevy) - elif self.isPlotable(x, y) and not self.isPlotable(prevx, prevy): - new_x, new_y = self.getPlotable(x, y, prevx, prevy) - qp.drawLine(x, y, new_x, new_y) - elif not self.isPlotable(x, y) and self.isPlotable(prevx, prevy): + if self.isPlotable(x, y): + if self.isPlotable(prevx, prevy): + qp.drawLine(x, y, prevx, prevy) + else: + new_x, new_y = self.getPlotable(x, y, prevx, prevy) + qp.drawLine(x, y, new_x, new_y) + elif self.isPlotable(prevx, prevy): new_x, new_y = self.getPlotable(prevx, prevy, x, y) qp.drawLine(prevx, prevy, new_x, new_y) qp.setPen(pen) @@ -197,8 +198,9 @@ def getYPosition(self, d: Datapoint) -> int: delay = 0 return self.getYPositionFromDelay(delay) - def getYPositionFromDelay(self, delay: float): - return self.topMargin + round((self.maxDelay - delay) / self.span * self.dim.height) + def getYPositionFromDelay(self, delay: float) -> int: + return self.topMargin + int( + (self.maxDelay - delay) / self.span * self.dim.height) def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin diff --git a/NanoVNASaver/Charts/Magnitude.py b/NanoVNASaver/Charts/Magnitude.py index 2c885134..0c8c9dfb 100644 --- a/NanoVNASaver/Charts/Magnitude.py +++ b/NanoVNASaver/Charts/Magnitude.py @@ -61,7 +61,8 @@ def drawValues(self, qp: QtGui.QPainter): mag = self.magnitude(d) max_value = max(max_value, mag) min_value = min(min_value, mag) - for d in self.reference: # Also check min/max for the reference sweep + # Also check min/max for the reference sweep + for d in self.reference: if d.freq < self.fstart or d.freq > self.fstop: continue max_value = max(max_value, mag) @@ -114,7 +115,8 @@ def drawValues(self, qp: QtGui.QPainter): def getYPosition(self, d: Datapoint) -> int: mag = self.magnitude(d) - return self.topMargin + round((self.maxValue - mag) / self.span * self.dim.height) + return self.topMargin + int( + (self.maxValue - mag) / self.span * self.dim.height) def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin diff --git a/NanoVNASaver/Charts/MagnitudeZ.py b/NanoVNASaver/Charts/MagnitudeZ.py index 9f1e43de..a6fd2aca 100644 --- a/NanoVNASaver/Charts/MagnitudeZ.py +++ b/NanoVNASaver/Charts/MagnitudeZ.py @@ -69,7 +69,8 @@ def drawValues(self, qp: QtGui.QPainter): continue self.maxValue = max(self.maxValue, mag) self.minValue = min(self.minValue, mag) - for d in self.reference: # Also check min/max for the reference sweep + # Also check min/max for the reference sweep + for d in self.reference: if d.freq < self.fstart or d.freq > self.fstop: continue mag = self.magnitude(d) @@ -114,9 +115,11 @@ def getYPosition(self, d: Datapoint) -> int: if math.isfinite(mag): if self.logarithmicY: span = math.log(self.maxValue) - math.log(self.minValue) - return self.topMargin + round( - (math.log(self.maxValue) - math.log(mag)) / span * self.dim.height) - return self.topMargin + round((self.maxValue - mag) / self.span * self.dim.height) + return self.topMargin + int( + (math.log(self.maxValue) - math.log(mag)) / + span * self.dim.height) + return self.topMargin + int( + (self.maxValue - mag) / self.span * self.dim.height) return self.topMargin def valueAtPosition(self, y) -> List[float]: diff --git a/NanoVNASaver/Charts/Permeability.py b/NanoVNASaver/Charts/Permeability.py index cb95323a..f4c975c4 100644 --- a/NanoVNASaver/Charts/Permeability.py +++ b/NanoVNASaver/Charts/Permeability.py @@ -96,7 +96,8 @@ def drawValues(self, qp: QtGui.QPainter): max_val = max(max_val, im) min_val = min(min_val, re) min_val = min(min_val, im) - for d in self.reference: # Also check min/max for the reference sweep + # Also check min/max for the reference sweep + for d in self.reference: if d.freq < self.fstart or d.freq > self.fstop: continue imp = d.impedance() @@ -171,24 +172,28 @@ def drawValues(self, qp: QtGui.QPainter): # Real part first line_pen.setColor(Chart.color.sweep) qp.setPen(line_pen) - if self.isPlotable(x, y_re) and self.isPlotable(prev_x, prev_y_re): - qp.drawLine(x, y_re, prev_x, prev_y_re) - elif self.isPlotable(x, y_re) and not self.isPlotable(prev_x, prev_y_re): - new_x, new_y = self.getPlotable(x, y_re, prev_x, prev_y_re) - qp.drawLine(x, y_re, new_x, new_y) - elif not self.isPlotable(x, y_re) and self.isPlotable(prev_x, prev_y_re): + if self.isPlotable(x, y_re): + if self.isPlotable(prev_x, prev_y_re): + qp.drawLine(x, y_re, prev_x, prev_y_re) + else: + new_x, new_y = self.getPlotable( + x, y_re, prev_x, prev_y_re) + qp.drawLine(x, y_re, new_x, new_y) + elif self.isPlotable(prev_x, prev_y_re): new_x, new_y = self.getPlotable(prev_x, prev_y_re, x, y_re) qp.drawLine(prev_x, prev_y_re, new_x, new_y) # Imag part second line_pen.setColor(Chart.color.sweep_secondary) qp.setPen(line_pen) - if self.isPlotable(x, y_im) and self.isPlotable(prev_x, prev_y_im): - qp.drawLine(x, y_im, prev_x, prev_y_im) - elif self.isPlotable(x, y_im) and not self.isPlotable(prev_x, prev_y_im): - new_x, new_y = self.getPlotable(x, y_im, prev_x, prev_y_im) - qp.drawLine(x, y_im, new_x, new_y) - elif not self.isPlotable(x, y_im) and self.isPlotable(prev_x, prev_y_im): + if self.isPlotable(x, y_im): + if self.isPlotable(prev_x, prev_y_im): + qp.drawLine(x, y_im, prev_x, prev_y_im) + else: + new_x, new_y = self.getPlotable( + x, y_im, prev_x, prev_y_im) + qp.drawLine(x, y_im, new_x, new_y) + elif self.isPlotable(prev_x, prev_y_im): new_x, new_y = self.getPlotable(prev_x, prev_y_im, x, y_im) qp.drawLine(prev_x, prev_y_im, new_x, new_y) @@ -231,24 +236,28 @@ def drawValues(self, qp: QtGui.QPainter): line_pen.setColor(Chart.color.reference) qp.setPen(line_pen) # Real part first - if self.isPlotable(x, y_re) and self.isPlotable(prev_x, prev_y_re): - qp.drawLine(x, y_re, prev_x, prev_y_re) - elif self.isPlotable(x, y_re) and not self.isPlotable(prev_x, prev_y_re): - new_x, new_y = self.getPlotable(x, y_re, prev_x, prev_y_re) - qp.drawLine(x, y_re, new_x, new_y) - elif not self.isPlotable(x, y_re) and self.isPlotable(prev_x, prev_y_re): + if self.isPlotable(x, y_re): + if self.isPlotable(prev_x, prev_y_re): + qp.drawLine(x, y_re, prev_x, prev_y_re) + else: + new_x, new_y = self.getPlotable( + x, y_re, prev_x, prev_y_re) + qp.drawLine(x, y_re, new_x, new_y) + elif self.isPlotable(prev_x, prev_y_re): new_x, new_y = self.getPlotable(prev_x, prev_y_re, x, y_re) qp.drawLine(prev_x, prev_y_re, new_x, new_y) line_pen.setColor(Chart.color.reference_secondary) qp.setPen(line_pen) # Imag part second - if self.isPlotable(x, y_im) and self.isPlotable(prev_x, prev_y_im): - qp.drawLine(x, y_im, prev_x, prev_y_im) - elif self.isPlotable(x, y_im) and not self.isPlotable(prev_x, prev_y_im): - new_x, new_y = self.getPlotable(x, y_im, prev_x, prev_y_im) - qp.drawLine(x, y_im, new_x, new_y) - elif not self.isPlotable(x, y_im) and self.isPlotable(prev_x, prev_y_im): + if self.isPlotable(x, y_im): + if self.isPlotable(prev_x, prev_y_im): + qp.drawLine(x, y_im, prev_x, prev_y_im) + else: + new_x, new_y = self.getPlotable( + x, y_im, prev_x, prev_y_im) + qp.drawLine(x, y_im, new_x, new_y) + elif self.isPlotable(prev_x, prev_y_im): new_x, new_y = self.getPlotable(prev_x, prev_y_im, x, y_im) qp.drawLine(prev_x, prev_y_im, new_x, new_y) diff --git a/NanoVNASaver/Charts/Phase.py b/NanoVNASaver/Charts/Phase.py index 2f740b6e..582afc10 100644 --- a/NanoVNASaver/Charts/Phase.py +++ b/NanoVNASaver/Charts/Phase.py @@ -49,7 +49,8 @@ def __init__(self, name=""): self.y_menu.addSeparator() self.action_unwrap = QtWidgets.QAction("Unwrap") self.action_unwrap.setCheckable(True) - self.action_unwrap.triggered.connect(lambda: self.setUnwrap(self.action_unwrap.isChecked())) + self.action_unwrap.triggered.connect( + lambda: self.setUnwrap(self.action_unwrap.isChecked())) self.y_menu.addAction(self.action_unwrap) def copy(self): @@ -67,14 +68,8 @@ def drawValues(self, qp: QtGui.QPainter): return if self.unwrap: - rawData = [] - for d in self.data: - rawData.append(d.phase) - - rawReference = [] - for d in self.reference: - rawReference.append(d.phase) - + rawData = [d.phase for d in self.data] + rawReference = [d.phase for d in self.reference] self.unwrappedData = np.degrees(np.unwrap(rawData)) self.unwrappedReference = np.degrees(np.unwrap(rawReference)) @@ -102,27 +97,28 @@ def drawValues(self, qp: QtGui.QPainter): for i in range(tickcount): angle = minAngle + span * i / tickcount - y = self.topMargin + round((self.maxAngle - angle) / self.span * self.dim.height) - if angle != minAngle and angle != maxAngle: + y = self.topMargin + int( + (self.maxAngle - angle) / self.span * self.dim.height) + if angle not in [minAngle, maxAngle]: qp.setPen(QtGui.QPen(Chart.color.text)) if angle != 0: - digits = max(0, min(2, math.floor(3 - math.log10(abs(angle))))) - if digits == 0: - anglestr = str(round(angle)) - else: - anglestr = str(round(angle, digits)) + digits = max( + 0, min(2, math.floor(3 - math.log10(abs(angle))))) + anglestr = str(round(angle)) if digits == 0 else str( + round(angle, digits)) else: anglestr = "0" - qp.drawText(3, y + 3, anglestr + "ยฐ") + qp.drawText(3, y + 3, f"{anglestr}ยฐ") qp.setPen(QtGui.QPen(Chart.color.foreground)) - qp.drawLine(self.leftMargin - 5, y, self.leftMargin + self.dim.width, y) + qp.drawLine(self.leftMargin - 5, y, + self.leftMargin + self.dim.width, y) qp.drawLine(self.leftMargin - 5, self.topMargin, self.leftMargin + self.dim.width, self.topMargin) qp.setPen(Chart.color.text) - qp.drawText(3, self.topMargin + 5, str(maxAngle) + "ยฐ") - qp.drawText(3, self.dim.height + self.topMargin, str(minAngle) + "ยฐ") + qp.drawText(3, self.topMargin + 5, f"{maxAngle}ยฐ") + qp.drawText(3, self.dim.height + self.topMargin, f"{minAngle}ยฐ") self._set_start_stop() @@ -136,16 +132,14 @@ def drawValues(self, qp: QtGui.QPainter): self.drawMarkers(qp) def getYPosition(self, d: Datapoint) -> int: - if self.unwrap: - if d in self.data: - angle = self.unwrappedData[self.data.index(d)] - elif d in self.reference: - angle = self.unwrappedReference[self.reference.index(d)] - else: - angle = math.degrees(d.phase) + if self.unwrap and d in self.data: + angle = self.unwrappedData[self.data.index(d)] + elif self.unwrap and d in self.reference: + angle = self.unwrappedReference[self.reference.index(d)] else: angle = math.degrees(d.phase) - return self.topMargin + round((self.maxAngle - angle) / self.span * self.dim.height) + return self.topMargin + int( + (self.maxAngle - angle) / self.span * self.dim.height) def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin diff --git a/NanoVNASaver/Charts/RI.py b/NanoVNASaver/Charts/RI.py index 567781b9..fa19d9dd 100644 --- a/NanoVNASaver/Charts/RI.py +++ b/NanoVNASaver/Charts/RI.py @@ -162,7 +162,8 @@ def drawValues(self, qp: QtGui.QPainter): min_real = min(min_real, re) max_imag = max(max_imag, im) min_imag = min(min_imag, im) - for d in self.reference: # Also check min/max for the reference sweep + # Also check min/max for the reference sweep + for d in self.reference: if d.freq < self.fstart or d.freq > self.fstop: continue imp = self.impedance(d) @@ -194,10 +195,12 @@ def drawValues(self, qp: QtGui.QPainter): span = max_imag - min_imag step_size = span / 8 if max_imag < step_size: - # The 0 line is the first step after the top. Scale accordingly. + # The 0 line is the first step after the top. + # Scale accordingly. max_imag = -min_imag / 7 elif -min_imag < step_size: - # The 0 line is the last step before the bottom. Scale accordingly. + # The 0 line is the last step before the bottom. + # Scale accordingly. min_imag = -max_imag / 7 else: # Scale max_imag to be a whole factor of min_imag @@ -275,24 +278,28 @@ def drawValues(self, qp: QtGui.QPainter): # Real part first line_pen.setColor(Chart.color.sweep) qp.setPen(line_pen) - if self.isPlotable(x, y_re) and self.isPlotable(prev_x, prev_y_re): - qp.drawLine(x, y_re, prev_x, prev_y_re) - elif self.isPlotable(x, y_re) and not self.isPlotable(prev_x, prev_y_re): - new_x, new_y = self.getPlotable(x, y_re, prev_x, prev_y_re) - qp.drawLine(x, y_re, new_x, new_y) - elif not self.isPlotable(x, y_re) and self.isPlotable(prev_x, prev_y_re): + if self.isPlotable(x, y_re): + if self.isPlotable(prev_x, prev_y_re): + qp.drawLine(x, y_re, prev_x, prev_y_re) + else: + new_x, new_y = self.getPlotable( + x, y_re, prev_x, prev_y_re) + qp.drawLine(x, y_re, new_x, new_y) + elif self.isPlotable(prev_x, prev_y_re): new_x, new_y = self.getPlotable(prev_x, prev_y_re, x, y_re) qp.drawLine(prev_x, prev_y_re, new_x, new_y) # Imag part second line_pen.setColor(Chart.color.sweep_secondary) qp.setPen(line_pen) - if self.isPlotable(x, y_im) and self.isPlotable(prev_x, prev_y_im): - qp.drawLine(x, y_im, prev_x, prev_y_im) - elif self.isPlotable(x, y_im) and not self.isPlotable(prev_x, prev_y_im): - new_x, new_y = self.getPlotable(x, y_im, prev_x, prev_y_im) - qp.drawLine(x, y_im, new_x, new_y) - elif not self.isPlotable(x, y_im) and self.isPlotable(prev_x, prev_y_im): + if self.isPlotable(x, y_im): + if self.isPlotable(prev_x, prev_y_im): + qp.drawLine(x, y_im, prev_x, prev_y_im) + else: + new_x, new_y = self.getPlotable( + x, y_im, prev_x, prev_y_im) + qp.drawLine(x, y_im, new_x, new_y) + elif self.isPlotable(prev_x, prev_y_im): new_x, new_y = self.getPlotable(prev_x, prev_y_im, x, y_im) qp.drawLine(prev_x, prev_y_im, new_x, new_y) @@ -335,24 +342,28 @@ def drawValues(self, qp: QtGui.QPainter): line_pen.setColor(Chart.color.reference) qp.setPen(line_pen) # Real part first - if self.isPlotable(x, y_re) and self.isPlotable(prev_x, prev_y_re): - qp.drawLine(x, y_re, prev_x, prev_y_re) - elif self.isPlotable(x, y_re) and not self.isPlotable(prev_x, prev_y_re): - new_x, new_y = self.getPlotable(x, y_re, prev_x, prev_y_re) - qp.drawLine(x, y_re, new_x, new_y) - elif not self.isPlotable(x, y_re) and self.isPlotable(prev_x, prev_y_re): + if self.isPlotable(x, y_re): + if self.isPlotable(prev_x, prev_y_re): + qp.drawLine(x, y_re, prev_x, prev_y_re) + else: + new_x, new_y = self.getPlotable( + x, y_re, prev_x, prev_y_re) + qp.drawLine(x, y_re, new_x, new_y) + elif self.isPlotable(prev_x, prev_y_re): new_x, new_y = self.getPlotable(prev_x, prev_y_re, x, y_re) qp.drawLine(prev_x, prev_y_re, new_x, new_y) line_pen.setColor(Chart.color.reference_secondary) qp.setPen(line_pen) # Imag part second - if self.isPlotable(x, y_im) and self.isPlotable(prev_x, prev_y_im): - qp.drawLine(x, y_im, prev_x, prev_y_im) - elif self.isPlotable(x, y_im) and not self.isPlotable(prev_x, prev_y_im): - new_x, new_y = self.getPlotable(x, y_im, prev_x, prev_y_im) - qp.drawLine(x, y_im, new_x, new_y) - elif not self.isPlotable(x, y_im) and self.isPlotable(prev_x, prev_y_im): + if self.isPlotable(x, y_im): + if self.isPlotable(prev_x, prev_y_im): + qp.drawLine(x, y_im, prev_x, prev_y_im) + else: + new_x, new_y = self.getPlotable( + x, y_im, prev_x, prev_y_im) + qp.drawLine(x, y_im, new_x, new_y) + elif self.isPlotable(prev_x, prev_y_im): new_x, new_y = self.getPlotable(prev_x, prev_y_im, x, y_im) qp.drawLine(prev_x, prev_y_im, new_x, new_y) diff --git a/NanoVNASaver/Charts/SParam.py b/NanoVNASaver/Charts/SParam.py index 832d00b9..8f7e2cdc 100644 --- a/NanoVNASaver/Charts/SParam.py +++ b/NanoVNASaver/Charts/SParam.py @@ -52,10 +52,14 @@ def drawChart(self, qp: QtGui.QPainter): qp.drawText(10, 15, "Real") qp.drawText(self.leftMargin + self.dim.width - 15, 15, "Imag") qp.setPen(QtGui.QPen(Chart.color.foreground)) - qp.drawLine(self.leftMargin, self.topMargin - 5, - self.leftMargin, self.topMargin + self.dim.height + 5) - qp.drawLine(self.leftMargin - 5, self.topMargin + self.dim.height, - self.leftMargin + self.dim.width, self.topMargin + self.dim.height) + qp.drawLine(self.leftMargin, + self.topMargin - 5, + self.leftMargin, + self.topMargin + self.dim.height + 5) + qp.drawLine(self.leftMargin - 5, + self.topMargin + self.dim.height, + self.leftMargin + self.dim.width, + self.topMargin + self.dim.height) def drawValues(self, qp: QtGui.QPainter): if len(self.data) == 0 and len(self.reference) == 0: diff --git a/NanoVNASaver/Charts/Square.py b/NanoVNASaver/Charts/Square.py index 72f56638..faf918d6 100644 --- a/NanoVNASaver/Charts/Square.py +++ b/NanoVNASaver/Charts/Square.py @@ -114,8 +114,11 @@ def mouseMoveEvent(self, a0: QtGui.QMouseEvent): y = a0.y() absx = x - (self.width() - self.dim.width) / 2 absy = y - (self.height() - self.dim.height) / 2 - if absx < 0 or absx > self.dim.width or absy < 0 or absy > self.dim.height \ - or len(self.data) == len(self.reference) == 0: + if (absx < 0 or + absx > self.dim.width or + absy < 0 or + absy > self.dim.height or + (not self.data and not self.reference)): a0.ignore() return a0.accept() diff --git a/NanoVNASaver/Charts/TDR.py b/NanoVNASaver/Charts/TDR.py index 65d98af3..8318173e 100644 --- a/NanoVNASaver/Charts/TDR.py +++ b/NanoVNASaver/Charts/TDR.py @@ -389,7 +389,8 @@ def paintEvent(self, _: QtGui.QPaintEvent) -> None: id_max = np.argmax(self.tdrWindow.td) max_point = QtCore.QPoint( self.leftMargin + int((id_max - min_index) / x_step), - (self.topMargin + height) - int(self.tdrWindow.td[id_max] / y_step)) + (self.topMargin + height) - int( + self.tdrWindow.td[id_max] / y_step)) qp.setPen(self.markers[0].color) qp.drawEllipse(max_point, 2, 2) qp.setPen(Chart.color.text) @@ -408,8 +409,9 @@ def paintEvent(self, _: QtGui.QPaintEvent) -> None: qp.drawText( marker_point.x() - 10, marker_point.y() - 5, - str(round(self.tdrWindow.distance_axis[self.markerLocation] / 2, - 2)) + "m") + str(round( + self.tdrWindow.distance_axis[self.markerLocation] / 2, + 2)) + "m") if self.dragbox.state and self.dragbox.pos[0] != -1: dashed_pen = QtGui.QPen( @@ -456,7 +458,8 @@ def lengthAtPosition(self, x, limit=True): x_step = (max_length - min_length) / width if limit and absx < 0: return min_length - return max_length if limit and absx > width else absx * x_step + min_length + return (max_length if limit and absx > width else + absx * x_step + min_length) def zoomTo(self, x1, y1, x2, y2): logger.debug( diff --git a/NanoVNASaver/Charts/VSWR.py b/NanoVNASaver/Charts/VSWR.py index e5e3ab4c..cc962e41 100644 --- a/NanoVNASaver/Charts/VSWR.py +++ b/NanoVNASaver/Charts/VSWR.py @@ -147,10 +147,12 @@ def getYPositionFromValue(self, vswr) -> int: else: return -1 return ( - self.topMargin + - round((math.log(self.maxVSWR) - math.log(vswr)) / span * self.dim.height)) + self.topMargin + int( + (math.log(self.maxVSWR) - math.log(vswr)) / + span * self.dim.height)) try: - return self.topMargin + round((self.maxVSWR - vswr) / self.span * self.dim.height) + return self.topMargin + int( + (self.maxVSWR - vswr) / self.span * self.dim.height) except OverflowError: return self.topMargin diff --git a/NanoVNASaver/Marker/Widget.py b/NanoVNASaver/Marker/Widget.py index 49b8dcf5..34167181 100644 --- a/NanoVNASaver/Marker/Widget.py +++ b/NanoVNASaver/Marker/Widget.py @@ -363,6 +363,8 @@ def updateLabels(self, self.label['s21magseries'].setText( format_magnitude(abs(_s21.seriesImpedance()))) self.label['s21realimagshunt'].setText( - format_complex_imp(_s21.shuntImpedance(), allow_negative=True)) + format_complex_imp( + _s21.shuntImpedance(), allow_negative=True)) self.label['s21realimagseries'].setText( - format_complex_imp(_s21.seriesImpedance(), allow_negative=True)) + format_complex_imp( + _s21.seriesImpedance(), allow_negative=True)) diff --git a/NanoVNASaver/Settings/Bands.py b/NanoVNASaver/Settings/Bands.py index 87fb2926..1e73206f 100644 --- a/NanoVNASaver/Settings/Bands.py +++ b/NanoVNASaver/Settings/Bands.py @@ -93,10 +93,12 @@ def data(self, index: QModelIndex, role: int = ...) -> QtCore.QVariant: if role == QtCore.Qt.TextAlignmentRole: if index.column() == 0: return QtCore.QVariant(QtCore.Qt.AlignCenter) - return QtCore.QVariant(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + return QtCore.QVariant( + QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) return QtCore.QVariant() - def setData(self, index: QModelIndex, value: typing.Any, role: int = ...) -> bool: + def setData(self, index: QModelIndex, + value: typing.Any, role: int = ...) -> bool: if role == QtCore.Qt.EditRole and index.isValid(): t = self.bands[index.row()] name = t[0] @@ -114,7 +116,8 @@ def setData(self, index: QModelIndex, value: typing.Any, role: int = ...) -> boo return True return False - def index(self, row: int, column: int, _: QModelIndex = ...) -> QModelIndex: + def index(self, row: int, + column: int, _: QModelIndex = ...) -> QModelIndex: return self.createIndex(row, column) def addRow(self): From 79a577ffe38d7d643d6b346dfc25329c8ec3e213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Thu, 15 Sep 2022 21:59:55 +0200 Subject: [PATCH 10/11] pycodestyle fixes --- NanoVNASaver/Analysis/AntennaAnalysis.py | 6 +- NanoVNASaver/Analysis/BandPassAnalysis.py | 62 +++++++++++++------ NanoVNASaver/Analysis/BandStopAnalysis.py | 42 ++++++++----- NanoVNASaver/Analysis/HighPassAnalysis.py | 40 ++++++++---- NanoVNASaver/Analysis/LowPassAnalysis.py | 18 ++++-- NanoVNASaver/Analysis/PeakSearchAnalysis.py | 3 +- .../Analysis/SimplePeakSearchAnalysis.py | 5 +- NanoVNASaver/Analysis/VSWRAnalysis.py | 57 ++++++++++------- NanoVNASaver/Controls/SerialControl.py | 3 +- NanoVNASaver/Controls/SweepControl.py | 9 ++- NanoVNASaver/Hardware/NanoVNA_V2.py | 13 ++-- NanoVNASaver/Hardware/TinySA.py | 3 +- NanoVNASaver/RFTools.py | 10 +-- NanoVNASaver/SweepWorker.py | 7 ++- NanoVNASaver/Touchstone.py | 6 +- NanoVNASaver/Windows/About.py | 11 ++-- NanoVNASaver/Windows/AnalysisWindow.py | 7 ++- NanoVNASaver/Windows/DeviceSettings.py | 6 +- NanoVNASaver/Windows/DisplaySettings.py | 6 +- NanoVNASaver/Windows/MarkerSettings.py | 6 +- NanoVNASaver/Windows/Screenshot.py | 3 +- NanoVNASaver/Windows/SweepSettings.py | 15 +++-- NanoVNASaver/Windows/TDR.py | 3 +- NanoVNASaver/__main__.py | 6 +- nanovna-saver.py | 5 +- 25 files changed, 227 insertions(+), 125 deletions(-) diff --git a/NanoVNASaver/Analysis/AntennaAnalysis.py b/NanoVNASaver/Analysis/AntennaAnalysis.py index d2a61308..af7fe4be 100644 --- a/NanoVNASaver/Analysis/AntennaAnalysis.py +++ b/NanoVNASaver/Analysis/AntennaAnalysis.py @@ -90,7 +90,8 @@ def runAnalysis(self): self.vswr_bandwith_value, self.vswr_limit_value - 1) self.input_vswr_limit.setValue(self.vswr_limit_value) logger.debug( - "found higher minimum, lowering vswr search to %s", self.vswr_limit_value) + "found higher minimum, lowering vswr search to %s", + self.vswr_limit_value) else: new_start = new_start - 5 * self.bandwith new_end = new_end + 5 * self.bandwith @@ -101,7 +102,8 @@ def runAnalysis(self): self.vswr_limit_value += 2 self.input_vswr_limit.setValue(self.vswr_limit_value) logger.debug( - "no minimum found, looking for higher value %s", self.vswr_limit_value) + "no minimum found, looking for higher value %s", + self.vswr_limit_value) new_start = max(self.min_freq, new_start) new_end = min(self.max_freq, new_end) logger.debug("next search will be %s - %s for vswr %s", diff --git a/NanoVNASaver/Analysis/BandPassAnalysis.py b/NanoVNASaver/Analysis/BandPassAnalysis.py index 159a559f..75585160 100644 --- a/NanoVNASaver/Analysis/BandPassAnalysis.py +++ b/NanoVNASaver/Analysis/BandPassAnalysis.py @@ -39,7 +39,8 @@ def __init__(self, app): layout.addRow(QtWidgets.QLabel("Band pass filter analysis")) layout.addRow( QtWidgets.QLabel( - f"Please place {self.app.markers[0].name} in the filter passband.")) + f"Please place {self.app.markers[0].name}" + f" in the filter passband.")) self.result_label = QtWidgets.QLabel() self.lower_cutoff_label = QtWidgets.QLabel() self.lower_six_db_label = QtWidgets.QLabel() @@ -134,9 +135,11 @@ def runAnalysis(self): self.result_label.setText("Lower cutoff location not found.") return - initial_lower_cutoff_frequency = self.app.data.s21[initial_lower_cutoff_location].freq + initial_lower_cutoff_frequency = ( + self.app.data.s21[initial_lower_cutoff_location].freq) - logger.debug("Found initial lower cutoff frequency at %d", initial_lower_cutoff_frequency) + logger.debug("Found initial lower cutoff frequency at %d", + initial_lower_cutoff_frequency) initial_upper_cutoff_location = -1 for i in range(pass_band_location, len(self.app.data.s21), 1): @@ -149,19 +152,23 @@ def runAnalysis(self): self.result_label.setText("Upper cutoff location not found.") return - initial_upper_cutoff_frequency = self.app.data.s21[initial_upper_cutoff_location].freq + initial_upper_cutoff_frequency = ( + self.app.data.s21[initial_upper_cutoff_location].freq) - logger.debug("Found initial upper cutoff frequency at %d", initial_upper_cutoff_frequency) + logger.debug("Found initial upper cutoff frequency at %d", + initial_upper_cutoff_frequency) peak_location = -1 peak_db = self.app.data.s21[initial_lower_cutoff_location].gain - for i in range(initial_lower_cutoff_location, initial_upper_cutoff_location, 1): + for i in range(initial_lower_cutoff_location, + initial_upper_cutoff_location, 1): db = self.app.data.s21[i].gain if db > peak_db: peak_db = db peak_location = i - logger.debug("Found peak of %f at %d", peak_db, self.app.data.s11[peak_location].freq) + logger.debug("Found peak of %f at %d", peak_db, + self.app.data.s11[peak_location].freq) lower_cutoff_location = -1 pass_band_db = peak_db @@ -171,14 +178,17 @@ def runAnalysis(self): lower_cutoff_location = i break - lower_cutoff_frequency = self.app.data.s21[lower_cutoff_location].freq - lower_cutoff_gain = self.app.data.s21[lower_cutoff_location].gain - pass_band_db + lower_cutoff_frequency = ( + self.app.data.s21[lower_cutoff_location].freq) + lower_cutoff_gain = ( + self.app.data.s21[lower_cutoff_location].gain - pass_band_db) if lower_cutoff_gain < -4: logger.debug("Lower cutoff frequency found at %f dB" " - insufficient data points for true -3 dB point.", lower_cutoff_gain) - logger.debug("Found true lower cutoff frequency at %d", lower_cutoff_frequency) + logger.debug("Found true lower cutoff frequency at %d", + lower_cutoff_frequency) self.lower_cutoff_label.setText( f"{format_frequency(lower_cutoff_frequency)}" @@ -196,13 +206,15 @@ def runAnalysis(self): break upper_cutoff_frequency = self.app.data.s21[upper_cutoff_location].freq - upper_cutoff_gain = self.app.data.s21[upper_cutoff_location].gain - pass_band_db + upper_cutoff_gain = ( + self.app.data.s21[upper_cutoff_location].gain - pass_band_db) if upper_cutoff_gain < -4: logger.debug("Upper cutoff frequency found at %f dB" " - insufficient data points for true -3 dB point.", upper_cutoff_gain) - logger.debug("Found true upper cutoff frequency at %d", upper_cutoff_frequency) + logger.debug("Found true upper cutoff frequency at %d", + upper_cutoff_frequency) self.upper_cutoff_label.setText( f"{format_frequency(upper_cutoff_frequency)}" @@ -221,7 +233,8 @@ def runAnalysis(self): self.quality_label.setText(str(round(q, 2))) self.app.markers[0].setFrequency(str(round(center_frequency))) - self.app.markers[0].frequencyInput.setText(str(round(center_frequency))) + self.app.markers[0].frequencyInput.setText( + str(round(center_frequency))) # Lower roll-off @@ -235,7 +248,8 @@ def runAnalysis(self): if lower_six_db_location < 0: self.result_label.setText("Lower 6 dB location not found.") return - lower_six_db_cutoff_frequency = self.app.data.s21[lower_six_db_location].freq + lower_six_db_cutoff_frequency = ( + self.app.data.s21[lower_six_db_location].freq) self.lower_six_db_label.setText( format_frequency(lower_six_db_cutoff_frequency)) @@ -262,7 +276,8 @@ def runAnalysis(self): if sixty_db_location > 0: if sixty_db_location > 0: - sixty_db_cutoff_frequency = self.app.data.s21[sixty_db_location].freq + sixty_db_cutoff_frequency = ( + self.app.data.s21[sixty_db_location].freq) self.lower_sixty_db_label.setText( format_frequency(sixty_db_cutoff_frequency)) elif ten_db_location != -1 and twenty_db_location != -1: @@ -275,7 +290,9 @@ def runAnalysis(self): else: self.lower_sixty_db_label.setText("Not calculated") - if ten_db_location > 0 and twenty_db_location > 0 and ten_db_location != twenty_db_location: + if (ten_db_location > 0 and + twenty_db_location > 0 and + ten_db_location != twenty_db_location): octave_attenuation, decade_attenuation = self.calculateRolloff( ten_db_location, twenty_db_location) self.lower_db_per_octave_label.setText( @@ -298,11 +315,13 @@ def runAnalysis(self): if upper_six_db_location < 0: self.result_label.setText("Upper 6 dB location not found.") return - upper_six_db_cutoff_frequency = self.app.data.s21[upper_six_db_location].freq + upper_six_db_cutoff_frequency = ( + self.app.data.s21[upper_six_db_location].freq) self.upper_six_db_label.setText( format_frequency(upper_six_db_cutoff_frequency)) - six_db_span = upper_six_db_cutoff_frequency - lower_six_db_cutoff_frequency + six_db_span = ( + upper_six_db_cutoff_frequency - lower_six_db_cutoff_frequency) self.six_db_span_label.setText( format_frequency(six_db_span)) @@ -329,7 +348,8 @@ def runAnalysis(self): break if sixty_db_location > 0: - sixty_db_cutoff_frequency = self.app.data.s21[sixty_db_location].freq + sixty_db_cutoff_frequency = ( + self.app.data.s21[sixty_db_location].freq) self.upper_sixty_db_label.setText( format_frequency(sixty_db_cutoff_frequency)) elif ten_db_location != -1 and twenty_db_location != -1: @@ -342,7 +362,9 @@ def runAnalysis(self): else: self.upper_sixty_db_label.setText("Not calculated") - if ten_db_location > 0 and twenty_db_location > 0 and ten_db_location != twenty_db_location: + if (ten_db_location > 0 and + twenty_db_location > 0 and + ten_db_location != twenty_db_location): octave_attenuation, decade_attenuation = self.calculateRolloff( ten_db_location, twenty_db_location) self.upper_db_per_octave_label.setText( diff --git a/NanoVNASaver/Analysis/BandStopAnalysis.py b/NanoVNASaver/Analysis/BandStopAnalysis.py index 8c6af782..f58a74ed 100644 --- a/NanoVNASaver/Analysis/BandStopAnalysis.py +++ b/NanoVNASaver/Analysis/BandStopAnalysis.py @@ -114,7 +114,8 @@ def runAnalysis(self): peak_db = db peak_location = i - logger.debug("Found peak of %f at %d", peak_db, self.app.data.s11[peak_location].freq) + logger.debug("Found peak of %f at %d", + peak_db, self.app.data.s11[peak_location].freq) lower_cutoff_location = -1 pass_band_db = peak_db @@ -125,14 +126,16 @@ def runAnalysis(self): break lower_cutoff_frequency = self.app.data.s21[lower_cutoff_location].freq - lower_cutoff_gain = self.app.data.s21[lower_cutoff_location].gain - pass_band_db + lower_cutoff_gain = ( + self.app.data.s21[lower_cutoff_location].gain - pass_band_db) if lower_cutoff_gain < -4: logger.debug("Lower cutoff frequency found at %f dB" " - insufficient data points for true -3 dB point.", lower_cutoff_gain) - logger.debug("Found true lower cutoff frequency at %d", lower_cutoff_frequency) + logger.debug("Found true lower cutoff frequency at %d", + lower_cutoff_frequency) self.lower_cutoff_label.setText( f"{format_frequency(lower_cutoff_frequency)}" @@ -148,14 +151,17 @@ def runAnalysis(self): upper_cutoff_location = i break - upper_cutoff_frequency = self.app.data.s21[upper_cutoff_location].freq - upper_cutoff_gain = self.app.data.s21[upper_cutoff_location].gain - pass_band_db + upper_cutoff_frequency = ( + self.app.data.s21[upper_cutoff_location].freq) + upper_cutoff_gain = ( + self.app.data.s21[upper_cutoff_location].gain - pass_band_db) if upper_cutoff_gain < -4: logger.debug("Upper cutoff frequency found at %f dB" " - insufficient data points for true -3 dB point.", upper_cutoff_gain) - logger.debug("Found true upper cutoff frequency at %d", upper_cutoff_frequency) + logger.debug("Found true upper cutoff frequency at %d", + upper_cutoff_frequency) self.upper_cutoff_label.setText( f"{format_frequency(upper_cutoff_frequency)}" @@ -164,7 +170,8 @@ def runAnalysis(self): self.app.markers[2].frequencyInput.setText(str(upper_cutoff_frequency)) span = upper_cutoff_frequency - lower_cutoff_frequency - center_frequency = math.sqrt(lower_cutoff_frequency * upper_cutoff_frequency) + center_frequency = math.sqrt( + lower_cutoff_frequency * upper_cutoff_frequency) q = center_frequency / span self.span_label.setText(format_frequency(span)) @@ -173,7 +180,8 @@ def runAnalysis(self): self.quality_label.setText(str(round(q, 2))) self.app.markers[0].setFrequency(str(round(center_frequency))) - self.app.markers[0].frequencyInput.setText(str(round(center_frequency))) + self.app.markers[0].frequencyInput.setText( + str(round(center_frequency))) # Lower roll-off @@ -187,7 +195,8 @@ def runAnalysis(self): if lower_six_db_location < 0: self.result_label.setText("Lower 6 dB location not found.") return - lower_six_db_cutoff_frequency = self.app.data.s21[lower_six_db_location].freq + lower_six_db_cutoff_frequency = ( + self.app.data.s21[lower_six_db_location].freq) self.lower_six_db_label.setText( format_frequency(lower_six_db_cutoff_frequency)) @@ -213,13 +222,15 @@ def runAnalysis(self): break if sixty_db_location > 0: - sixty_db_cutoff_frequency = self.app.data.s21[sixty_db_location].freq + sixty_db_cutoff_frequency = ( + self.app.data.s21[sixty_db_location].freq) self.lower_sixty_db_label.setText( format_frequency(sixty_db_cutoff_frequency)) elif ten_db_location != -1 and twenty_db_location != -1: ten = self.app.data.s21[ten_db_location].freq twenty = self.app.data.s21[twenty_db_location].freq - sixty_db_frequency = ten * 10 ** (5 * (math.log10(twenty) - math.log10(ten))) + sixty_db_frequency = ten * \ + 10 ** (5 * (math.log10(twenty) - math.log10(ten))) self.lower_sixty_db_label.setText( f"{format_frequency(sixty_db_frequency)} (derived)") else: @@ -250,11 +261,13 @@ def runAnalysis(self): if upper_six_db_location < 0: self.result_label.setText("Upper 6 dB location not found.") return - upper_six_db_cutoff_frequency = self.app.data.s21[upper_six_db_location].freq + upper_six_db_cutoff_frequency = ( + self.app.data.s21[upper_six_db_location].freq) self.upper_six_db_label.setText( format_frequency(upper_six_db_cutoff_frequency)) - six_db_span = upper_six_db_cutoff_frequency - lower_six_db_cutoff_frequency + six_db_span = ( + upper_six_db_cutoff_frequency - lower_six_db_cutoff_frequency) self.six_db_span_label.setText( format_frequency(six_db_span)) @@ -281,7 +294,8 @@ def runAnalysis(self): break if sixty_db_location > 0: - sixty_db_cutoff_frequency = self.app.data.s21[sixty_db_location].freq + sixty_db_cutoff_frequency = ( + self.app.data.s21[sixty_db_location].freq) self.upper_sixty_db_label.setText( format_frequency(sixty_db_cutoff_frequency)) elif ten_db_location != -1 and twenty_db_location != -1: diff --git a/NanoVNASaver/Analysis/HighPassAnalysis.py b/NanoVNASaver/Analysis/HighPassAnalysis.py index ab585a1c..40608905 100644 --- a/NanoVNASaver/Analysis/HighPassAnalysis.py +++ b/NanoVNASaver/Analysis/HighPassAnalysis.py @@ -37,7 +37,8 @@ def __init__(self, app): self._widget.setLayout(layout) layout.addRow(QtWidgets.QLabel("High pass filter analysis")) layout.addRow(QtWidgets.QLabel( - f"Please place {self.app.markers[0].name} in the filter passband.")) + f"Please place {self.app.markers[0].name}" + f" in the filter passband.")) self.result_label = QtWidgets.QLabel() self.cutoff_label = QtWidgets.QLabel() self.six_db_label = QtWidgets.QLabel() @@ -91,21 +92,27 @@ def runAnalysis(self): self.result_label.setText("Cutoff location not found.") return - initial_cutoff_frequency = self.app.data.s21[initial_cutoff_location].freq + initial_cutoff_frequency = ( + self.app.data.s21[initial_cutoff_location].freq) - logger.debug("Found initial cutoff frequency at %d", initial_cutoff_frequency) + logger.debug("Found initial cutoff frequency at %d", + initial_cutoff_frequency) peak_location = -1 peak_db = self.app.data.s21[initial_cutoff_location].gain - for i in range(len(self.app.data.s21) - 1, initial_cutoff_location - 1, -1): + for i in range(len(self.app.data.s21) - 1, + initial_cutoff_location - 1, -1): if self.app.data.s21[i].gain > peak_db: peak_db = db peak_location = i - logger.debug("Found peak of %f at %d", peak_db, self.app.data.s11[peak_location].freq) + logger.debug("Found peak of %f at %d", peak_db, + self.app.data.s11[peak_location].freq) - self.app.markers[0].setFrequency(str(self.app.data.s21[peak_location].freq)) - self.app.markers[0].frequencyInput.setText(str(self.app.data.s21[peak_location].freq)) + self.app.markers[0].setFrequency( + str(self.app.data.s21[peak_location].freq)) + self.app.markers[0].frequencyInput.setText( + str(self.app.data.s21[peak_location].freq)) cutoff_location = -1 pass_band_db = peak_db @@ -166,25 +173,32 @@ def runAnalysis(self): if sixty_db_location > 0: if sixty_db_location > 0: - sixty_db_cutoff_frequency = self.app.data.s21[sixty_db_location].freq + sixty_db_cutoff_frequency = ( + self.app.data.s21[sixty_db_location].freq) self.sixty_db_label.setText( format_frequency(sixty_db_cutoff_frequency)) elif ten_db_location != -1 and twenty_db_location != -1: ten = self.app.data.s21[ten_db_location].freq twenty = self.app.data.s21[twenty_db_location].freq - sixty_db_frequency = ten * 10 ** (5 * (math.log10(twenty) - math.log10(ten))) + sixty_db_frequency = ten * \ + 10 ** (5 * (math.log10(twenty) - math.log10(ten))) self.sixty_db_label.setText( f"{format_frequency(sixty_db_frequency)} (derived)") else: self.sixty_db_label.setText("Not calculated") - if ten_db_location > 0 and twenty_db_location > 0 and ten_db_location != twenty_db_location: + if (ten_db_location > 0 and + twenty_db_location > 0 and + ten_db_location != twenty_db_location): octave_attenuation, decade_attenuation = self.calculateRolloff( ten_db_location, twenty_db_location) - self.db_per_octave_label.setText(str(round(octave_attenuation, 3)) + " dB / octave") - self.db_per_decade_label.setText(str(round(decade_attenuation, 3)) + " dB / decade") + self.db_per_octave_label.setText( + str(round(octave_attenuation, 3)) + " dB / octave") + self.db_per_decade_label.setText( + str(round(decade_attenuation, 3)) + " dB / decade") else: self.db_per_octave_label.setText("Not calculated") self.db_per_decade_label.setText("Not calculated") - self.result_label.setText(f"Analysis complete ({len(self.app.data.s11)}) points)") + self.result_label.setText( + f"Analysis complete ({len(self.app.data.s11)}) points)") diff --git a/NanoVNASaver/Analysis/LowPassAnalysis.py b/NanoVNASaver/Analysis/LowPassAnalysis.py index 78f3d3e9..996089c3 100644 --- a/NanoVNASaver/Analysis/LowPassAnalysis.py +++ b/NanoVNASaver/Analysis/LowPassAnalysis.py @@ -94,9 +94,11 @@ def runAnalysis(self): self.result_label.setText("Cutoff location not found.") return - initial_cutoff_frequency = self.app.data.s21[initial_cutoff_location].freq + initial_cutoff_frequency = ( + self.app.data.s21[initial_cutoff_location].freq) - logger.debug("Found initial cutoff frequency at %d", initial_cutoff_frequency) + logger.debug("Found initial cutoff frequency at %d", + initial_cutoff_frequency) peak_location = -1 peak_db = self.app.data.s21[initial_cutoff_location].gain @@ -106,10 +108,13 @@ def runAnalysis(self): peak_db = db peak_location = i - logger.debug("Found peak of %f at %d", peak_db, self.app.data.s11[peak_location].freq) + logger.debug("Found peak of %f at %d", peak_db, + self.app.data.s11[peak_location].freq) - self.app.markers[0].setFrequency(str(self.app.data.s21[peak_location].freq)) - self.app.markers[0].frequencyInput.setText(str(self.app.data.s21[peak_location].freq)) + self.app.markers[0].setFrequency( + str(self.app.data.s21[peak_location].freq)) + self.app.markers[0].frequencyInput.setText( + str(self.app.data.s21[peak_location].freq)) cutoff_location = -1 pass_band_db = peak_db @@ -175,7 +180,8 @@ def runAnalysis(self): break if sixty_db_location > 0: - sixty_db_cutoff_frequency = self.app.data.s21[sixty_db_location].freq + sixty_db_cutoff_frequency = ( + self.app.data.s21[sixty_db_location].freq) self.sixty_db_label.setText( format_frequency(sixty_db_cutoff_frequency)) elif ten_db_location != -1 and twenty_db_location != -1: diff --git a/NanoVNASaver/Analysis/PeakSearchAnalysis.py b/NanoVNASaver/Analysis/PeakSearchAnalysis.py index 63a0e612..9f95b05b 100644 --- a/NanoVNASaver/Analysis/PeakSearchAnalysis.py +++ b/NanoVNASaver/Analysis/PeakSearchAnalysis.py @@ -150,7 +150,8 @@ def runAnalysis(self): logger.debug("Frequency %d", self.app.data.s11[peaks[i]].freq) logger.debug("Value %f", sign * data[peaks[i]]) self.layout.addRow( - f"Freq {format_frequency_short(self.app.data.s11[peaks[i]].freq)}", + f"Freq" + f" {format_frequency_short(self.app.data.s11[peaks[i]].freq)}", QtWidgets.QLabel(f" value {fn(sign * data[peaks[i]])}" )) diff --git a/NanoVNASaver/Analysis/SimplePeakSearchAnalysis.py b/NanoVNASaver/Analysis/SimplePeakSearchAnalysis.py index 0629885c..1f3f1d12 100644 --- a/NanoVNASaver/Analysis/SimplePeakSearchAnalysis.py +++ b/NanoVNASaver/Analysis/SimplePeakSearchAnalysis.py @@ -120,7 +120,8 @@ def runAnalysis(self): format_frequency(self.app.data.s11[idx_peak].freq)) self.peak_value.setText(str(round(data[idx_peak], 3)) + suffix) - if self.checkbox_move_marker.isChecked() and len(self.app.markers) >= 1: - self.app.markers[0].setFrequency(str(self.app.data.s11[idx_peak].freq)) + if self.checkbox_move_marker.isChecked() and self.app.markers: + self.app.markers[0].setFrequency( + str(self.app.data.s11[idx_peak].freq)) self.app.markers[0].frequencyInput.setText( format_frequency(self.app.data.s11[idx_peak].freq)) diff --git a/NanoVNASaver/Analysis/VSWRAnalysis.py b/NanoVNASaver/Analysis/VSWRAnalysis.py index bbf1b8bf..4e802f79 100644 --- a/NanoVNASaver/Analysis/VSWRAnalysis.py +++ b/NanoVNASaver/Analysis/VSWRAnalysis.py @@ -18,6 +18,7 @@ # along with this program. If not, see . import os import csv +import itertools import logging import numpy as np @@ -107,18 +108,22 @@ def runAnalysis(self): start, lowest, end = m if start != end: logger.debug( - "Section from %d to %d, lowest at %d", start, end, lowest) + "Section from %d to %d, lowest at %d", + start, end, lowest) self.layout.addRow("Start", QtWidgets.QLabel( format_frequency(self.app.data.s11[start].freq))) self.layout.addRow("Minimum", QtWidgets.QLabel( - f"{format_frequency(self.app.data.s11[lowest].freq)} ({round(data[lowest], 2)})")) + f"{format_frequency(self.app.data.s11[lowest].freq)}" + f" ({round(data[lowest], 2)})")) self.layout.addRow("End", QtWidgets.QLabel( format_frequency(self.app.data.s11[end].freq))) - self.layout.addRow("Span", QtWidgets.QLabel(format_frequency( - (self.app.data.s11[end].freq - self.app.data.s11[start].freq)))) + self.layout.addRow( + "Span", QtWidgets.QLabel(format_frequency( + (self.app.data.s11[end].freq - + self.app.data.s11[start].freq)))) else: self.layout.addRow("Low spot", QtWidgets.QLabel( @@ -204,25 +209,26 @@ def runAnalysis(self): self.layout.removeRow(self.layout.rowCount() - 1) # if len(crossing) > max_dips_shown: - # self.layout.addRow(QtWidgets.QLabel("More than " + str(max_dips_shown) + - # " dips found. Lowest shown.")) + # self.layout.addRow(QtWidgets.QLabel( + # "More than " + str(max_dips_shown) + + # " dips found. Lowest shown.")) # self.crossing = crossing[:max_dips_shown] - if len(crossing) > 0: + if crossing: extended_data = [] for m in crossing: start, lowest, end = m my_data = self._get_data(lowest) - + s11_low = self.app.data.s11[lowest] extended_data.append(my_data) if start != end: logger.debug( - "Section from %d to %d, lowest at %d", start, end, lowest) - + "Section from %d to %d, lowest at %d", + start, end, lowest) self.layout.addRow( "Resonance", QtWidgets.QLabel( - f"{format_frequency(self.app.data.s11[lowest].freq)}" - f" ({format_complex_imp(self.app.data.s11[lowest].impedance())})")) + f"{format_frequency(s11_low.freq)}" + f" ({format_complex_imp(s11_low.impedance())})")) else: self.layout.addRow("Resonance", QtWidgets.QLabel( format_frequency(self.app.data.s11[lowest].freq))) @@ -230,7 +236,6 @@ def runAnalysis(self): # Remove the final separator line self.layout.removeRow(self.layout.rowCount() - 1) if filename and extended_data: - with open(filename, 'w', newline='') as csvfile: fieldnames = extended_data[0].keys() writer = csv.DictWriter(csvfile, fieldnames=fieldnames) @@ -271,13 +276,12 @@ def runAnalysis(self): extended_data = {} both = [] tolerance = 2 - for i in maximums: - for low, _, high in crossing: - if low - tolerance <= i <= high + tolerance: - both.append(i) - continue - if low > i: - continue + for i, (low, _, high) in itertools.product(maximums, crossing): + if low - tolerance <= i <= high + tolerance: + both.append(i) + continue + if low > i: + continue if both: logger.info("%i crossing HW", len(both)) logger.info(crossing) @@ -321,8 +325,13 @@ def runAnalysis(self): diff = self.compare({}, extended_data, fields=fields) self.old_data.append(extended_data) for i, index in enumerate(sorted(extended_data.keys())): - self.layout.addRow(f"{format_frequency_short(self.app.data.s11[index].freq)}", QtWidgets.QLabel( - f" ({diff[i]['freq']}) {format_complex_imp(self.app.data.s11[index].impedance())} ({diff[i]['r']}) {diff[i]['lambda']} m")) + s11_idx = self.app.data.s11[index] + self.layout.addRow( + f"{format_frequency_short(s11_idx.freq)}", + QtWidgets.QLabel( + f" ({diff[i]['freq']})" + f" {format_complex_imp(s11_idx.impedance())}" + f" ({diff[i]['r']}) {diff[i]['lambda']} m")) if filename and extended_data: with open(filename, 'w', newline='') as csvfile: @@ -389,7 +398,9 @@ def no_compare(): logger.debug("possible missing band, ") if len(old_idx) > (i + split + 1): - if abs(new[k]["freq"] - old[old_idx[i + split + 1]]["freq"]) < max_delta_f: + if (abs(new[k]["freq"] - + old[old_idx[i + split + 1]]["freq"]) < + max_delta_f): logger.debug("new is missing band, compare next ") split += 1 # FIXME: manage 2 or more band missing ?!? diff --git a/NanoVNASaver/Controls/SerialControl.py b/NanoVNASaver/Controls/SerialControl.py index 206bed38..a8612512 100644 --- a/NanoVNASaver/Controls/SerialControl.py +++ b/NanoVNASaver/Controls/SerialControl.py @@ -114,7 +114,8 @@ def connect_device(self): else: self.app.sweep_control.set_end( frequencies[0] + - self.app.vna.datapoints * self.app.sweep_control.get_segments()) + self.app.vna.datapoints * + self.app.sweep_control.get_segments()) self.app.sweep_control.set_segments(1) # speed up things self.app.sweep_control.update_center_span() diff --git a/NanoVNASaver/Controls/SweepControl.py b/NanoVNASaver/Controls/SweepControl.py index d2b32421..959e2152 100644 --- a/NanoVNASaver/Controls/SweepControl.py +++ b/NanoVNASaver/Controls/SweepControl.py @@ -66,7 +66,8 @@ def __init__(self, app: QtWidgets.QWidget): self.input_center.setAlignment(QtCore.Qt.AlignRight) self.input_center.textEdited.connect(self.update_start_end) - input_right_layout.addRow(QtWidgets.QLabel("Center"), self.input_center) + input_right_layout.addRow(QtWidgets.QLabel( + "Center"), self.input_center) self.input_span = FrequencyInputWidget() self.input_span.setFixedHeight(20) @@ -75,14 +76,16 @@ def __init__(self, app: QtWidgets.QWidget): input_right_layout.addRow(QtWidgets.QLabel("Span"), self.input_span) - self.input_segments = QtWidgets.QLineEdit(self.app.settings.value("Segments", "1")) + self.input_segments = QtWidgets.QLineEdit( + self.app.settings.value("Segments", "1")) self.input_segments.setAlignment(QtCore.Qt.AlignRight) self.input_segments.setFixedHeight(20) self.input_segments.setFixedWidth(60) self.input_segments.textEdited.connect(self.update_step_size) self.label_step = QtWidgets.QLabel("Hz/step") - self.label_step.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.label_step.setAlignment( + QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) segment_layout = QtWidgets.QHBoxLayout() segment_layout.addWidget(self.input_segments) diff --git a/NanoVNASaver/Hardware/NanoVNA_V2.py b/NanoVNASaver/Hardware/NanoVNA_V2.py index c08eb361..4c05bc3a 100644 --- a/NanoVNASaver/Hardware/NanoVNA_V2.py +++ b/NanoVNASaver/Hardware/NanoVNA_V2.py @@ -165,8 +165,9 @@ def readValues(self, value) -> List[str]: self._sweepdata = [(complex(), complex())] * ( self.datapoints + s21hack) pointstodo = self.datapoints + s21hack - # we read at most 255 values at a time and the time required empirically is - # just over 3 seconds for 101 points or 7 seconds for 255 points + # we read at most 255 values at a time and the time required + # empirically is just over 3 seconds for 101 points or + # 7 seconds for 255 points self.serial.timeout = min(pointstodo, 255) * 0.035 + 0.1 while pointstodo > 0: logger.info("reading values") @@ -180,13 +181,15 @@ def readValues(self, value) -> List[str]: # each value is 32 bytes nBytes = pointstoread * 32 - # serial .read() will try to read nBytes bytes in timeout secs + # serial .read() will try to read nBytes bytes in + # timeout secs arr = self.serial.read(nBytes) if nBytes != len(arr): logger.warning("expected %d bytes, got %d", nBytes, len(arr)) - # the way to retry on timeout is keep the data already read - # then try to read the rest of the data into the array + # the way to retry on timeout is keep the data + # already read then try to read the rest of + # the data into the array if nBytes > len(arr): arr = arr + self.serial.read(nBytes - len(arr)) if nBytes != len(arr): diff --git a/NanoVNASaver/Hardware/TinySA.py b/NanoVNASaver/Hardware/TinySA.py index 4446276f..9dfa6f6e 100644 --- a/NanoVNASaver/Hardware/TinySA.py +++ b/NanoVNASaver/Hardware/TinySA.py @@ -113,5 +113,6 @@ def readFrequencies(self) -> List[int]: def readValues(self, value) -> List[str]: logger.debug("Read: %s", value) if value == "data 0": - self._sweepdata = [f"0 {line.strip()}" for line in self.exec_command("data")] + self._sweepdata = [f"0 {line.strip()}" + for line in self.exec_command("data")] return self._sweepdata diff --git a/NanoVNASaver/RFTools.py b/NanoVNASaver/RFTools.py index 1110e66b..ca120401 100644 --- a/NanoVNASaver/RFTools.py +++ b/NanoVNASaver/RFTools.py @@ -76,10 +76,12 @@ def qFactor(self, ref_impedance: float = 50) -> float: return -1 if imp.real == 0.0 else abs(imp.imag / imp.real) def capacitiveEquivalent(self, ref_impedance: float = 50) -> float: - return impedance_to_capacitance(self.impedance(ref_impedance), self.freq) + return impedance_to_capacitance( + self.impedance(ref_impedance), self.freq) def inductiveEquivalent(self, ref_impedance: float = 50) -> float: - return impedance_to_inductance(self.impedance(ref_impedance), self.freq) + return impedance_to_inductance( + self.impedance(ref_impedance), self.freq) def gamma_to_impedance(gamma: complex, ref_impedance: float = 50) -> complex: @@ -102,9 +104,7 @@ def impedance_to_capacitance(z: complex, freq: float) -> float: """Calculate capacitive equivalent for reactance""" if freq == 0: return -math.inf - if z.imag == 0: - return math.inf - return -(1 / (freq * 2 * math.pi * z.imag)) + return math.inf if z.imag == 0 else -(1 / (freq * 2 * math.pi * z.imag)) def impedance_to_inductance(z: complex, freq: float) -> float: diff --git a/NanoVNASaver/SweepWorker.py b/NanoVNASaver/SweepWorker.py index 26b8689d..e2ac7b4a 100644 --- a/NanoVNASaver/SweepWorker.py +++ b/NanoVNASaver/SweepWorker.py @@ -185,7 +185,6 @@ def applyCalibration(self, raw_data11: List[Datapoint], raw_data21: List[Datapoint] ) -> Tuple[List[Datapoint], List[Datapoint]]: - data11: List[Datapoint] = [] data21: List[Datapoint] = [] @@ -193,7 +192,8 @@ def applyCalibration(self, data11 = raw_data11.copy() data21 = raw_data21.copy() elif self.app.calibration.isValid1Port(): - data11.extend(self.app.calibration.correct11(dp) for dp in raw_data11) + data11.extend(self.app.calibration.correct11(dp) + for dp in raw_data11) else: data11 = raw_data11.copy() @@ -205,7 +205,8 @@ def applyCalibration(self, data21 = raw_data21 if self.offsetDelay != 0: - data11 = [correct_delay(dp, self.offsetDelay, reflect=True) for dp in data11] + data11 = [correct_delay(dp, self.offsetDelay, reflect=True) + for dp in data11] data21 = [correct_delay(dp, self.offsetDelay) for dp in data21] return data11, data21 diff --git a/NanoVNASaver/Touchstone.py b/NanoVNASaver/Touchstone.py index 32521a04..eba4d3c6 100644 --- a/NanoVNASaver/Touchstone.py +++ b/NanoVNASaver/Touchstone.py @@ -192,12 +192,14 @@ def _append_line_data(self, freq: int, data: list): vals = iter(data) for v in vals: if self.opts.format == "ri": - next(data_list).append(Datapoint(freq, float(v), float(next(vals)))) + next(data_list).append(Datapoint(freq, float(v), + float(next(vals)))) if self.opts.format == "ma": z = cmath.rect(float(v), math.radians(float(next(vals)))) next(data_list).append(Datapoint(freq, z.real, z.imag)) if self.opts.format == "db": - z = cmath.rect(10 ** (float(v) / 20), math.radians(float(next(vals)))) + z = cmath.rect(10 ** (float(v) / 20), + math.radians(float(next(vals)))) next(data_list).append(Datapoint(freq, z.real, z.imag)) def load(self): diff --git a/NanoVNASaver/Windows/About.py b/NanoVNASaver/Windows/About.py index 0d8f30f0..9e125d48 100644 --- a/NanoVNASaver/Windows/About.py +++ b/NanoVNASaver/Windows/About.py @@ -56,7 +56,7 @@ def __init__(self, app: QtWidgets.QWidget): layout.addWidget(QtWidgets.QLabel( "\N{COPYRIGHT SIGN} Copyright 2019, 2020 Rune B. Broberg\n" "\N{COPYRIGHT SIGN} Copyright 2020ff NanoVNA-Saver Authors" - )) + )) layout.addWidget(QtWidgets.QLabel( "This program comes with ABSOLUTELY NO WARRANTY")) layout.addWidget(QtWidgets.QLabel( @@ -118,15 +118,18 @@ def findUpdates(self, automatic=False): if line.startswith("RELEASE_URL ="): latest_url = line[13:].strip(" \"'") except error.HTTPError as e: - logger.exception("Checking for updates produced an HTTP exception: %s", e) + logger.exception( + "Checking for updates produced an HTTP exception: %s", e) self.updateLabel.setText("Connection error.") return except TypeError as e: - logger.exception("Checking for updates provided an unparseable file: %s", e) + logger.exception( + "Checking for updates provided an unparseable file: %s", e) self.updateLabel.setText("Data error reading versions.") return except error.URLError as e: - logger.exception("Checking for updates produced a URL exception: %s", e) + logger.exception( + "Checking for updates produced a URL exception: %s", e) self.updateLabel.setText("Connection error.") return diff --git a/NanoVNASaver/Windows/AnalysisWindow.py b/NanoVNASaver/Windows/AnalysisWindow.py index a453727f..fd31bc8c 100644 --- a/NanoVNASaver/Windows/AnalysisWindow.py +++ b/NanoVNASaver/Windows/AnalysisWindow.py @@ -20,9 +20,10 @@ from PyQt5 import QtWidgets, QtCore -from NanoVNASaver.Analysis import Analysis, LowPassAnalysis, HighPassAnalysis, \ - BandPassAnalysis, BandStopAnalysis, VSWRAnalysis, \ - SimplePeakSearchAnalysis, MagLoopAnalysis +from NanoVNASaver.Analysis import ( + Analysis, LowPassAnalysis, HighPassAnalysis, BandPassAnalysis, + BandStopAnalysis, VSWRAnalysis, SimplePeakSearchAnalysis, + MagLoopAnalysis) from NanoVNASaver.Analysis.VSWRAnalysis import ResonanceAnalysis from NanoVNASaver.Analysis.VSWRAnalysis import EFHWAnalysis from NanoVNASaver.Analysis import PeakSearchAnalysis diff --git a/NanoVNASaver/Windows/DeviceSettings.py b/NanoVNASaver/Windows/DeviceSettings.py index 6a0ffb78..cc3aad2e 100644 --- a/NanoVNASaver/Windows/DeviceSettings.py +++ b/NanoVNASaver/Windows/DeviceSettings.py @@ -63,8 +63,10 @@ def __init__(self, app: QtWidgets.QWidget): settings_box = QtWidgets.QGroupBox("Settings") settings_layout = QtWidgets.QFormLayout(settings_box) - self.chkValidateInputData = QtWidgets.QCheckBox("Validate received data") - validate_input = self.app.settings.value("SerialInputValidation", False, bool) + self.chkValidateInputData = QtWidgets.QCheckBox( + "Validate received data") + validate_input = self.app.settings.value( + "SerialInputValidation", False, bool) self.chkValidateInputData.setChecked(validate_input) self.chkValidateInputData.stateChanged.connect(self.updateValidation) settings_layout.addRow("Validation", self.chkValidateInputData) diff --git a/NanoVNASaver/Windows/DisplaySettings.py b/NanoVNASaver/Windows/DisplaySettings.py index b431bd54..f1c6526b 100644 --- a/NanoVNASaver/Windows/DisplaySettings.py +++ b/NanoVNASaver/Windows/DisplaySettings.py @@ -203,8 +203,10 @@ def __init__(self, app: QtWidgets.QWidget): "VSWRMarkers", [], float) if isinstance(self.vswrMarkers, float): - # Single values from the .ini become floats rather than lists. Convert them. - self.vswrMarkers = [] if self.vswrMarkers == 0.0 else [self.vswrMarkers] + # Single values from the .ini become floats rather than lists. + # Convert them. + self.vswrMarkers = ([] if self.vswrMarkers == 0.0 else + [self.vswrMarkers]) vswr_marker_layout.addRow( "VSWR Markers", self.color_picker("VSWRColor", "swr")) diff --git a/NanoVNASaver/Windows/MarkerSettings.py b/NanoVNASaver/Windows/MarkerSettings.py index a00b3063..4e949a84 100644 --- a/NanoVNASaver/Windows/MarkerSettings.py +++ b/NanoVNASaver/Windows/MarkerSettings.py @@ -50,7 +50,8 @@ def __init__(self, app: QtWidgets.QWidget): settings_group_box = QtWidgets.QGroupBox("Settings") settings_group_box_layout = QtWidgets.QFormLayout(settings_group_box) - self.checkboxColouredMarker = QtWidgets.QCheckBox("Colored marker name") + self.checkboxColouredMarker = QtWidgets.QCheckBox( + "Colored marker name") self.checkboxColouredMarker.setChecked( self.app.settings.value("ColoredMarkerNames", True, bool)) self.checkboxColouredMarker.stateChanged.connect(self.updateMarker) @@ -101,7 +102,8 @@ def __init__(self, app: QtWidgets.QWidget): def updateMarker(self): self.exampleMarker.setFrequency(123456000) - self.exampleMarker.setColoredText(self.checkboxColouredMarker.isChecked()) + self.exampleMarker.setColoredText( + self.checkboxColouredMarker.isChecked()) self.exampleMarker.setFieldSelection(self.currentFieldSelection) self.exampleMarker.findLocation(self.exampleData11) self.exampleMarker.resetLabels() diff --git a/NanoVNASaver/Windows/Screenshot.py b/NanoVNASaver/Windows/Screenshot.py index bc8e09e3..c967250b 100644 --- a/NanoVNASaver/Windows/Screenshot.py +++ b/NanoVNASaver/Windows/Screenshot.py @@ -97,5 +97,6 @@ def resizeEvent(self, a0: QtGui.QResizeEvent) -> None: QtCore.Qt.FastTransformation)) def setScale(self, scale): - width, height = self.pix.size().width() * scale, self.pix.size().height() * scale + width, height = (self.pix.size().width() * scale, + self.pix.size().height() * scale) self.resize(width, height) diff --git a/NanoVNASaver/Windows/SweepSettings.py b/NanoVNASaver/Windows/SweepSettings.py index 17627b6c..633af16b 100644 --- a/NanoVNASaver/Windows/SweepSettings.py +++ b/NanoVNASaver/Windows/SweepSettings.py @@ -160,7 +160,8 @@ def sweep_box(self) -> 'QtWidgets.QWidget': layout.addRow("Select band", self.band_list) sweep_pad_layout.addWidget(QtWidgets.QLabel("Pad band limits:")) - for btn_label, value in (("None", 0), ("10%", 10), ("25%", 25), ("100%", 100),): + for btn_label, value in ( + ("None", 0), ("10%", 10), ("25%", 25), ("100%", 100),): radio_button = QtWidgets.QRadioButton(btn_label) radio_button.setMinimumHeight(20) radio_button.setChecked(self.padding == value) @@ -190,10 +191,14 @@ def vna_connected(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()) + 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.padding > 0: span = stop - start diff --git a/NanoVNASaver/Windows/TDR.py b/NanoVNASaver/Windows/TDR.py index 1fcda6c9..25cdb920 100644 --- a/NanoVNASaver/Windows/TDR.py +++ b/NanoVNASaver/Windows/TDR.py @@ -164,7 +164,8 @@ def updateTDR(self): time_axis = np.linspace(0, 1 / step_size, FFT_POINTS) self.distance_axis = time_axis * v * c # peak = np.max(td) - # We should check that this is an actual *peak*, and not just a vague maximum + # We should check that this is an actual *peak*, and not just + # a vague maximum index_peak = np.argmax(self.td) cable_len = round(self.distance_axis[index_peak] / 2, 3) diff --git a/NanoVNASaver/__main__.py b/NanoVNASaver/__main__.py index 10503c03..944837c4 100644 --- a/NanoVNASaver/__main__.py +++ b/NanoVNASaver/__main__.py @@ -46,9 +46,11 @@ def main(): parser.add_argument("-D", "--debug-file", help="File to write debug logging output to") parser.add_argument("-f", "--file", - help="Touchstone file to load as sweep for off device usage") + help="Touchstone file to load as sweep for off" + " device usage") parser.add_argument("-r", "--ref-file", - help="Touchstone file to load as reference for off device usage") + help="Touchstone file to load as reference for off" + " device usage") parser.add_argument("--version", action="version", version=f"NanoVNASaver {VERSION}") args = parser.parse_args() diff --git a/nanovna-saver.py b/nanovna-saver.py index d6b6e511..9844a07d 100755 --- a/nanovna-saver.py +++ b/nanovna-saver.py @@ -1,6 +1,7 @@ #! /usr/bin/env python3 -# NanoVNASaver - a python program to view and export Touchstone data from a NanoVNA -# Copyright (C) 2019. Rune B. Broberg +# NanoVNASaver - a python program to view and export Touchstone data from a +# NanoVNA +# Copyright (C) 2019. Rune B. Broberg # # 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 From d163143356783b871d9b20d3647110da594d83f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Fri, 16 Sep 2022 08:15:16 +0200 Subject: [PATCH 11/11] Version bump --- CHANGELOG.md | 5 ++++- NanoVNASaver/About.py | 2 +- README.md | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44bfb3c7..e2b36f9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,12 @@ Changelog ========= -0.5.3-pre +0.5.3 ----- + - Int casts due to python 3.10 extension interface changes + - Pycodestyle changes + 0.5.2 ----- diff --git a/NanoVNASaver/About.py b/NanoVNASaver/About.py index 2b97b9ee..8a892078 100644 --- a/NanoVNASaver/About.py +++ b/NanoVNASaver/About.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -VERSION = "0.5.3-pre" +VERSION = "0.5.3" VERSION_URL = ( "https://raw.githubusercontent.com/" "NanoVNA-Saver/nanovna-saver/master/NanoVNASaver/About.py") diff --git a/README.md b/README.md index 4d68a2e2..a5328fd9 100644 --- a/README.md +++ b/README.md @@ -17,17 +17,20 @@ points, and generally display and analyze the resulting data. Latest Changes -------------- -### Changes in 0.5.2 +### Changes in 0.5.3 + - Python 3.10 compatability fixes - Fix crash on open in use serial device - Use a Defaults module for all settings - ignores old .ini settings - Refactoring and unifying Chart classes - No more automatic update checks (more privacy) - Corrected error handling in NanaVNA\_V2 code - - fixed crashing polar charts on python3.10 + - Fixed man float related crashes with Qt and + Python 3.10 - Using more integer divisions to get right type for QPainter points + - No more long lines in code (pycodestyle) ### Changes in 0.4.0