From 3d3e31e1765cc26fab9689d419ebda0fa91a660f Mon Sep 17 00:00:00 2001 From: Roel Jordans Date: Fri, 10 Feb 2023 16:30:21 +0100 Subject: [PATCH] Re-organize RI chart to have RIZ specialization - separate impedance plotting specific bits - preparation new chart to plot mu' and mu'' for given core dimensions --- NanoVNASaver/Charts/RI.py | 55 ++--------- NanoVNASaver/Charts/RIZ.py | 98 +++++++++++++++++++ .../Charts/{RISeries.py => RIZSeries.py} | 4 +- .../Charts/{RIShunt.py => RIZShunt.py} | 4 +- NanoVNASaver/Charts/__init__.py | 5 +- NanoVNASaver/NanoVNASaver.py | 8 +- 6 files changed, 115 insertions(+), 59 deletions(-) create mode 100644 NanoVNASaver/Charts/RIZ.py rename NanoVNASaver/Charts/{RISeries.py => RIZSeries.py} (91%) rename NanoVNASaver/Charts/{RIShunt.py => RIZShunt.py} (91%) diff --git a/NanoVNASaver/Charts/RI.py b/NanoVNASaver/Charts/RI.py index 102f51f..fab3bb0 100644 --- a/NanoVNASaver/Charts/RI.py +++ b/NanoVNASaver/Charts/RI.py @@ -72,33 +72,7 @@ class RealImaginaryChart(FrequencyChart): mode_group.addAction(self.y_action_fixed_span) self.y_menu.addAction(self.y_action_automatic) self.y_menu.addAction(self.y_action_fixed_span) - self.y_menu.addSeparator() - self.action_set_fixed_maximum_real = QtWidgets.QAction( - f"Maximum R ({self.maxDisplayReal})") - self.action_set_fixed_maximum_real.triggered.connect( - self.setMaximumRealValue) - - self.action_set_fixed_minimum_real = QtWidgets.QAction( - f"Minimum R ({self.minDisplayReal})") - self.action_set_fixed_minimum_real.triggered.connect( - self.setMinimumRealValue) - - self.action_set_fixed_maximum_imag = QtWidgets.QAction( - f"Maximum jX ({self.maxDisplayImag})") - self.action_set_fixed_maximum_imag.triggered.connect( - self.setMaximumImagValue) - - self.action_set_fixed_minimum_imag = QtWidgets.QAction( - f"Minimum jX ({self.minDisplayImag})") - self.action_set_fixed_minimum_imag.triggered.connect( - self.setMinimumImagValue) - - self.y_menu.addAction(self.action_set_fixed_maximum_real) - self.y_menu.addAction(self.action_set_fixed_minimum_real) - self.y_menu.addSeparator() - self.y_menu.addAction(self.action_set_fixed_maximum_imag) - self.y_menu.addAction(self.action_set_fixed_minimum_imag) def copy(self): new_chart: RealImaginaryChart = super().copy() @@ -109,23 +83,6 @@ class RealImaginaryChart(FrequencyChart): new_chart.minDisplayImag = self.minDisplayImag return new_chart - def drawChart(self, qp: QtGui.QPainter): - qp.setPen(QtGui.QPen(Chart.color.text)) - qp.drawText(self.leftMargin + 5, 15, - f"{self.name} (\N{OHM SIGN})") - 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) - self.drawTitle(qp) - def drawValues(self, qp: QtGui.QPainter): if not self.data and not self.reference: return @@ -333,7 +290,7 @@ class RealImaginaryChart(FrequencyChart): max_real = 0 max_imag = -1000 for d in self.data: - imp = self.impedance(d) + imp = self.value(d) re, im = imp.real, imp.imag if math.isinf(re): # Avoid infinite scales continue @@ -345,7 +302,7 @@ class RealImaginaryChart(FrequencyChart): for d in self.reference: if d.freq < self.fstart or d.freq > self.fstop: continue - imp = self.impedance(d) + imp = self.value(d) re, im = imp.real, imp.imag if math.isinf(re): # Avoid infinite scales continue @@ -393,12 +350,12 @@ class RealImaginaryChart(FrequencyChart): return min_imag, max_imag def getImYPosition(self, d: Datapoint) -> int: - im = self.impedance(d).imag + im = self.value(d).imag 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 + re = self.value(d).real return int(self.topMargin + (self.max_real - re) / self.span_real * self.dim.height if math.isfinite(re) else self.topMargin) @@ -521,5 +478,5 @@ class RealImaginaryChart(FrequencyChart): f"Maximum jX ({self.maxDisplayImag})") self.menu.exec_(event.globalPos()) - def impedance(self, p: Datapoint) -> complex: - return p.impedance() + def value(self, p: Datapoint) -> complex: + raise NotImplementedError() diff --git a/NanoVNASaver/Charts/RIZ.py b/NanoVNASaver/Charts/RIZ.py new file mode 100644 index 0000000..049c5d7 --- /dev/null +++ b/NanoVNASaver/Charts/RIZ.py @@ -0,0 +1,98 @@ +# NanoVNASaver +# +# A python program to view and export Touchstone data from a NanoVNA +# Copyright (C) 2019, 2020 Rune B. Broberg +# Copyright (C) 2020,2021 NanoVNA-Saver Authors +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +import logging + +from PyQt5 import QtWidgets, QtGui + +from NanoVNASaver.Formatting import format_frequency_chart +from NanoVNASaver.RFTools import Datapoint +from NanoVNASaver.Charts.Chart import Chart + +from .RI import RealImaginaryChart + +logger = logging.getLogger(__name__) + +class RealImaginaryZChart(RealImaginaryChart): + def __init__(self, name=""): + super().__init__(name) + self.y_menu.addSeparator() + + self.action_set_fixed_maximum_real = QtWidgets.QAction( + f"Maximum R ({self.maxDisplayReal})") + self.action_set_fixed_maximum_real.triggered.connect( + self.setMaximumRealValue) + + self.action_set_fixed_minimum_real = QtWidgets.QAction( + f"Minimum R ({self.minDisplayReal})") + self.action_set_fixed_minimum_real.triggered.connect( + self.setMinimumRealValue) + + self.action_set_fixed_maximum_imag = QtWidgets.QAction( + f"Maximum jX ({self.maxDisplayImag})") + self.action_set_fixed_maximum_imag.triggered.connect( + self.setMaximumImagValue) + + self.action_set_fixed_minimum_imag = QtWidgets.QAction( + f"Minimum jX ({self.minDisplayImag})") + self.action_set_fixed_minimum_imag.triggered.connect( + self.setMinimumImagValue) + + self.y_menu.addAction(self.action_set_fixed_maximum_real) + self.y_menu.addAction(self.action_set_fixed_minimum_real) + self.y_menu.addSeparator() + self.y_menu.addAction(self.action_set_fixed_maximum_imag) + self.y_menu.addAction(self.action_set_fixed_minimum_imag) + + def drawChart(self, qp: QtGui.QPainter): + qp.setPen(QtGui.QPen(Chart.color.text)) + qp.drawText(self.leftMargin + 5, 15, + f"{self.name} (\N{OHM SIGN})") + 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) + self.drawTitle(qp) + + def contextMenuEvent(self, event): + self.action_set_fixed_start.setText( + f"Start ({format_frequency_chart(self.minFrequency)})") + self.action_set_fixed_stop.setText( + f"Stop ({format_frequency_chart(self.maxFrequency)})") + self.action_set_fixed_minimum_real.setText( + f"Minimum R ({self.minDisplayReal})") + self.action_set_fixed_maximum_real.setText( + f"Maximum R ({self.maxDisplayReal})") + self.action_set_fixed_minimum_imag.setText( + f"Minimum jX ({self.minDisplayImag})") + self.action_set_fixed_maximum_imag.setText( + f"Maximum jX ({self.maxDisplayImag})") + self.menu.exec_(event.globalPos()) + + def value(self, p: Datapoint) -> complex: + return self.impedance(p) + + def impedance(self, p: Datapoint) -> complex: + return p.impedance() diff --git a/NanoVNASaver/Charts/RISeries.py b/NanoVNASaver/Charts/RIZSeries.py similarity index 91% rename from NanoVNASaver/Charts/RISeries.py rename to NanoVNASaver/Charts/RIZSeries.py index 245b937..60f18fc 100644 --- a/NanoVNASaver/Charts/RISeries.py +++ b/NanoVNASaver/Charts/RIZSeries.py @@ -19,12 +19,12 @@ import logging from NanoVNASaver.RFTools import Datapoint -from .RI import RealImaginaryChart +from .RIZ import RealImaginaryZChart logger = logging.getLogger(__name__) -class RealImaginarySeriesChart(RealImaginaryChart): +class RealImaginaryZSeriesChart(RealImaginaryZChart): def impedance(self, p: Datapoint) -> complex: return p.seriesImpedance() diff --git a/NanoVNASaver/Charts/RIShunt.py b/NanoVNASaver/Charts/RIZShunt.py similarity index 91% rename from NanoVNASaver/Charts/RIShunt.py rename to NanoVNASaver/Charts/RIZShunt.py index 2987425..1609282 100644 --- a/NanoVNASaver/Charts/RIShunt.py +++ b/NanoVNASaver/Charts/RIZShunt.py @@ -19,12 +19,12 @@ import logging from NanoVNASaver.RFTools import Datapoint -from .RI import RealImaginaryChart +from .RIZ import RealImaginaryZChart logger = logging.getLogger(__name__) -class RealImaginaryShuntChart(RealImaginaryChart): +class RealImaginaryZShuntChart(RealImaginaryZChart): def impedance(self, p: Datapoint) -> complex: return p.shuntImpedance() diff --git a/NanoVNASaver/Charts/__init__.py b/NanoVNASaver/Charts/__init__.py index d8ebd65..30c5520 100644 --- a/NanoVNASaver/Charts/__init__.py +++ b/NanoVNASaver/Charts/__init__.py @@ -15,8 +15,9 @@ from .Permeability import PermeabilityChart from .Phase import PhaseChart from .QFactor import QualityFactorChart from .RI import RealImaginaryChart -from .RIShunt import RealImaginaryShuntChart -from .RISeries import RealImaginarySeriesChart +from .RIZ import RealImaginaryZChart +from .RIZShunt import RealImaginaryZShuntChart +from .RIZSeries import RealImaginaryZSeriesChart from .Smith import SmithChart from .SParam import SParameterChart from .TDR import TDRChart diff --git a/NanoVNASaver/NanoVNASaver.py b/NanoVNASaver/NanoVNASaver.py index d14a9ea..796e91f 100644 --- a/NanoVNASaver/NanoVNASaver.py +++ b/NanoVNASaver/NanoVNASaver.py @@ -45,7 +45,7 @@ from .Charts import ( MagnitudeChart, MagnitudeZChart, MagnitudeZShuntChart, MagnitudeZSeriesChart, QualityFactorChart, VSWRChart, PermeabilityChart, PolarChart, - RealImaginaryChart, RealImaginaryShuntChart, RealImaginarySeriesChart, + RealImaginaryChart, RealImaginaryZChart, RealImaginaryZShuntChart, RealImaginaryZSeriesChart, SmithChart, SParameterChart, TDRChart, ) from .Calibration import Calibration @@ -151,7 +151,7 @@ class NanoVNASaver(QtWidgets.QWidget): " X/\N{GREEK SMALL LETTER OMEGA}"), "phase": PhaseChart("S11 Phase"), "q_factor": QualityFactorChart("S11 Quality Factor"), - "real_imag": RealImaginaryChart("S11 R+jX"), + "real_imag": RealImaginaryZChart("S11 R+jX"), "smith": SmithChart("S11 Smith Chart"), "s_parameter": SParameterChart("S11 Real/Imaginary"), "vswr": VSWRChart("S11 VSWR"), @@ -163,8 +163,8 @@ class NanoVNASaver(QtWidgets.QWidget): "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( + "real_imag_shunt": RealImaginaryZShuntChart("S21 R+jX shunt"), + "real_imag_series": RealImaginaryZSeriesChart( "S21 R+jX series"), "phase": PhaseChart("S21 Phase"), "polar": PolarChart("S21 Polar Plot"),