First beta of a Quality Factor chart

pull/12/head
Rune B. Broberg 2019-09-10 19:51:21 +02:00
rodzic 35823a6234
commit 9cf710992e
2 zmienionych plików z 199 dodań i 1 usunięć

Wyświetl plik

@ -898,3 +898,190 @@ class LogMagChart(Chart):
# Calculate the reflection coefficient
mag = math.sqrt((re50 - 50) * (re50 - 50) + im50 * im50) / math.sqrt((re50 + 50) * (re50 + 50) + im50 * im50)
return -20 * math.log10(mag)
class QualityFactorChart(Chart):
def __init__(self, name=""):
super().__init__()
self.leftMargin = 35
self.chartWidth = 360
self.chartHeight = 360
self.name = name
self.fstart = 0
self.fstop = 0
self.mouselocation = 0
self.minQ = 0
self.maxQ = 0
self.span = 0
self.setMinimumSize(self.chartWidth + 20 + self.leftMargin, self.chartHeight + 40)
self.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding))
pal = QtGui.QPalette()
pal.setColor(QtGui.QPalette.Background, self.backgroundColor)
self.setPalette(pal)
self.setAutoFillBackground(True)
self.marker1Color = QtGui.QColor(255, 0, 20)
self.marker2Color = QtGui.QColor(20, 0, 255)
def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
self.chartWidth = a0.size().width()-20-self.leftMargin
self.chartHeight = a0.size().height()-40
self.update()
def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
qp = QtGui.QPainter(self)
#qp.begin(self) # Apparently not needed?
self.drawChart(qp)
self.drawValues(qp)
qp.end()
def drawChart(self, qp: QtGui.QPainter):
from NanoVNASaver.NanoVNASaver import NanoVNASaver
qp.setPen(QtGui.QPen(self.textColor))
qp.drawText(3, 15, self.name)
qp.setPen(QtGui.QPen(QtGui.QColor("lightgray")))
qp.drawLine(self.leftMargin, 20, self.leftMargin, 20+self.chartHeight+5)
qp.drawLine(self.leftMargin-5, 20+self.chartHeight, self.leftMargin+self.chartWidth, 20 + self.chartHeight)
minQ = 0 # We always want 0 to be included in the graph
maxQ = 0
# Make up some sensible scaling here
for d in self.data:
Q = NanoVNASaver.qualifyFactor(d)
if Q > maxQ:
maxQ = Q
if Q < minQ:
minQ = Q
if maxQ != 0:
maxQ = min(1000, maxQ) # Don't show Q over 1000
maxScale = math.floor(max(math.log10(maxQ), 1))
else:
maxScale = 1
if minQ != 0:
minQ = max(-1000, minQ) # Nor Q less than -1000
minScale = math.floor(max(math.log10(abs(minQ)), 1))
else:
minScale = 1
self.maxQ = math.ceil(round(maxQ / maxScale) * maxScale)
self.minQ = math.floor(round(minQ / minScale) * minScale)
self.span = maxQ - minQ
step = math.floor(self.span / 8)
if step == 0:
return # No data to draw the graph from
for i in range(self.minQ, self.maxQ, step):
y = 30 + round((maxQ - i) / self.span * (self.chartHeight-10))
if i != minQ:
qp.setPen(QtGui.QPen(self.textColor))
qp.drawText(3, y+3, str(i))
qp.setPen(QtGui.QPen(QtGui.QColor("lightgray")))
qp.drawLine(self.leftMargin-5, y, self.leftMargin+self.chartWidth, y)
#qp.drawLine(self.leftMargin - 5, 30, self.leftMargin + self.chartWidth, 30)
qp.setPen(self.textColor)
#qp.drawText(3, 35, str(maxQ))
#qp.drawText(3, self.chartHeight+20, str(minQ))
def drawValues(self, qp: QtGui.QPainter):
from NanoVNASaver.NanoVNASaver import NanoVNASaver
if len(self.data) == 0 and len(self.reference) == 0:
return
pen = QtGui.QPen(self.sweepColor)
pen.setWidth(2)
line_pen = QtGui.QPen(self.sweepColor)
line_pen.setWidth(1)
highlighter = QtGui.QPen(QtGui.QColor(20, 0, 255))
highlighter.setWidth(1)
if len(self.data) > 0:
fstart = self.data[0].freq
fstop = self.data[len(self.data)-1].freq
else:
fstart = self.reference[0].freq
fstop = self.reference[len(self.reference) - 1].freq
self.fstart = fstart
self.fstop = fstop
fspan = fstop-fstart
qp.drawText(self.leftMargin-20, 20 + self.chartHeight + 15, Chart.shortenFrequency(fstart))
ticks = math.floor(self.chartWidth/100) # Number of ticks does not include the origin
for i in range(ticks):
x = self.leftMargin + round((i+1)*self.chartWidth/ticks)
qp.setPen(QtGui.QPen(QtGui.QColor("lightgray")))
qp.drawLine(x, 20, x, 20+self.chartHeight+5)
qp.setPen(self.textColor)
qp.drawText(x-20, 20+self.chartHeight+15, Chart.shortenFrequency(round(fspan/ticks*(i+1) + fstart)))
if self.mouselocation != 0:
qp.setPen(QtGui.QPen(QtGui.QColor(224,224,224)))
x = self.leftMargin + 1 + round(self.chartWidth * (self.mouselocation - fstart) / fspan)
qp.drawLine(x, 20, x, 20 + self.chartHeight +5)
qp.setPen(pen)
for i in range(len(self.data)):
Q = NanoVNASaver.qualifyFactor(self.data[i])
x = self.leftMargin + 1 + round(self.chartWidth/len(self.data) * i)
y = 30 + round((self.maxQ - Q)/ self.span *(self.chartHeight-10))
qp.drawPoint(int(x), int(y))
if self.drawLines and i > 0:
Q = NanoVNASaver.qualifyFactor(self.data[i-1])
prevx = self.leftMargin + 1 + round(self.chartWidth / len(self.data) * (i-1))
prevy = 30 + round((self.maxQ - Q) / self.span * (self.chartHeight - 10))
qp.setPen(line_pen)
qp.drawLine(x, y, prevx, prevy)
qp.setPen(pen)
pen.setColor(self.referenceColor)
qp.setPen(pen)
for i in range(len(self.reference)):
if self.reference[i].freq < fstart or self.reference[i].freq > fstop:
continue
Q = NanoVNASaver.qualifyFactor(self.reference[i])
x = self.leftMargin + 1 + round(self.chartWidth*(self.reference[i].freq - fstart)/fspan)
y = 30 + round((self.maxQ - Q)/self.span*(self.chartHeight-10))
qp.drawPoint(int(x), int(y))
if self.drawLines and i > 0:
Q = NanoVNASaver.qualifyFactor(self.reference[i-1])
prevx = x = self.leftMargin + 1 + round(self.chartWidth*(self.reference[i-1].freq - fstart)/fspan)
prevy = 30 + round((self.maxQ - Q) / self.span * (self.chartHeight - 10))
qp.setPen(line_pen)
qp.drawLine(x, y, prevx, prevy)
qp.setPen(pen)
# Now draw the markers
for m in self.markers:
if m.location != -1:
highlighter.setColor(m.color)
qp.setPen(highlighter)
Q = NanoVNASaver.qualifyFactor(self.data[m.location])
x = self.leftMargin + 1 + round(self.chartWidth/len(self.data) * m.location)
y = 30 + round((self.maxQ - Q) / self.span * (self.chartHeight - 10))
qp.drawLine(int(x), int(y) + 3, int(x) - 3, int(y) - 3)
qp.drawLine(int(x), int(y) + 3, int(x) + 3, int(y) - 3)
qp.drawLine(int(x) - 3, int(y) - 3, int(x) + 3, int(y) - 3)
#qp.drawPoint(int(x), int(y))
def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None:
self.mouseMoveEvent(a0)
def mouseMoveEvent(self, a0: QtGui.QMouseEvent) -> None:
x = a0.x()
absx = x - self.leftMargin
if absx < 0 or absx > self.chartWidth:
self.mouselocation = 0
a0.ignore()
return
a0.accept()
if self.fstop - self.fstart > 0:
span = self.fstop - self.fstart
step = span/self.chartWidth
f = self.fstart + absx * step
# self.mouselocation = f
self.markers[0].setFrequency(str(round(f)))
self.markers[0].frequencyInput.setText(str(round(f)))
else:
self.mouselocation = 0
return
@staticmethod
def angle(d: Datapoint) -> float:
re = d.re
im = d.im
return -math.degrees(math.atan2(im, re))

Wyświetl plik

@ -24,7 +24,7 @@ import serial
from PyQt5 import QtWidgets, QtCore, QtGui
from serial.tools import list_ports
from .Chart import Chart, PhaseChart, VSWRChart, PolarChart, SmithChart, LogMagChart
from .Chart import Chart, PhaseChart, VSWRChart, PolarChart, SmithChart, LogMagChart, QualityFactorChart
from .Calibration import CalibrationWindow, Calibration
from .Marker import Marker
from .SweepWorker import SweepWorker
@ -97,12 +97,14 @@ class NanoVNASaver(QtWidgets.QWidget):
self.s11Phase = PhaseChart("S11 Phase")
self.s21Phase = PhaseChart("S21 Phase")
self.s11VSWR = VSWRChart("S11 VSWR")
self.s11QualityFactor = QualityFactorChart("S11 Quality Factor")
self.s11charts: List[Chart] = []
self.s11charts.append(self.s11SmithChart)
self.s11charts.append(self.s11LogMag)
self.s11charts.append(self.s11Phase)
self.s11charts.append(self.s11VSWR)
self.s11charts.append(self.s11QualityFactor)
self.s21charts: List[Chart] = []
self.s21charts.append(self.s21PolarChart)
@ -757,6 +759,15 @@ class NanoVNASaver(QtWidgets.QWidget):
vswr = (1 + mag) / (1 - mag)
return im50, re50, vswr
@staticmethod
def qualifyFactor(data: Datapoint):
im50, re50, _ = NanoVNASaver.vswr(data)
if re50 != 0:
Q = im50 / re50
else:
Q = 0
return Q
@staticmethod
def reactanceEquivalent(im50, freq) -> str:
capacitance = 10**12/(freq * 2 * math.pi * im50)