Trivial style changes (#625)

* Style: update type annotations

* Style: simplify extraction of version from metadata

* Style: replace some handwritten classes with namedtuples or dataclasses

* RIZ.py: remove unused import

* Style: remove some redundant lambda constructs

* Marker/Values: remove __init__ parameters

Mutable default values imply some complexity. In this case, the
constructor is always called without arguments.
pull/629/head
Name 2023-03-22 15:56:59 +01:00 zatwierdzone przez GitHub
rodzic d89c9f9d94
commit 6eb24f2315
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
42 zmienionych plików z 172 dodań i 279 usunięć

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
import math import math
from typing import Dict, List
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
@ -158,13 +157,13 @@ class BandPassAnalysis(Analysis):
self.set_result(f"Analysis complete ({len(s21)} points)") self.set_result(f"Analysis complete ({len(s21)} points)")
def derive_60dB( def derive_60dB(
self, cutoff_pos: Dict[str, int], cutoff_freq: Dict[str, float] self, cutoff_pos: dict[str, int], cutoff_freq: dict[str, float]
): ):
"""derive 60dB cutoff if needed an possible """derive 60dB cutoff if needed an possible
Args: Args:
cutoff_pos (Dict[str, int]) cutoff_pos (dict[str, int])
cutoff_freq (Dict[str, float]) cutoff_freq (dict[str, float])
""" """
if ( if (
math.isnan(cutoff_freq["60.0dB_l"]) math.isnan(cutoff_freq["60.0dB_l"])
@ -191,7 +190,7 @@ class BandPassAnalysis(Analysis):
) )
) )
def find_center(self, gains: List[float]) -> int: def find_center(self, gains: list[float]) -> int:
marker = self.app.markers[0] marker = self.app.markers[0]
if marker.location <= 0 or marker.location >= len(gains) - 1: if marker.location <= 0 or marker.location >= len(gains) - 1:
logger.debug( logger.debug(
@ -207,8 +206,8 @@ class BandPassAnalysis(Analysis):
return peak return peak
def find_bounderies( def find_bounderies(
self, gains: List[float], peak: int, peak_db: float self, gains: list[float], peak: int, peak_db: float
) -> Dict[str, int]: ) -> dict[str, int]:
cutoff_pos = {} cutoff_pos = {}
for attn in CUTOFF_VALS: for attn in CUTOFF_VALS:
cutoff_pos[f"{attn:.1f}dB_l"] = at.cut_off_left( cutoff_pos[f"{attn:.1f}dB_l"] = at.cut_off_left(

Wyświetl plik

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from typing import Dict, List
import NanoVNASaver.AnalyticTools as at import NanoVNASaver.AnalyticTools as at
from NanoVNASaver.Analysis.Base import CUTOFF_VALS from NanoVNASaver.Analysis.Base import CUTOFF_VALS
@ -31,12 +30,12 @@ class BandStopAnalysis(BandPassAnalysis):
super().__init__(app) super().__init__(app)
self.set_titel("Band stop filter analysis") self.set_titel("Band stop filter analysis")
def find_center(self, gains: List[float]) -> int: def find_center(self, gains: list[float]) -> int:
return max(enumerate(gains), key=lambda i: i[1])[0] return max(enumerate(gains), key=lambda i: i[1])[0]
def find_bounderies( def find_bounderies(
self, gains: List[float], _: int, peak_db: float self, gains: list[float], _: int, peak_db: float
) -> Dict[str, int]: ) -> dict[str, int]:
cutoff_pos = {} cutoff_pos = {}
for attn in CUTOFF_VALS: for attn in CUTOFF_VALS:
( (

Wyświetl plik

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from typing import Dict
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -34,7 +33,7 @@ class QHLine(QtWidgets.QFrame):
class Analysis: class Analysis:
def __init__(self, app: QtWidgets.QWidget): def __init__(self, app: QtWidgets.QWidget):
self.app = app self.app = app
self.label: Dict[str, QtWidgets.QLabel] = { self.label: dict[str, QtWidgets.QLabel] = {
"titel": QtWidgets.QLabel(), "titel": QtWidgets.QLabel(),
"result": QtWidgets.QLabel(), "result": QtWidgets.QLabel(),
} }

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
import math import math
from typing import Dict, List
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
@ -109,7 +108,7 @@ class HighPassAnalysis(Analysis):
self.set_result(f"Analysis complete ({len(s21)}) points)") self.set_result(f"Analysis complete ({len(s21)}) points)")
def find_level(self, gains: List[float]) -> int: def find_level(self, gains: list[float]) -> int:
marker = self.app.markers[0] marker = self.app.markers[0]
logger.debug("Pass band location: %d", marker.location) logger.debug("Pass band location: %d", marker.location)
if marker.location < 0: if marker.location < 0:
@ -118,8 +117,8 @@ class HighPassAnalysis(Analysis):
return at.center_from_idx(gains, marker.location) return at.center_from_idx(gains, marker.location)
def find_cutoffs( def find_cutoffs(
self, gains: List[float], peak: int, peak_db: float self, gains: list[float], peak: int, peak_db: float
) -> Dict[str, int]: ) -> dict[str, int]:
return { return {
f"{attn:.1f}dB": at.cut_off_left(gains, peak, peak_db, attn) f"{attn:.1f}dB": at.cut_off_left(gains, peak, peak_db, attn)
for attn in CUTOFF_VALS for attn in CUTOFF_VALS

Wyświetl plik

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from typing import Dict, List
import NanoVNASaver.AnalyticTools as at import NanoVNASaver.AnalyticTools as at
from NanoVNASaver.Analysis.Base import CUTOFF_VALS from NanoVNASaver.Analysis.Base import CUTOFF_VALS
@ -33,8 +32,8 @@ class LowPassAnalysis(HighPassAnalysis):
self.set_titel("Lowpass filter analysis") self.set_titel("Lowpass filter analysis")
def find_cutoffs( def find_cutoffs(
self, gains: List[float], peak: int, peak_db: float self, gains: list[float], peak: int, peak_db: float
) -> Dict[str, int]: ) -> dict[str, int]:
return { return {
f"{attn:.1f}dB": at.cut_off_right(gains, peak, peak_db, attn) f"{attn:.1f}dB": at.cut_off_right(gains, peak, peak_db, attn)
for attn in CUTOFF_VALS for attn in CUTOFF_VALS

Wyświetl plik

@ -19,7 +19,6 @@
import os import os
import csv import csv
import logging import logging
from typing import List
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
@ -44,7 +43,7 @@ def vswr_transformed(z, ratio=49) -> float:
class ResonanceAnalysis(Analysis): class ResonanceAnalysis(Analysis):
def __init__(self, app): def __init__(self, app):
super().__init__(app) super().__init__(app)
self.crossings: List[int] = [] self.crossings: list[int] = []
self.filename = "" self.filename = ""
self._widget = QtWidgets.QWidget() self._widget = QtWidgets.QWidget()
self.layout = QtWidgets.QFormLayout() self.layout = QtWidgets.QFormLayout()

Wyświetl plik

@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from typing import Callable, List, Tuple from typing import Callable
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
import numpy as np import numpy as np
@ -102,7 +102,7 @@ class SimplePeakSearchAnalysis(Analysis):
if self.button["move_marker"].isChecked() and self.app.markers: if self.button["move_marker"].isChecked() and self.app.markers:
self.app.markers[0].setFrequency(f"{s11[idx_peak].freq}") self.app.markers[0].setFrequency(f"{s11[idx_peak].freq}")
def data_and_format(self) -> Tuple[List[float], Callable]: def data_and_format(self) -> tuple[list[float], Callable]:
s11 = self.app.data.s11 s11 = self.app.data.s11
s21 = self.app.data.s21 s21 = self.app.data.s21

Wyświetl plik

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from typing import List
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
@ -54,7 +53,7 @@ class VSWRAnalysis(Analysis):
self.results_label = QtWidgets.QLabel("<b>Results</b>") self.results_label = QtWidgets.QLabel("<b>Results</b>")
self.layout.addRow(self.results_label) self.layout.addRow(self.results_label)
self.minimums: List[int] = [] self.minimums: list[int] = []
def runAnalysis(self): def runAnalysis(self):
if not self.app.data.s11: if not self.app.data.s11:

Wyświetl plik

@ -18,7 +18,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import itertools as it import itertools as it
import math import math
from typing import Callable, List, Tuple from typing import Callable
import numpy as np import numpy as np
@ -28,14 +28,14 @@ from scipy.signal import find_peaks
from NanoVNASaver.RFTools import Datapoint from NanoVNASaver.RFTools import Datapoint
def zero_crossings(data: List[float]) -> List[int]: def zero_crossings(data: list[float]) -> list[int]:
"""find zero crossings """find zero crossings
Args: Args:
data (List[float]): data list execute data (list[float]): data list execute
Returns: Returns:
List[int]: sorted indices of zero crossing points list[int]: sorted indices of zero crossing points
""" """
if not data: if not data:
return [] return []
@ -54,27 +54,27 @@ def zero_crossings(data: List[float]) -> List[int]:
return sorted(real_zeros + crossings) return sorted(real_zeros + crossings)
def maxima(data: List[float], threshold: float = 0.0) -> List[int]: def maxima(data: list[float], threshold: float = 0.0) -> list[int]:
"""maxima """maxima
Args: Args:
data (List[float]): data list to execute data (list[float]): data list to execute
Returns: Returns:
List[int]: indices of maxima list[int]: indices of maxima
""" """
peaks = find_peaks(data, width=2, distance=3, prominence=1)[0].tolist() peaks = find_peaks(data, width=2, distance=3, prominence=1)[0].tolist()
return [i for i in peaks if data[i] > threshold] if threshold else peaks return [i for i in peaks if data[i] > threshold] if threshold else peaks
def minima(data: List[float], threshold: float = 0.0) -> List[int]: def minima(data: list[float], threshold: float = 0.0) -> list[int]:
"""minima """minima
Args: Args:
data (List[float]): data list to execute data (list[float]): data list to execute
Returns: Returns:
List[int]: indices of minima list[int]: indices of minima
""" """
bottoms = find_peaks(-np.array(data), width=2, distance=3, prominence=1)[ bottoms = find_peaks(-np.array(data), width=2, distance=3, prominence=1)[
0 0
@ -83,18 +83,18 @@ def minima(data: List[float], threshold: float = 0.0) -> List[int]:
def take_from_idx( def take_from_idx(
data: List[float], idx: int, predicate: Callable data: list[float], idx: int, predicate: Callable
) -> List[int]: ) -> list[int]:
"""take_from_center """take_from_center
Args: Args:
data (List[float]): data list to execute data (list[float]): data list to execute
idx (int): index of a start position idx (int): index of a start position
predicate (Callable): predicate on which elements to take predicate (Callable): predicate on which elements to take
from center. (e.g. lambda i: i[1] < threshold) from center. (e.g. lambda i: i[1] < threshold)
Returns: Returns:
List[int]: indices of element matching predicate left list[int]: indices of element matching predicate left
and right from index and right from index
""" """
lower = list( lower = list(
@ -111,11 +111,11 @@ def take_from_idx(
return lower + upper return lower + upper
def center_from_idx(gains: List[float], idx: int, delta: float = 3.0) -> int: def center_from_idx(gains: list[float], idx: int, delta: float = 3.0) -> int:
"""find maximum from index postion of gains in a attn dB gain span """find maximum from index postion of gains in a attn dB gain span
Args: Args:
gains (List[float]): gain values gains (list[float]): gain values
idx (int): start position to search from idx (int): start position to search from
delta (float, optional): max gain delta from start. Defaults to 3.0. delta (float, optional): max gain delta from start. Defaults to 3.0.
@ -128,13 +128,13 @@ def center_from_idx(gains: List[float], idx: int, delta: float = 3.0) -> int:
def cut_off_left( def cut_off_left(
gains: List[float], idx: int, peak_gain: float, attn: float = 3.0 gains: list[float], idx: int, peak_gain: float, attn: float = 3.0
) -> int: ) -> int:
"""find first position in list where gain in attn lower then peak """find first position in list where gain in attn lower then peak
left from index left from index
Args: Args:
gains (List[float]): gain values gains (list[float]): gain values
idx (int): start position to search from idx (int): start position to search from
peak_gain (float): reference gain value peak_gain (float): reference gain value
attn (float, optional): attenuation to search position for. attn (float, optional): attenuation to search position for.
@ -149,13 +149,13 @@ def cut_off_left(
def cut_off_right( def cut_off_right(
gains: List[float], idx: int, peak_gain: float, attn: float = 3.0 gains: list[float], idx: int, peak_gain: float, attn: float = 3.0
) -> int: ) -> int:
"""find first position in list where gain in attn lower then peak """find first position in list where gain in attn lower then peak
right from index right from index
Args: Args:
gains (List[float]): gain values gains (list[float]): gain values
idx (int): start position to search from idx (int): start position to search from
peak_gain (float): reference gain value peak_gain (float): reference gain value
attn (float, optional): attenuation to search position for. attn (float, optional): attenuation to search position for.
@ -171,15 +171,15 @@ def cut_off_right(
def dip_cut_offs( def dip_cut_offs(
gains: List[float], peak_gain: float, attn: float = 3.0 gains: list[float], peak_gain: float, attn: float = 3.0
) -> Tuple[int, int]: ) -> tuple[int, int]:
rng = np.where(np.array(gains) < (peak_gain - attn))[0].tolist() rng = np.where(np.array(gains) < (peak_gain - attn))[0].tolist()
return (rng[0], rng[-1]) if rng else (math.nan, math.nan) return (rng[0], rng[-1]) if rng else (math.nan, math.nan)
def calculate_rolloff( def calculate_rolloff(
s21: List[Datapoint], idx_1: int, idx_2: int s21: list[Datapoint], idx_1: int, idx_2: int
) -> Tuple[float, float]: ) -> tuple[float, float]:
if idx_1 == idx_2: if idx_1 == idx_2:
return (math.nan, math.nan) return (math.nan, math.nan)
freq_1, freq_2 = s21[idx_1].freq, s21[idx_2].freq freq_1, freq_2 = s21[idx_1].freq, s21[idx_2].freq

Wyświetl plik

@ -23,7 +23,6 @@ import os
import re import re
from collections import defaultdict, UserDict from collections import defaultdict, UserDict
from dataclasses import dataclass from dataclasses import dataclass
from typing import List
from scipy.interpolate import interp1d from scipy.interpolate import interp1d
@ -235,7 +234,7 @@ class CalDataSet(UserDict):
setattr(self.data[freq], name, (dp.z)) setattr(self.data[freq], name, (dp.z))
self.data[freq].freq = freq self.data[freq].freq = freq
def frequencies(self) -> List[int]: def frequencies(self) -> list[int]:
return sorted(self.data.keys()) return sorted(self.data.keys())
def get(self, key: int, default: CalData = None) -> CalData: def get(self, key: int, default: CalData = None) -> CalData:
@ -276,7 +275,7 @@ class Calibration:
self.source = "Manual" self.source = "Manual"
def insert(self, name: str, data: List[Datapoint]): def insert(self, name: str, data: list[Datapoint]):
for dp in data: for dp in data:
self.dataset.insert(name, dp) self.dataset.insert(name, dp)

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import logging import logging
from typing import List
from PyQt6 import QtGui from PyQt6 import QtGui
@ -33,11 +32,11 @@ class CombinedLogMagChart(LogMagChart):
def __init__(self, name=""): def __init__(self, name=""):
super().__init__(name) super().__init__(name)
self.data11: List[Datapoint] = [] self.data11: list[Datapoint] = []
self.data21: List[Datapoint] = [] self.data21: list[Datapoint] = []
self.reference11: List[Datapoint] = [] self.reference11: list[Datapoint] = []
self.reference21: List[Datapoint] = [] self.reference21: list[Datapoint] = []
def setCombinedData(self, data11, data21): def setCombinedData(self, data11, data21):
self.data11 = data11 self.data11 = data11

Wyświetl plik

@ -19,7 +19,7 @@
import logging import logging
from dataclasses import dataclass, field, replace from dataclasses import dataclass, field, replace
from typing import List, Set, Tuple, ClassVar, Any, Optional from typing import ClassVar, Any
from PyQt6 import QtWidgets, QtGui, QtCore from PyQt6 import QtWidgets, QtGui, QtCore
from PyQt6.QtCore import pyqtSignal, Qt from PyQt6.QtCore import pyqtSignal, Qt
@ -67,8 +67,8 @@ class ChartDimensions:
@dataclass @dataclass
class ChartDragBox: class ChartDragBox:
pos: Tuple[int] = (-1, -1) pos: tuple[int] = (-1, -1)
pos_start: Tuple[int] = (0, 0) pos_start: tuple[int] = (0, 0)
state: bool = False state: bool = False
move_x: int = -1 move_x: int = -1
move_y: int = -1 move_y: int = -1
@ -128,11 +128,11 @@ class Chart(QtWidgets.QWidget):
self.draggedMarker = None self.draggedMarker = None
self.data: List[Datapoint] = [] self.data: list[Datapoint] = []
self.reference: List[Datapoint] = [] self.reference: list[Datapoint] = []
self.markers: List[Marker] = [] self.markers: list[Marker] = []
self.swrMarkers: Set[float] = set() self.swrMarkers: set[float] = set()
self.action_popout = QAction("Popout chart") self.action_popout = QAction("Popout chart")
self.action_popout.triggered.connect( self.action_popout.triggered.connect(
@ -192,7 +192,7 @@ class Chart(QtWidgets.QWidget):
None, None,
) )
def getNearestMarker(self, x, y) -> Optional[Marker]: def getNearestMarker(self, x, y) -> Marker | None:
if not self.data: if not self.data:
return None return None
shortest = 10**6 shortest = 10**6
@ -205,7 +205,7 @@ class Chart(QtWidgets.QWidget):
nearest = m nearest = m
return nearest return nearest
def getPosition(self, d: Datapoint) -> Tuple[int, int]: def getPosition(self, d: Datapoint) -> tuple[int, int]:
return self.getXPosition(d), self.getYPosition(d) return self.getXPosition(d), self.getYPosition(d)
def setDrawLines(self, draw_lines): def setDrawLines(self, draw_lines):

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import logging import logging
from typing import List, Tuple
import numpy as np import numpy as np
from PyQt6 import QtWidgets, QtGui, QtCore from PyQt6 import QtWidgets, QtGui, QtCore
@ -405,7 +404,7 @@ class FrequencyChart(Chart):
step = span / self.dim.width step = span / self.dim.width
return round(self.fstart + absx * step) return round(self.fstart + absx * step)
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
""" """
Returns the chart-specific value(s) at the specified Y-position Returns the chart-specific value(s) at the specified Y-position
:param y: The Y position to calculate for. :param y: The Y position to calculate for.
@ -493,7 +492,7 @@ class FrequencyChart(Chart):
self.drawDragbog(qp) self.drawDragbog(qp)
qp.end() qp.end()
def _data_oob(self, data: List[Datapoint]) -> bool: def _data_oob(self, data: list[Datapoint]) -> bool:
return data[0].freq > self.fstop or self.data[-1].freq < self.fstart return data[0].freq > self.fstop or self.data[-1].freq < self.fstart
def _check_frequency_boundaries(self, qp: QtGui.QPainter): def _check_frequency_boundaries(self, qp: QtGui.QPainter):
@ -605,7 +604,7 @@ class FrequencyChart(Chart):
self.drawData(qp, self.reference, Chart.color.reference) self.drawData(qp, self.reference, Chart.color.reference)
self.drawMarkers(qp) self.drawMarkers(qp)
def _find_scaling(self) -> Tuple[float, float]: def _find_scaling(self) -> tuple[float, float]:
min_value = self.minDisplayValue / 10e11 min_value = self.minDisplayValue / 10e11
max_value = self.maxDisplayValue / 10e11 max_value = self.maxDisplayValue / 10e11
if self.fixedValues: if self.fixedValues:
@ -686,7 +685,7 @@ class FrequencyChart(Chart):
def drawData( def drawData(
self, self,
qp: QtGui.QPainter, qp: QtGui.QPainter,
data: List[Datapoint], data: list[Datapoint],
color: QtGui.QColor, color: QtGui.QColor,
y_function=None, y_function=None,
): ):

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import logging import logging
from typing import List
import numpy as np import numpy as np
@ -74,7 +73,7 @@ class GroupDelayChart(FrequencyChart):
self.groupDelayReference = self.calc_data(self.reference) self.groupDelayReference = self.calc_data(self.reference)
self.update() self.update()
def calc_data(self, data: List[Datapoint]): def calc_data(self, data: list[Datapoint]):
data_len = len(data) data_len = len(data)
if data_len <= 1: if data_len <= 1:
return [] return []
@ -172,8 +171,8 @@ class GroupDelayChart(FrequencyChart):
self, self,
qp: QtGui.QPainter, qp: QtGui.QPainter,
color: QtGui.QColor, color: QtGui.QColor,
data: List[Datapoint], data: list[Datapoint],
delay: List[Datapoint], delay: list[Datapoint],
): ):
pen = QtGui.QPen(color) pen = QtGui.QPen(color)
pen.setWidth(self.dim.point) pen.setWidth(self.dim.point)
@ -216,7 +215,7 @@ class GroupDelayChart(FrequencyChart):
(self.maxDelay - delay) / self.span * self.dim.height (self.maxDelay - delay) / self.span * self.dim.height
) )
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
val = -1 * ((absy / self.dim.height * self.span) - self.maxDelay) val = -1 * ((absy / self.dim.height * self.span) - self.maxDelay)
return [val] return [val]

Wyświetl plik

@ -19,7 +19,6 @@
from dataclasses import dataclass from dataclasses import dataclass
import math import math
import logging import logging
from typing import List
from PyQt6 import QtGui from PyQt6 import QtGui
@ -165,7 +164,7 @@ class LogMagChart(FrequencyChart):
(self.maxValue - logMag) / self.span * self.dim.height (self.maxValue - logMag) / self.span * self.dim.height
) )
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
val = -1 * ((absy / self.dim.height * self.span) - self.maxValue) val = -1 * ((absy / self.dim.height * self.span) - self.maxValue)
return [val] return [val]

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import logging import logging
from typing import List
from PyQt6 import QtGui from PyQt6 import QtGui
@ -127,7 +126,7 @@ class MagnitudeChart(FrequencyChart):
(self.maxValue - mag) / self.span * self.dim.height (self.maxValue - mag) / self.span * self.dim.height
) )
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
val = -1 * ((absy / self.dim.height * self.span) - self.maxValue) val = -1 * ((absy / self.dim.height * self.span) - self.maxValue)
return [val] return [val]

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import logging import logging
from typing import List
from PyQt6 import QtGui from PyQt6 import QtGui
@ -129,7 +128,7 @@ class MagnitudeZChart(FrequencyChart):
) )
return self.topMargin return self.topMargin
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
if self.logarithmicY: if self.logarithmicY:
span = math.log(self.maxValue) - math.log(self.minValue) span = math.log(self.maxValue) - math.log(self.minValue)

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import logging import logging
from typing import List
from PyQt6 import QtGui from PyQt6 import QtGui
@ -325,7 +324,7 @@ class PermeabilityChart(FrequencyChart):
self.topMargin + (self.max - re) / self.span * self.dim.height self.topMargin + (self.max - re) / self.span * self.dim.height
) )
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
if self.logarithmicY: if self.logarithmicY:
min_val = self.max - self.span min_val = self.max - self.span

Wyświetl plik

@ -19,7 +19,6 @@
import math import math
import logging import logging
from typing import List
import numpy as np import numpy as np
from PyQt6.QtGui import QAction, QPainter, QPen from PyQt6.QtGui import QAction, QPainter, QPen
@ -151,7 +150,7 @@ class PhaseChart(FrequencyChart):
(self.maxAngle - angle) / self.span * self.dim.height (self.maxAngle - angle) / self.span * self.dim.height
) )
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
val = -1 * ((absy / self.dim.height * self.span) - self.maxAngle) val = -1 * ((absy / self.dim.height * self.span) - self.maxAngle)
return [val] return [val]

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import logging import logging
from typing import List
from PyQt6 import QtGui from PyQt6 import QtGui
@ -127,7 +126,7 @@ class QualityFactorChart(FrequencyChart):
(self.maxQ - Q) / self.span * self.dim.height (self.maxQ - Q) / self.span * self.dim.height
) )
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
val = -1 * ((absy / self.dim.height * self.span) - self.maxQ) val = -1 * ((absy / self.dim.height * self.span) - self.maxQ)
return [val] return [val]

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import logging import logging
from typing import List, Optional
from PyQt6 import QtWidgets, QtGui from PyQt6 import QtWidgets, QtGui
@ -381,7 +380,7 @@ class RealImaginaryChart(FrequencyChart):
else self.topMargin else self.topMargin
) )
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
valRe = -1 * ((absy / self.dim.height * self.span_real) - self.max_real) valRe = -1 * ((absy / self.dim.height * self.span_real) - self.max_real)
valIm = -1 * ((absy / self.dim.height * self.span_imag) - self.max_imag) valIm = -1 * ((absy / self.dim.height * self.span_imag) - self.max_imag)
@ -408,7 +407,7 @@ class RealImaginaryChart(FrequencyChart):
self.update() self.update()
def getNearestMarker(self, x, y) -> Optional[Marker]: def getNearestMarker(self, x, y) -> Marker | None:
if not self.data: if not self.data:
return None return None
shortest = 10e6 shortest = 10e6

Wyświetl plik

@ -18,7 +18,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from PyQt6 import QtWidgets, QtGui from PyQt6 import QtGui
from NanoVNASaver.Formatting import format_frequency_chart from NanoVNASaver.Formatting import format_frequency_chart
from NanoVNASaver.RFTools import Datapoint from NanoVNASaver.RFTools import Datapoint

Wyświetl plik

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from typing import List
from PyQt6 import QtGui from PyQt6 import QtGui
@ -142,7 +141,7 @@ class SParameterChart(FrequencyChart):
+ (self.maxValue - d.im) / self.span * self.dim.height + (self.maxValue - d.im) / self.span * self.dim.height
) )
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
val = -1 * ((absy / self.dim.height * self.span) - self.maxValue) val = -1 * ((absy / self.dim.height * self.span) - self.maxValue)
return [val] return [val]

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
import math import math
from typing import List
from PyQt6 import QtGui, QtCore, QtWidgets from PyQt6 import QtGui, QtCore, QtWidgets
@ -58,7 +57,7 @@ class SquareChart(Chart):
self, self,
qp: QtGui.QPainter, qp: QtGui.QPainter,
color: QtGui.QColor, color: QtGui.QColor,
data: List[Datapoint], data: list[Datapoint],
fstart: int = 0, fstart: int = 0,
fstop: int = 0, fstop: int = 0,
): ):

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import logging import logging
from typing import List
from PyQt6 import QtGui from PyQt6 import QtGui
@ -166,7 +165,7 @@ class VSWRChart(FrequencyChart):
def getYPosition(self, d: Datapoint) -> int: def getYPosition(self, d: Datapoint) -> int:
return self.getYPositionFromValue(d.vswr) return self.getYPositionFromValue(d.vswr)
def valueAtPosition(self, y) -> List[float]: def valueAtPosition(self, y) -> list[float]:
absy = y - self.topMargin absy = y - self.topMargin
if self.logarithmicY: if self.logarithmicY:
min_val = self.maxVSWR - self.span min_val = self.maxVSWR - self.span

Wyświetl plik

@ -62,7 +62,7 @@ class Chart:
marker_size: int = 8 marker_size: int = 8
returnloss_is_positive: bool = False returnloss_is_positive: bool = False
show_bands: bool = False show_bands: bool = False
vswr_lines: list = DC.field(default_factory=lambda: []) vswr_lines: list = DC.field(default_factory=list)
@DC.dataclass @DC.dataclass
@ -126,11 +126,11 @@ class Markers:
@DC.dataclass @DC.dataclass
class CFG: class CFG:
gui: object = DC.field(default_factory=lambda: GUI()) gui: object = DC.field(default_factory=GUI)
charts_selected: object = DC.field(default_factory=lambda: ChartsSelected()) charts_selected: object = DC.field(default_factory=ChartsSelected)
chart: object = DC.field(default_factory=lambda: Chart()) chart: object = DC.field(default_factory=Chart)
chart_colors: object = DC.field(default_factory=lambda: ChartColors()) chart_colors: object = DC.field(default_factory=ChartColors)
markers: object = DC.field(default_factory=lambda: Markers()) markers: object = DC.field(default_factory=Markers)
cfg = CFG() cfg = CFG()
@ -159,9 +159,9 @@ def store(settings: "AppSettings", data: CFG = None) -> None:
def from_type(data) -> str: def from_type(data) -> str:
type_map = { type_map = {
bytearray: lambda x: x.hex(), bytearray: bytearray.hex,
QColor: lambda x: x.getRgb(), QColor: QColor.getRgb,
QByteArray: lambda x: x.toHex(), QByteArray: QByteArray.toHex,
} }
return ( return (
f"{type_map[type(data)](data)}" if type(data) in type_map else f"{data}" f"{type_map[type(data)](data)}" if type(data) in type_map else f"{data}"

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
from numbers import Number from numbers import Number
from typing import Union
from NanoVNASaver import SITools from NanoVNASaver import SITools
@ -55,7 +54,7 @@ def format_frequency(freq: Number) -> str:
return str(SITools.Value(freq, "Hz", FMT_FREQ)) return str(SITools.Value(freq, "Hz", FMT_FREQ))
def format_frequency_inputs(freq: Union[Number, str]) -> str: def format_frequency_inputs(freq: Number | str) -> str:
return str(SITools.Value(freq, "Hz", FMT_FREQ_INPUTS)) return str(SITools.Value(freq, "Hz", FMT_FREQ_INPUTS))

Wyświetl plik

@ -20,7 +20,6 @@ import logging
import platform import platform
from collections import namedtuple from collections import namedtuple
from time import sleep from time import sleep
from typing import List
import serial import serial
from serial.tools import list_ports from serial.tools import list_ports
@ -91,7 +90,7 @@ def usb_typename(device: ListPortInfo) -> str:
# Get list of interfaces with VNAs connected # Get list of interfaces with VNAs connected
def get_interfaces() -> List[Interface]: def get_interfaces() -> list[Interface]:
interfaces = [] interfaces = []
# serial like usb interfaces # serial like usb interfaces
for d in list_ports.comports(): for d in list_ports.comports():
@ -117,7 +116,7 @@ def get_interfaces() -> List[Interface]:
return interfaces return interfaces
def get_portinfos() -> List[str]: def get_portinfos() -> list[str]:
portinfos = [] portinfos = []
# serial like usb interfaces # serial like usb interfaces
for d in list_ports.comports(): for d in list_ports.comports():

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
import struct import struct
from typing import List
import serial import serial
import numpy as np import numpy as np
@ -123,7 +122,7 @@ class NanoVNA(VNA):
self.features.add("Scan command") self.features.add("Scan command")
self.sweep_method = "scan" self.sweep_method = "scan"
def readFrequencies(self) -> List[int]: def readFrequencies(self) -> list[int]:
logger.debug("readFrequencies: %s", self.sweep_method) logger.debug("readFrequencies: %s", self.sweep_method)
if self.sweep_method != "scan_mask": if self.sweep_method != "scan_mask":
return super().readFrequencies() return super().readFrequencies()
@ -134,7 +133,7 @@ class NanoVNA(VNA):
) )
] ]
def readValues(self, value) -> List[str]: def readValues(self, value) -> list[str]:
if self.sweep_method != "scan_mask": if self.sweep_method != "scan_mask":
return super().readValues(value) return super().readValues(value)
logger.debug("readValue with scan mask (%s)", value) logger.debug("readValue with scan mask (%s)", value)

Wyświetl plik

@ -20,7 +20,6 @@ import logging
import platform import platform
from struct import pack, unpack_from from struct import pack, unpack_from
from time import sleep from time import sleep
from typing import List
from NanoVNASaver.Hardware.Serial import Interface from NanoVNASaver.Hardware.Serial import Interface
from NanoVNASaver.Hardware.VNA import VNA from NanoVNASaver.Hardware.VNA import VNA
@ -131,7 +130,7 @@ class NanoVNA_V2(VNA):
logger.debug("readFirmware: %s", result) logger.debug("readFirmware: %s", result)
return result return result
def readFrequencies(self) -> List[int]: def readFrequencies(self) -> list[int]:
return [ return [
int(self.sweepStartHz + i * self.sweepStepHz) int(self.sweepStartHz + i * self.sweepStepHz)
for i in range(self.datapoints) for i in range(self.datapoints)
@ -159,7 +158,7 @@ class NanoVNA_V2(VNA):
logger.debug("Freq index to: %i", freq_index) logger.debug("Freq index to: %i", freq_index)
def readValues(self, value) -> List[str]: def readValues(self, value) -> list[str]:
# Actually grab the data only when requesting channel 0. # Actually grab the data only when requesting channel 0.
# The hardware will return all channels which we will store. # The hardware will return all channels which we will store.
if value == "data 0": if value == "data 0":

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
import struct import struct
from typing import List
import serial import serial
import numpy as np import numpy as np
@ -109,11 +108,11 @@ class TinySA(VNA):
list(self.exec_command(f"sweep {start} {stop} {self.datapoints}")) list(self.exec_command(f"sweep {start} {stop} {self.datapoints}"))
list(self.exec_command("trigger auto")) list(self.exec_command("trigger auto"))
def readFrequencies(self) -> List[int]: def readFrequencies(self) -> list[int]:
logger.debug("readFrequencies") logger.debug("readFrequencies")
return [int(line) for line in self.exec_command("frequencies")] return [int(line) for line in self.exec_command("frequencies")]
def readValues(self, value) -> List[str]: def readValues(self, value) -> list[str]:
def conv2float(data: str) -> float: def conv2float(data: str) -> float:
try: try:
return 10 ** (float(data.strip()) / 20) return 10 ** (float(data.strip()) / 20)

Wyświetl plik

@ -18,7 +18,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from time import sleep from time import sleep
from typing import List, Iterator, Set from typing import Iterator
from PyQt6 import QtGui from PyQt6 import QtGui
@ -131,7 +131,7 @@ class VNA:
if len(self.valid_datapoints) > 1: if len(self.valid_datapoints) > 1:
self.features.add("Customizable data points") self.features.add("Customizable data points")
def get_bandwidths(self) -> List[int]: def get_bandwidths(self) -> list[int]:
logger.debug("get bandwidths") logger.debug("get bandwidths")
if self.bw_method == "dislord": if self.bw_method == "dislord":
return list(DISLORD_BW.keys()) return list(DISLORD_BW.keys())
@ -153,7 +153,7 @@ class VNA:
raise IOError(f"set_bandwith({bandwidth}: {result}") raise IOError(f"set_bandwith({bandwidth}: {result}")
self.bandwidth = bandwidth self.bandwidth = bandwidth
def readFrequencies(self) -> List[int]: def readFrequencies(self) -> list[int]:
return [int(f) for f in self.readValues("frequencies")] return [int(f) for f in self.readValues("frequencies")]
def resetSweep(self, start: int, stop: int): def resetSweep(self, start: int, stop: int):
@ -170,7 +170,7 @@ class VNA:
def connected(self) -> bool: def connected(self) -> bool:
return self.serial.is_open return self.serial.is_open
def getFeatures(self) -> Set[str]: def getFeatures(self) -> set[str]:
return self.features return self.features
def getCalibration(self) -> str: def getCalibration(self) -> str:
@ -194,7 +194,7 @@ class VNA:
logger.debug("result:\n%s", result) logger.debug("result:\n%s", result)
return result return result
def readValues(self, value) -> List[str]: def readValues(self, value) -> list[str]:
logger.debug("VNA reading %s", value) logger.debug("VNA reading %s", value)
result = list(self.exec_command(value)) result = list(self.exec_command(value))
logger.debug("VNA done reading %s (%d values)", value, len(result)) logger.debug("VNA done reading %s (%d values)", value, len(result))

Wyświetl plik

@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import List, NamedTuple from typing import NamedTuple
from NanoVNASaver.RFTools import Datapoint from NanoVNASaver.RFTools import Datapoint
@ -71,16 +71,13 @@ class Value:
"""Contains the data area to calculate marker values from""" """Contains the data area to calculate marker values from"""
def __init__( def __init__(
self, self,
freq: int = 0,
s11: List[Datapoint] = None,
s21: List[Datapoint] = None,
): ):
self.freq = freq self.freq: int = 0
self.s11 = [] if s11 is None else s11[:] self.s11: list[Datapoint] = []
self.s21 = [] if s21 is None else s21[:] self.s21: list[Datapoint] = []
def store(self, index: int, s11: List[Datapoint], s21: List[Datapoint]): def store(self, index: int, s11: list[Datapoint], s21: list[Datapoint]):
# handle boundaries # handle boundaries
if index == 0: if index == 0:
index = 1 index = 1

Wyświetl plik

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
from typing import List
from PyQt6 import QtGui, QtWidgets, QtCore from PyQt6 import QtGui, QtWidgets, QtCore
from PyQt6.QtCore import pyqtSignal from PyQt6.QtCore import pyqtSignal
@ -253,7 +252,7 @@ class Marker(QtCore.QObject, Value):
def getRow(self): def getRow(self):
return QtWidgets.QLabel(self.name), self.layout return QtWidgets.QLabel(self.name), self.layout
def findLocation(self, data: List[RFTools.Datapoint]): def findLocation(self, data: list[RFTools.Datapoint]):
self.location = -1 self.location = -1
self.frequencyInput.nextFrequency = -1 self.frequencyInput.nextFrequency = -1
self.frequencyInput.previousFrequency = -1 self.frequencyInput.previousFrequency = -1
@ -298,7 +297,7 @@ class Marker(QtCore.QObject, Value):
v.setText("") v.setText("")
def updateLabels( def updateLabels(
self, s11: List[RFTools.Datapoint], s21: List[RFTools.Datapoint] self, s11: list[RFTools.Datapoint], s21: list[RFTools.Datapoint]
): ):
if not s11: if not s11:
return return

Wyświetl plik

@ -18,7 +18,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import math import math
import cmath import cmath
from typing import List, NamedTuple from typing import NamedTuple
from NanoVNASaver.SITools import Format, clamp_value from NanoVNASaver.SITools import Format, clamp_value
@ -92,7 +92,7 @@ def gamma_to_impedance(gamma: complex, ref_impedance: float = 50) -> complex:
return math.inf return math.inf
def groupDelay(data: List[Datapoint], index: int) -> float: def groupDelay(data: list[Datapoint], index: int) -> float:
idx0 = clamp_value(index - 1, 0, len(data) - 1) idx0 = clamp_value(index - 1, 0, len(data) - 1)
idx1 = clamp_value(index + 1, 0, len(data) - 1) idx1 = clamp_value(index + 1, 0, len(data) - 1)
delta_angle = data[idx1].phase - data[idx0].phase delta_angle = data[idx1].phase - data[idx0].phase
@ -147,7 +147,7 @@ def serial_to_parallel(z: complex) -> complex:
return complex(z_sq_sum / z.real, z_sq_sum / z.imag) return complex(z_sq_sum / z.real, z_sq_sum / z.imag)
def corr_att_data(data: List[Datapoint], att: float) -> List[Datapoint]: def corr_att_data(data: list[Datapoint], att: float) -> list[Datapoint]:
"""Correct the ratio for a given attenuation on s21 input""" """Correct the ratio for a given attenuation on s21 input"""
if att <= 0: if att <= 0:
return data return data

Wyświetl plik

@ -17,10 +17,11 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from dataclasses import dataclass, replace
from enum import Enum from enum import Enum
from math import log from math import log
from threading import Lock from threading import Lock
from typing import Iterator, Tuple from typing import Iterator, NamedTuple
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -31,63 +32,28 @@ class SweepMode(Enum):
AVERAGE = 2 AVERAGE = 2
class Properties: class Properties(NamedTuple):
def __init__( name: str = ""
self, mode: "SweepMode" = SweepMode.SINGLE
name: str = "", averages: tuple[int, int] = (3, 0)
mode: "SweepMode" = SweepMode.SINGLE, logarithmic: bool = False
averages: Tuple[int, int] = (3, 0),
logarithmic: bool = False,
):
self.name = name
self.mode = mode
self.averages = averages
self.logarithmic = logarithmic
def __repr__(self):
return (
f"Properties('{self.name}', {self.mode}, {self.averages},"
f" {self.logarithmic})"
)
@dataclass
class Sweep: class Sweep:
def __init__( start: int = 3600000
self, end: int = 30000000
start: int = 3600000, points: int = 101
end: int = 30000000, segments: int = 1
points: int = 101, properties: "Properties" = Properties()
segments: int = 1,
properties: "Properties" = Properties(), def __post_init__(self):
):
self.start = start
self.end = end
self.points = points
self.segments = segments
self.properties = properties
self.lock = Lock() self.lock = Lock()
self.check() self.check()
logger.debug("%s", self) logger.debug("%s", self)
def __repr__(self) -> str:
return (
f"Sweep({self.start}, {self.end}, {self.points}, {self.segments},"
f" {self.properties})"
)
def __eq__(self, other) -> bool:
return (
self.start == other.start
and self.end == other.end
and self.points == other.points
and self.segments == other.segments
and self.properties == other.properties
)
def copy(self) -> "Sweep": def copy(self) -> "Sweep":
return Sweep( return replace(self)
self.start, self.end, self.points, self.segments, self.properties
)
@property @property
def span(self) -> int: def span(self) -> int:
@ -110,7 +76,7 @@ class Sweep:
def _exp_factor(self, index: int) -> float: def _exp_factor(self, index: int) -> float:
return 1 - log(self.segments + 1 - index) / log(self.segments + 1) return 1 - log(self.segments + 1 - index) / log(self.segments + 1)
def get_index_range(self, index: int) -> Tuple[int, int]: def get_index_range(self, index: int) -> tuple[int, int]:
if not self.properties.logarithmic: if not self.properties.logarithmic:
start = self.start + index * self.points * self.stepsize start = self.start + index * self.points * self.stepsize
end = start + (self.points - 1) * self.stepsize end = start + (self.points - 1) * self.stepsize

Wyświetl plik

@ -18,7 +18,6 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from time import sleep from time import sleep
from typing import List, Tuple
import numpy as np import numpy as np
from PyQt6 import QtCore, QtWidgets from PyQt6 import QtCore, QtWidgets
@ -31,7 +30,7 @@ from NanoVNASaver.Settings.Sweep import Sweep, SweepMode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def truncate(values: List[List[Tuple]], count: int) -> List[List[Tuple]]: def truncate(values: list[list[tuple]], count: int) -> list[list[tuple]]:
"""truncate drops extrema from data list if averaging is active""" """truncate drops extrema from data list if averaging is active"""
keep = len(values) - count keep = len(values) - count
logger.debug("Truncating from %d values to %d", len(values), keep) logger.debug("Truncating from %d values to %d", len(values), keep)
@ -62,10 +61,10 @@ class SweepWorker(QtCore.QRunnable):
self.sweep = Sweep() self.sweep = Sweep()
self.setAutoDelete(False) self.setAutoDelete(False)
self.percentage = 0 self.percentage = 0
self.data11: List[Datapoint] = [] self.data11: list[Datapoint] = []
self.data21: List[Datapoint] = [] self.data21: list[Datapoint] = []
self.rawData11: List[Datapoint] = [] self.rawData11: list[Datapoint] = []
self.rawData21: List[Datapoint] = [] self.rawData21: list[Datapoint] = []
self.init_data() self.init_data()
self.stopped = False self.stopped = False
self.running = False self.running = False
@ -187,10 +186,10 @@ class SweepWorker(QtCore.QRunnable):
self.signals.updated.emit() self.signals.updated.emit()
def applyCalibration( def applyCalibration(
self, raw_data11: List[Datapoint], raw_data21: List[Datapoint] self, raw_data11: list[Datapoint], raw_data21: list[Datapoint]
) -> Tuple[List[Datapoint], List[Datapoint]]: ) -> tuple[list[Datapoint], list[Datapoint]]:
data11: List[Datapoint] = [] data11: list[Datapoint] = []
data21: List[Datapoint] = [] data21: list[Datapoint] = []
if not self.app.calibration.isCalculated: if not self.app.calibration.isCalculated:
data11 = raw_data11.copy() data11 = raw_data11.copy()

Wyświetl plik

@ -22,8 +22,6 @@ import cmath
import io import io
from operator import attrgetter from operator import attrgetter
from typing import List
from scipy.interpolate import interp1d from scipy.interpolate import interp1d
from NanoVNASaver.RFTools import Datapoint from NanoVNASaver.RFTools import Datapoint
@ -108,42 +106,42 @@ class Touchstone:
self._interp = {} self._interp = {}
@property @property
def s11(self) -> List[Datapoint]: def s11(self) -> list[Datapoint]:
return self.s("11") return self.s("11")
@s11.setter @s11.setter
def s11(self, value: List[Datapoint]): def s11(self, value: list[Datapoint]):
self.sdata[0] = value self.sdata[0] = value
@property @property
def s12(self) -> List[Datapoint]: def s12(self) -> list[Datapoint]:
return self.s("12") return self.s("12")
@s12.setter @s12.setter
def s12(self, value: List[Datapoint]): def s12(self, value: list[Datapoint]):
self.sdata[2] = value self.sdata[2] = value
@property @property
def s21(self) -> List[Datapoint]: def s21(self) -> list[Datapoint]:
return self.s("21") return self.s("21")
@s21.setter @s21.setter
def s21(self, value: List[Datapoint]): def s21(self, value: list[Datapoint]):
self.sdata[1] = value self.sdata[1] = value
@property @property
def s22(self) -> List[Datapoint]: def s22(self) -> list[Datapoint]:
return self.s("22") return self.s("22")
@s22.setter @s22.setter
def s22(self, value: List[Datapoint]): def s22(self, value: list[Datapoint]):
self.sdata[3] = value self.sdata[3] = value
@property @property
def r(self) -> int: def r(self) -> int:
return self.opts.resistance return self.opts.resistance
def s(self, name: str) -> List[Datapoint]: def s(self, name: str) -> list[Datapoint]:
return self.sdata[Touchstone.FIELD_ORDER.index(name)] return self.sdata[Touchstone.FIELD_ORDER.index(name)]
def s_freq(self, name: str, freq: int) -> Datapoint: def s_freq(self, name: str, freq: int) -> Datapoint:

Wyświetl plik

@ -17,12 +17,12 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
import re import re
import typing
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Version: _RXP = re.compile(
RXP = re.compile(
r"""^ r"""^
\D* \D*
(?P<major>\d+)\. (?P<major>\d+)\.
@ -33,61 +33,26 @@ class Version:
re.VERBOSE, re.VERBOSE,
) )
def __init__(self, vstring: str = "0.0.0"):
self.data = {
"major": 0,
"minor": 0,
"revision": 0,
"note": "",
}
try:
self.data = Version.RXP.search(vstring).groupdict()
for name in ("major", "minor", "revision"):
self.data[name] = int(self.data[name])
except TypeError:
self.data["revision"] = 0
except AttributeError:
logger.error("Unable to parse version: %s", vstring)
def __gt__(self, other: "Version") -> bool: class _Version(typing.NamedTuple):
left, right = self.data, other.data major: int
for name in ("major", "minor", "revision"): minor: int
if left[name] > right[name]: revision: int
return True note: str
if left[name] < right[name]:
return False
return False
def __lt__(self, other: "Version") -> bool:
return other.__gt__(self)
def __ge__(self, other: "Version") -> bool:
return self.__gt__(other) or self.__eq__(other)
def __le__(self, other: "Version") -> bool:
return other.__gt__(self) or self.__eq__(other)
def __eq__(self, other: "Version") -> bool:
return self.data == other.data
def __str__(self) -> str: def __str__(self) -> str:
return ( return (
f'{self.data["major"]}.{self.data["minor"]}' f'{self.major}.{self.minor}'
f'.{self.data["revision"]}{self.data["note"]}' f'.{self.revision}{self.note}'
) )
@property
def major(self) -> int:
return self.data["major"]
@property def Version(vstring: str = "0.0.0") -> '_Version':
def minor(self) -> int: if (match := _RXP.search(vstring)) is None:
return self.data["minor"] logger.error("Unable to parse version: %s", vstring)
return _Version(0, 0, 0, '')
@property return _Version(int(match.group('major')),
def revision(self) -> int: int(match.group('minor')),
return self.data["revision"] int(match.group('revision') or '0'),
match.group('note'))
@property
def note(self) -> str:
return self.data["note"]

Wyświetl plik

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from typing import List
from PyQt6 import QtWidgets, QtCore from PyQt6 import QtWidgets, QtCore
from PyQt6.QtGui import QColor, QColorConstants, QPalette, QShortcut from PyQt6.QtGui import QColor, QColorConstants, QPalette, QShortcut
@ -210,7 +209,7 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
vswr_marker_box = QtWidgets.QGroupBox("VSWR Markers") vswr_marker_box = QtWidgets.QGroupBox("VSWR Markers")
vswr_marker_layout = QtWidgets.QFormLayout(vswr_marker_box) vswr_marker_layout = QtWidgets.QFormLayout(vswr_marker_box)
self.vswrMarkers: List[float] = self.app.settings.value( self.vswrMarkers: list[float] = self.app.settings.value(
"VSWRMarkers", [], float "VSWRMarkers", [], float
) )

Wyświetl plik

@ -1,13 +1,7 @@
from importlib.metadata import ( import importlib.metadata
PackageNotFoundError,
version,
)
try: try:
# Change here if project is renamed and does not equal the package name # Change here if project is renamed and does not equal the package name
dist_name = "nanovna-saver" __version__ = importlib.metadata.version(distribution_name="nanovna-saver")
__version__ = version(dist_name) except importlib.metadata.PackageNotFoundError: # pragma: no cover
except PackageNotFoundError: # pragma: no cover
__version__ = "unknown" __version__ = "unknown"
finally:
del version, PackageNotFoundError

Wyświetl plik

@ -27,8 +27,10 @@ class TestCases(unittest.TestCase):
def test_sweep(self): def test_sweep(self):
sweep = Sweep() sweep = Sweep()
self.assertEqual(str(sweep), self.assertEqual(str(sweep),
"Sweep(3600000, 30000000, 101, 1, Properties(''," "Sweep(start=3600000, end=30000000, points=101,"
" SweepMode.SINGLE, (3, 0), False))") " segments=1, properties=Properties(name='',"
" mode=<SweepMode.SINGLE: 0>, averages=(3, 0),"
" logarithmic=False))")
self.assertTrue(Sweep(3600000) == sweep) self.assertTrue(Sweep(3600000) == sweep)
self.assertFalse(Sweep(3600001) == sweep) self.assertFalse(Sweep(3600001) == sweep)
self.assertRaises(ValueError, Sweep, -1) self.assertRaises(ValueError, Sweep, -1)