pull/617/head
Holger Müller 2023-03-13 12:08:33 +01:00
rodzic 9ace7d8cd4
commit 5b21315a11
9 zmienionych plików z 80 dodań i 84 usunięć

Wyświetl plik

@ -39,7 +39,8 @@ points, and generally display and analyze the resulting data.
* Copyright 2019, 2020 Rune B. Broberg
* Copyright 2020ff NanoVNA-Saver Authors
It's written in **Python 3** using **PyQt6** and **scipy**.
It's developed in **Python 3 (>=3.8)** using **PyQt6**, **numpy** and
**scipy**.
Introduction
@ -88,8 +89,6 @@ Screenshot
Running the application
-----------------------
The software was written in Python on Windows, using Pycharm, and the modules
PyQT5, numpy, scipy and pyserial.
Main development is currently done on Linux (Mint 21 "Vanessa" Cinnamon)
Installation
@ -187,10 +186,13 @@ for the plot (right click on the plot).
Latest Changes
^^^^^^^^^^^^^^
* Using PyQt6
* Moved to PyScaffold project structure
Changes in 0.5.5
^^^^^^^^^^^^^^^^
* Measuring inductor core permeability
* Bugfixes for calibration data loading and saving
* Let V2 Devices more time for usb-serial setup
@ -199,7 +201,6 @@ Changes in 0.5.5
Changes in 0.5.4
^^^^^^^^^^^^^^^^
* Bugfixes for Python3.11 compatability
* Bugfix for Python3.8 compatability
* use math instead of table for log step calculation

Wyświetl plik

@ -1,2 +1,3 @@
#!/bin/sh
export PYTHONPATH="src"
exec python -m debugpy --listen 5678 --wait-for-client $@

Wyświetl plik

@ -102,8 +102,6 @@ class ResonanceAnalysis(Analysis):
self.layout.addRow(QtWidgets.QLabel("No resonance found"))
return
self
self.do_resonance_analysis()
def do_resonance_analysis(self):

Wyświetl plik

@ -144,7 +144,7 @@ class PermeabilityChart(FrequencyChart):
primary_pen = pen
secondary_pen = QtGui.QPen(Chart.color.sweep_secondary)
if len(self.data) > 0:
if self.data:
c = QtGui.QColor(Chart.color.sweep)
c.setAlpha(255)
pen = QtGui.QPen(c)
@ -215,7 +215,7 @@ class PermeabilityChart(FrequencyChart):
line_pen.setColor(Chart.color.reference)
secondary_pen.setColor(Chart.color.reference_secondary)
qp.setPen(primary_pen)
if len(self.reference) > 0:
if self.reference:
c = QtGui.QColor(Chart.color.reference)
c.setAlpha(255)
pen = QtGui.QPen(c)

Wyświetl plik

@ -22,7 +22,7 @@ import logging
from typing import List
import numpy as np
from PyQt6 import QtWidgets, QtGui
from PyQt6.QtGui import QAction, QPainter, QPen
from NanoVNASaver.RFTools import Datapoint
from NanoVNASaver.Charts.Chart import Chart
@ -47,7 +47,7 @@ class PhaseChart(FrequencyChart):
self.maxDisplayValue = 180
self.y_menu.addSeparator()
self.action_unwrap = QtGui.QAction("Unwrap")
self.action_unwrap = QAction("Unwrap")
self.action_unwrap.setCheckable(True)
self.action_unwrap.triggered.connect(
lambda: self.setUnwrap(self.action_unwrap.isChecked())
@ -64,7 +64,7 @@ class PhaseChart(FrequencyChart):
self.unwrap = unwrap
self.update()
def drawValues(self, qp: QtGui.QPainter):
def drawValues(self, qp: QPainter):
if len(self.data) == 0 and len(self.reference) == 0:
return
@ -102,7 +102,7 @@ class PhaseChart(FrequencyChart):
(self.maxAngle - angle) / self.span * self.dim.height
)
if angle not in [minAngle, maxAngle]:
qp.setPen(QtGui.QPen(Chart.color.text))
qp.setPen(QPen(Chart.color.text))
if angle != 0:
digits = max(
0, min(2, math.floor(3 - math.log10(abs(angle))))
@ -115,7 +115,7 @@ class PhaseChart(FrequencyChart):
else:
anglestr = "0"
qp.drawText(3, y + 3, f"{anglestr}°")
qp.setPen(QtGui.QPen(Chart.color.foreground))
qp.setPen(QPen(Chart.color.foreground))
qp.drawLine(
self.leftMargin - 5, y, self.leftMargin + self.dim.width, y
)

Wyświetl plik

@ -20,8 +20,18 @@ import math
import logging
import numpy as np
from PyQt6 import QtWidgets, QtGui, QtCore
from PyQt6.QtCore import Qt
from PyQt6.QtCore import QPoint, QRect, Qt
from PyQt6.QtGui import (
QAction,
QActionGroup,
QMouseEvent,
QPalette,
QPainter,
QPaintEvent,
QPen,
QResizeEvent,
)
from PyQt6.QtWidgets import QInputDialog, QMenu, QSizePolicy
from NanoVNASaver.Charts.Chart import Chart
@ -48,32 +58,32 @@ class TDRChart(Chart):
self.setMinimumSize(300, 300)
self.setSizePolicy(
QtWidgets.QSizePolicy(
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
QSizePolicy(
QSizePolicy.Policy.MinimumExpanding,
QSizePolicy.Policy.MinimumExpanding,
)
)
pal = QtGui.QPalette()
pal.setColor(QtGui.QPalette.ColorRole.Window, Chart.color.background)
pal = QPalette()
pal.setColor(QPalette.ColorRole.Window, Chart.color.background)
self.setPalette(pal)
self.setAutoFillBackground(True)
self.setContextMenuPolicy(Qt.ContextMenuPolicy.DefaultContextMenu)
self.menu = QtWidgets.QMenu()
self.menu = QMenu()
self.reset = QtGui.QAction("Reset")
self.reset = QAction("Reset")
self.reset.triggered.connect(self.resetDisplayLimits)
self.menu.addAction(self.reset)
self.x_menu = QtWidgets.QMenu("Length axis")
self.mode_group = QtGui.QActionGroup(self.x_menu)
self.action_automatic = QtGui.QAction("Automatic")
self.x_menu = QMenu("Length axis")
self.mode_group = QActionGroup(self.x_menu)
self.action_automatic = QAction("Automatic")
self.action_automatic.setCheckable(True)
self.action_automatic.setChecked(True)
self.action_automatic.changed.connect(
lambda: self.setFixedSpan(self.action_fixed_span.isChecked())
)
self.action_fixed_span = QtGui.QAction("Fixed span")
self.action_fixed_span = QAction("Fixed span")
self.action_fixed_span.setCheckable(True)
self.action_fixed_span.changed.connect(
lambda: self.setFixedSpan(self.action_fixed_span.isChecked())
@ -84,28 +94,26 @@ class TDRChart(Chart):
self.x_menu.addAction(self.action_fixed_span)
self.x_menu.addSeparator()
self.action_set_fixed_start = QtGui.QAction(
self.action_set_fixed_start = QAction(
f"Start ({self.minDisplayLength})"
)
self.action_set_fixed_start.triggered.connect(self.setMinimumLength)
self.action_set_fixed_stop = QtGui.QAction(
f"Stop ({self.maxDisplayLength})"
)
self.action_set_fixed_stop = QAction(f"Stop ({self.maxDisplayLength})")
self.action_set_fixed_stop.triggered.connect(self.setMaximumLength)
self.x_menu.addAction(self.action_set_fixed_start)
self.x_menu.addAction(self.action_set_fixed_stop)
self.y_menu = QtWidgets.QMenu("Impedance axis")
self.y_mode_group = QtGui.QActionGroup(self.y_menu)
self.y_action_automatic = QtGui.QAction("Automatic")
self.y_menu = QMenu("Impedance axis")
self.y_mode_group = QActionGroup(self.y_menu)
self.y_action_automatic = QAction("Automatic")
self.y_action_automatic.setCheckable(True)
self.y_action_automatic.setChecked(True)
self.y_action_automatic.changed.connect(
lambda: self.setFixedValues(self.y_action_fixed.isChecked())
)
self.y_action_fixed = QtGui.QAction("Fixed")
self.y_action_fixed = QAction("Fixed")
self.y_action_fixed.setCheckable(True)
self.y_action_fixed.changed.connect(
lambda: self.setFixedValues(self.y_action_fixed.isChecked())
@ -116,14 +124,14 @@ class TDRChart(Chart):
self.y_menu.addAction(self.y_action_fixed)
self.y_menu.addSeparator()
self.y_action_set_fixed_maximum = QtGui.QAction(
self.y_action_set_fixed_maximum = QAction(
f"Maximum ({self.maxImpedance})"
)
self.y_action_set_fixed_maximum.triggered.connect(
self.setMaximumImpedance
)
self.y_action_set_fixed_minimum = QtGui.QAction(
self.y_action_set_fixed_minimum = QAction(
f"Minimum ({self.minImpedance})"
)
self.y_action_set_fixed_minimum.triggered.connect(
@ -137,7 +145,7 @@ class TDRChart(Chart):
self.menu.addMenu(self.y_menu)
self.menu.addSeparator()
self.menu.addAction(self.action_save_screenshot)
self.action_popout = QtGui.QAction("Popout chart")
self.action_popout = QAction("Popout chart")
self.action_popout.triggered.connect(
lambda: self.popoutRequested.emit(self)
)
@ -177,7 +185,7 @@ class TDRChart(Chart):
self.update()
def setMinimumLength(self):
min_val, selected = QtWidgets.QInputDialog.getDouble(
min_val, selected = QInputDialog.getDouble(
self,
"Start length (m)",
"Set start length (m)",
@ -193,7 +201,7 @@ class TDRChart(Chart):
self.update()
def setMaximumLength(self):
max_val, selected = QtWidgets.QInputDialog.getDouble(
max_val, selected = QInputDialog.getDouble(
self,
"Stop length (m)",
"Set stop length (m)",
@ -213,7 +221,7 @@ class TDRChart(Chart):
self.update()
def setMinimumImpedance(self):
min_val, selected = QtWidgets.QInputDialog.getDouble(
min_val, selected = QInputDialog.getDouble(
self,
"Minimum impedance (\N{OHM SIGN})",
"Set minimum impedance (\N{OHM SIGN})",
@ -229,7 +237,7 @@ class TDRChart(Chart):
self.update()
def setMaximumImpedance(self):
max_val, selected = QtWidgets.QInputDialog.getDouble(
max_val, selected = QInputDialog.getDouble(
self,
"Maximum impedance (\N{OHM SIGN})",
"Set maximum impedance (\N{OHM SIGN})",
@ -256,7 +264,7 @@ class TDRChart(Chart):
self.tdrWindow.updated.connect(new_chart.update)
return new_chart
def mouseMoveEvent(self, a0: QtGui.QMouseEvent) -> None:
def mouseMoveEvent(self, a0: QMouseEvent) -> None:
if a0.buttons() == Qt.MouseButton.RightButton:
a0.ignore()
return
@ -310,12 +318,12 @@ class TDRChart(Chart):
def _draw_ticks(self, height, width, x_step, min_index):
ticks = (self.width() - self.leftMargin) // 100
qp = QtGui.QPainter(self)
qp = QPainter(self)
for i in range(ticks):
x = self.leftMargin + round((i + 1) * width / ticks)
qp.setPen(QtGui.QPen(Chart.color.foreground))
qp.setPen(QPen(Chart.color.foreground))
qp.drawLine(x, self.topMargin, x, self.topMargin + height)
qp.setPen(QtGui.QPen(Chart.color.text))
qp.setPen(QPen(Chart.color.text))
distance = (
self.tdrWindow.distance_axis[
min_index + int((x - self.leftMargin) * x_step) - 1
@ -325,15 +333,15 @@ class TDRChart(Chart):
qp.drawText(
x - 15, self.topMargin + height + 15, f"{round(distance, 1)}m"
)
qp.setPen(QtGui.QPen(Chart.color.text))
qp.setPen(QPen(Chart.color.text))
qp.drawText(
self.leftMargin - 10,
self.topMargin + height + 15,
str(round(self.tdrWindow.distance_axis[min_index] / 2, 1)) + "m",
f"{str(round(self.tdrWindow.distance_axis[min_index] / 2, 1))}m",
)
def _draw_y_ticks(self, height, width, min_impedance, max_impedance):
qp = QtGui.QPainter(self)
qp = QPainter(self)
y_step = (max_impedance - min_impedance) / height
y_ticks = math.floor(height / 60)
y_tick_step = height / y_ticks
@ -350,10 +358,10 @@ class TDRChart(Chart):
)
def _draw_max_point(self, height, x_step, y_step, min_index):
qp = QtGui.QPainter(self)
qp = QPainter(self)
id_max = np.argmax(self.tdrWindow.td)
max_point = QtCore.QPoint(
max_point = QPoint(
self.leftMargin + int((id_max - min_index) / x_step),
(self.topMargin + height) - int(self.tdrWindow.td[id_max] / y_step),
)
@ -368,8 +376,8 @@ class TDRChart(Chart):
)
def _draw_marker(self, height, x_step, y_step, min_index):
qp = QtGui.QPainter(self)
marker_point = QtCore.QPoint(
qp = QPainter(self)
marker_point = QPoint(
self.leftMargin + int((self.markerLocation - min_index) / x_step),
(self.topMargin + height)
- int(self.tdrWindow.td[self.markerLocation] / y_step),
@ -415,8 +423,8 @@ class TDRChart(Chart):
self._draw_ticks(height, width, x_step, min_index)
self._draw_y_ticks(height, width, min_impedance, max_impedance)
qp = QtGui.QPainter(self)
pen = QtGui.QPen(Chart.color.sweep)
qp = QPainter(self)
pen = QPen(Chart.color.sweep)
pen.setWidth(self.dim.point)
qp.setPen(pen)
@ -443,15 +451,15 @@ class TDRChart(Chart):
if self.markerLocation != -1:
self._draw_marker(height, x_step, y_step, min_index)
def paintEvent(self, _: QtGui.QPaintEvent) -> None:
qp = QtGui.QPainter(self)
qp.setPen(QtGui.QPen(Chart.color.text))
def paintEvent(self, _: QPaintEvent) -> None:
qp = QPainter(self)
qp.setPen(QPen(Chart.color.text))
qp.drawText(3, 15, self.name)
width = self.width() - self.leftMargin - self.rightMargin
height = self.height() - self.bottomMargin - self.topMargin
qp.setPen(QtGui.QPen(Chart.color.foreground))
qp.setPen(QPen(Chart.color.foreground))
qp.drawLine(
self.leftMargin - 5,
self.height() - self.bottomMargin,
@ -471,14 +479,12 @@ class TDRChart(Chart):
self._draw_graph(height, width)
if self.dragbox.state and self.dragbox.pos[0] != -1:
dashed_pen = QtGui.QPen(
Chart.color.foreground, 1, QtCore.Qt.DashLine
)
dashed_pen = QPen(Chart.color.foreground, 1, Qt.DashLine)
qp.setPen(dashed_pen)
qp.drawRect(
QtCore.QRect(
QtCore.QPoint(*self.dragbox.pos_start),
QtCore.QPoint(*self.dragbox.pos),
QRect(
QPoint(*self.dragbox.pos_start),
QPoint(*self.dragbox.pos),
)
)
@ -548,7 +554,7 @@ class TDRChart(Chart):
self.update()
def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
def resizeEvent(self, a0: QResizeEvent) -> None:
super().resizeEvent(a0)
self.dim.width = self.width() - self.leftMargin - self.rightMargin
self.dim.height = self.height() - self.bottomMargin - self.topMargin

Wyświetl plik

@ -101,6 +101,6 @@ class Value:
]
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]

Wyświetl plik

@ -232,11 +232,11 @@ class Marker(QtCore.QObject, Value):
if color.isValid():
self.color = color
p = self.btnColorPicker.palette()
# TODO: p.setColor(QtGui.QPalette.ButtonText, self.color)
p.setColor(QtGui.QPalette.ColorRole.ButtonText, self.color)
self.btnColorPicker.setPalette(p)
# TODO: fix Stylesheet
if self.coloredText:
color_string = QtCore.QVariant(color)
# TODO: color_string.convert(str)
self.group_box.setStyleSheet(
f"QGroupBox {{ color: {color_string.value()}; "
f"font-size: {self._size_str()}}};"
@ -377,7 +377,6 @@ class Marker(QtCore.QObject, Value):
self.label["s21polar"].setText(
f"{str(round(abs(_s21.z), 2))}{format_phase(_s21.phase)}"
)
self.label["s21magshunt"].setText(
format_magnitude(abs(_s21.shuntImpedance()))
)

Wyświetl plik

@ -1,16 +1,7 @@
import sys
if sys.version_info[:2] >= (3, 8):
# TODO: Import directly (no need for conditional) when `python_requires = >= 3.8`
from importlib.metadata import (
PackageNotFoundError,
version,
) # pragma: no cover
else:
from importlib_metadata import (
PackageNotFoundError,
version,
) # pragma: no cover
from importlib.metadata import (
PackageNotFoundError,
version,
)
try:
# Change here if project is renamed and does not equal the package name