kopia lustrzana https://github.com/NanoVNA-Saver/nanovna-saver
Use more integer devisions
Using more integer divisions to get right type for QPainter pointspull/543/head
rodzic
06ffd48de0
commit
7690f39c19
|
@ -36,7 +36,6 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class FrequencyChart(Chart):
|
||||
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__(name)
|
||||
self.maxFrequency = 100000000
|
||||
|
@ -335,7 +334,7 @@ class FrequencyChart(Chart):
|
|||
return (
|
||||
self.topMargin +
|
||||
round((self.maxValue - self.value_function(d) /
|
||||
self.span * self.dim.height)))
|
||||
self.span * self.dim.height)))
|
||||
except ValueError:
|
||||
return self.topMargin
|
||||
|
||||
|
@ -455,13 +454,13 @@ class FrequencyChart(Chart):
|
|||
|
||||
def _check_frequency_boundaries(self, qp: QtGui.QPainter):
|
||||
if (self.data and self._data_oob(self.data) and
|
||||
(not self.reference or self._data_oob(self.reference))):
|
||||
(not self.reference or self._data_oob(self.reference))):
|
||||
# Data outside frequency range
|
||||
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 + self.dim.width // 2 - 70,
|
||||
self.topMargin + self.dim.height // 2 - 20,
|
||||
"Data outside frequency span")
|
||||
|
||||
def drawDragbog(self, qp: QtGui.QPainter):
|
||||
|
|
|
@ -156,32 +156,23 @@ class RealImaginaryChart(FrequencyChart):
|
|||
for d in self.data:
|
||||
imp = self.impedance(d)
|
||||
re, im = imp.real, imp.imag
|
||||
if math.isinf(re): # Avoid infinite scales
|
||||
if math.isinf(re): # Avoid infinite scales
|
||||
continue
|
||||
if re > max_real:
|
||||
max_real = re
|
||||
if re < min_real:
|
||||
min_real = re
|
||||
if im > max_imag:
|
||||
max_imag = im
|
||||
if im < min_imag:
|
||||
min_imag = im
|
||||
max_real = max(max_real, re)
|
||||
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
|
||||
if d.freq < self.fstart or d.freq > self.fstop:
|
||||
continue
|
||||
imp = self.impedance(d)
|
||||
re, im = imp.real, imp.imag
|
||||
if math.isinf(re): # Avoid infinite scales
|
||||
if math.isinf(re): # Avoid infinite scales
|
||||
continue
|
||||
if re > max_real:
|
||||
max_real = re
|
||||
if re < min_real:
|
||||
min_real = re
|
||||
if im > max_imag:
|
||||
max_imag = im
|
||||
if im < min_imag:
|
||||
min_imag = im
|
||||
|
||||
max_real = max(max_real, re)
|
||||
min_real = min(min_real, re)
|
||||
max_imag = max(max_imag, im)
|
||||
min_imag = min(min_imag, im)
|
||||
# Always have at least 8 numbered horizontal lines
|
||||
max_real = math.ceil(max_real)
|
||||
min_real = math.floor(min_real)
|
||||
|
@ -190,8 +181,8 @@ class RealImaginaryChart(FrequencyChart):
|
|||
|
||||
if max_imag - min_imag < 8:
|
||||
missing = 8 - (max_imag - min_imag)
|
||||
max_imag += math.ceil(missing/2)
|
||||
min_imag -= math.floor(missing/2)
|
||||
max_imag += math.ceil(missing / 2)
|
||||
min_imag -= math.floor(missing / 2)
|
||||
|
||||
if 0 > max_imag > -2:
|
||||
max_imag = 0
|
||||
|
@ -217,31 +208,29 @@ class RealImaginaryChart(FrequencyChart):
|
|||
self.max_real = max_real
|
||||
self.max_imag = max_imag
|
||||
|
||||
span_real = max_real - min_real
|
||||
if span_real == 0:
|
||||
span_real = 0.01
|
||||
self.span_real = span_real
|
||||
|
||||
span_imag = max_imag - min_imag
|
||||
if span_imag == 0:
|
||||
span_imag = 0.01
|
||||
self.span_imag = span_imag
|
||||
self.span_real = (max_real - min_real) or 0.01
|
||||
self.span_imag = (max_imag - min_imag) or 0.01
|
||||
|
||||
# We want one horizontal tick per 50 pixels, at most
|
||||
horizontal_ticks = math.floor(self.dim.height/50)
|
||||
horizontal_ticks = self.dim.height // 50
|
||||
|
||||
fmt = Format(max_nr_digits=3)
|
||||
for i in range(horizontal_ticks):
|
||||
y = self.topMargin + round(i * self.dim.height / horizontal_ticks)
|
||||
y = self.topMargin + i * self.dim.height // horizontal_ticks
|
||||
qp.setPen(QtGui.QPen(Chart.color.foreground))
|
||||
qp.drawLine(self.leftMargin - 5, y, self.leftMargin + self.dim.width + 5, y)
|
||||
qp.drawLine(self.leftMargin - 5, y,
|
||||
self.leftMargin + self.dim.width + 5, y)
|
||||
qp.setPen(QtGui.QPen(Chart.color.text))
|
||||
re = max_real - i * span_real / horizontal_ticks
|
||||
im = max_imag - i * span_imag / horizontal_ticks
|
||||
qp.drawText(3, y + 4, str(Value(re, fmt=fmt)))
|
||||
qp.drawText(self.leftMargin + self.dim.width + 8, y + 4, str(Value(im, fmt=fmt)))
|
||||
re = max_real - i * self.span_real / horizontal_ticks
|
||||
im = max_imag - i * self.span_imag / horizontal_ticks
|
||||
qp.drawText(3, y + 4, f"{Value(re, fmt=fmt)}")
|
||||
qp.drawText(
|
||||
self.leftMargin + self.dim.width + 8,
|
||||
y + 4,
|
||||
f"{Value(im, fmt=fmt)}")
|
||||
|
||||
qp.drawText(3, self.dim.height + self.topMargin, str(Value(min_real, fmt=fmt)))
|
||||
qp.drawText(3, self.dim.height + self.topMargin,
|
||||
str(Value(min_real, fmt=fmt)))
|
||||
qp.drawText(self.leftMargin + self.dim.width + 8,
|
||||
self.dim.height + self.topMargin,
|
||||
str(Value(min_imag, fmt=fmt)))
|
||||
|
@ -379,18 +368,20 @@ class RealImaginaryChart(FrequencyChart):
|
|||
|
||||
def getImYPosition(self, d: Datapoint) -> int:
|
||||
im = self.impedance(d).imag
|
||||
return self.topMargin + round((self.max_imag - im) / self.span_imag * self.dim.height)
|
||||
return (self.topMargin + int(self.max_imag - im) // self.span_imag
|
||||
* self.dim.height)
|
||||
|
||||
def getReYPosition(self, d: Datapoint) -> int:
|
||||
re = self.impedance(d).real
|
||||
if math.isfinite(re):
|
||||
return self.topMargin + round((self.max_real - re) / self.span_real * self.dim.height)
|
||||
return self.topMargin
|
||||
return (self.topMargin + int(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
|
||||
valRe = -1 * ((absy / self.dim.height * self.span_real) - self.max_real)
|
||||
valIm = -1 * ((absy / self.dim.height * self.span_imag) - self.max_imag)
|
||||
valRe = -1 * ((absy / self.dim.height *
|
||||
self.span_real) - self.max_real)
|
||||
valIm = -1 * ((absy / self.dim.height *
|
||||
self.span_imag) - self.max_imag)
|
||||
return [valRe, valIm]
|
||||
|
||||
def zoomTo(self, x1, y1, x2, y2):
|
||||
|
|
|
@ -49,96 +49,71 @@ class SParameterChart(FrequencyChart):
|
|||
|
||||
def drawChart(self, qp: QtGui.QPainter):
|
||||
qp.setPen(QtGui.QPen(Chart.color.text))
|
||||
qp.drawText(int(round(self.dim.width / 2)) - 20, 15, self.name + "")
|
||||
qp.drawText(self.dim.width // 2 - 20, 15, f"{self.name}")
|
||||
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)
|
||||
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:
|
||||
return
|
||||
|
||||
self._set_start_stop()
|
||||
|
||||
# Draw bands if required
|
||||
if self.bands.enabled:
|
||||
self.drawBands(qp, self.fstart, self.fstop)
|
||||
|
||||
if self.fixedValues:
|
||||
maxValue = self.maxDisplayValue
|
||||
minValue = self.minDisplayValue
|
||||
self.maxValue = maxValue
|
||||
self.minValue = minValue
|
||||
else:
|
||||
# Find scaling
|
||||
minValue = -1
|
||||
maxValue = 1
|
||||
self.maxValue = maxValue
|
||||
self.minValue = minValue
|
||||
# for d in self.data:
|
||||
# val = d.re
|
||||
# if val > maxValue:
|
||||
# maxValue = val
|
||||
# if val < minValue:
|
||||
# minValue = val
|
||||
# for d in self.reference: # Also check min/max for the reference sweep
|
||||
# if d.freq < self.fstart or d.freq > self.fstop:
|
||||
# continue
|
||||
# logmag = self.logMag(d)
|
||||
# if logmag > maxValue:
|
||||
# maxValue = logmag
|
||||
# if logmag < minValue:
|
||||
# minValue = logmag
|
||||
|
||||
# minValue = 10*math.floor(minValue/10)
|
||||
# self.minValue = minValue
|
||||
# maxValue = 10*math.ceil(maxValue/10)
|
||||
# self.maxValue = maxValue
|
||||
|
||||
span = maxValue-minValue
|
||||
self.minValue = minValue
|
||||
self.maxValue = maxValue
|
||||
span = maxValue - minValue
|
||||
if span == 0:
|
||||
span = 0.01
|
||||
self.span = span
|
||||
|
||||
tick_count = math.floor(self.dim.height / 60)
|
||||
tick_count = self.dim.height // 60
|
||||
tick_step = self.span / tick_count
|
||||
|
||||
for i in range(tick_count):
|
||||
val = minValue + i * tick_step
|
||||
y = self.topMargin + round((maxValue - val)/span*self.dim.height)
|
||||
y = self.topMargin + (maxValue - val) // span * self.dim.height
|
||||
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)
|
||||
if val > minValue and val != maxValue:
|
||||
qp.setPen(QtGui.QPen(Chart.color.text))
|
||||
qp.drawText(3, y + 4, str(round(val, 2)))
|
||||
|
||||
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))
|
||||
self.drawFrequencyTicks(qp)
|
||||
|
||||
qp.setPen(Chart.color.text)
|
||||
qp.drawText(3, self.topMargin + 4, f"{maxValue}")
|
||||
qp.drawText(3, self.dim.height + self.topMargin, f"{minValue}")
|
||||
self.drawFrequencyTicks(qp)
|
||||
self.drawData(qp, self.data, Chart.color.sweep, self.getReYPosition)
|
||||
self.drawData(qp, self.reference, Chart.color.reference, self.getReYPosition)
|
||||
self.drawData(qp, self.data, Chart.color.sweep_secondary, self.getImYPosition)
|
||||
self.drawData(qp, self.reference, Chart.color.reference_secondary, self.getImYPosition)
|
||||
self.drawData(qp, self.reference, Chart.color.reference,
|
||||
self.getReYPosition)
|
||||
self.drawData(qp, self.data, Chart.color.sweep_secondary,
|
||||
self.getImYPosition)
|
||||
self.drawData(qp, self.reference,
|
||||
Chart.color.reference_secondary, self.getImYPosition)
|
||||
|
||||
self.drawMarkers(qp, y_function=self.getReYPosition)
|
||||
self.drawMarkers(qp, y_function=self.getImYPosition)
|
||||
|
||||
def getYPosition(self, d: Datapoint) -> int:
|
||||
return self.topMargin + round((self.maxValue - d.re) / self.span * self.dim.height)
|
||||
return self.topMargin + (self.maxValue - d.re) // self.span * self.dim.height
|
||||
|
||||
def getReYPosition(self, d: Datapoint) -> int:
|
||||
return self.topMargin + round((self.maxValue - d.re) / self.span * self.dim.height)
|
||||
return self.topMargin + (self.maxValue - d.re) // self.span * self.dim.height
|
||||
|
||||
def getImYPosition(self, d: Datapoint) -> int:
|
||||
return self.topMargin + round((self.maxValue - d.im) / self.span * self.dim.height)
|
||||
return self.topMargin + (self.maxValue - d.im) // self.span * self.dim.height
|
||||
|
||||
def valueAtPosition(self, y) -> List[float]:
|
||||
absy = y - self.topMargin
|
||||
|
@ -146,9 +121,7 @@ class SParameterChart(FrequencyChart):
|
|||
return [val]
|
||||
|
||||
def logMag(self, p: Datapoint) -> float:
|
||||
if self.isInverted:
|
||||
return -p.gain
|
||||
return p.gain
|
||||
return -p.gain if self.isInverted else p.gain
|
||||
|
||||
def copy(self):
|
||||
new_chart: LogMagChart = super().copy()
|
||||
|
|
|
@ -27,59 +27,65 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class SmithChart(SquareChart):
|
||||
def drawChart(self, qp: QtGui.QPainter) -> None:
|
||||
centerX = int(self.width()/2)
|
||||
centerY = int(self.height()/2)
|
||||
center_x = self.width() // 2
|
||||
center_y = self.height() // 2
|
||||
width_2 = self.dim.width // 2
|
||||
height_2 = self.dim.height // 2
|
||||
qp.setPen(QtGui.QPen(Chart.color.text))
|
||||
qp.drawText(3, 15, self.name)
|
||||
qp.setPen(QtGui.QPen(Chart.color.foreground))
|
||||
qp.drawEllipse(QtCore.QPoint(centerX, centerY),
|
||||
int(self.dim.width / 2),
|
||||
int(self.dim.height / 2))
|
||||
qp.drawLine(
|
||||
centerX - int(self.dim.width / 2),
|
||||
centerY,
|
||||
centerX + int(self.dim.width / 2),
|
||||
centerY)
|
||||
qp.drawEllipse(QtCore.QPoint(center_x, center_y), width_2, height_2)
|
||||
qp.drawLine(center_x - width_2, center_y,
|
||||
center_x + width_2, center_y)
|
||||
|
||||
qp.drawEllipse(QtCore.QPoint(centerX + int(self.dim.width/4), centerY),
|
||||
int(self.dim.width/4), int(self.dim.height/4)) # Re(Z) = 1
|
||||
qp.drawEllipse(QtCore.QPoint(centerX + int(2/3*self.dim.width/2), centerY),
|
||||
int(self.dim.width/6), int(self.dim.height/6)) # Re(Z) = 2
|
||||
qp.drawEllipse(QtCore.QPoint(centerX + int(3 / 4 * self.dim.width / 2), centerY),
|
||||
int(self.dim.width / 8), int(self.dim.height / 8)) # Re(Z) = 3
|
||||
qp.drawEllipse(QtCore.QPoint(centerX + int(5 / 6 * self.dim.width / 2), centerY),
|
||||
int(self.dim.width / 12), int(self.dim.height / 12)) # Re(Z) = 5
|
||||
qp.drawEllipse(
|
||||
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),
|
||||
self.dim.width // 6, self.dim.height // 6) # Re(Z) = 2
|
||||
qp.drawEllipse(
|
||||
QtCore.QPoint(center_x + 3 * self.dim.width // 8, center_y),
|
||||
self.dim.width // 8, self.dim.height // 8) # Re(Z) = 3
|
||||
qp.drawEllipse(
|
||||
QtCore.QPoint(center_x + 5 * self.dim.width // 12, center_y),
|
||||
self.dim.width // 12, self.dim.height // 12) # Re(Z) = 5
|
||||
qp.drawEllipse(
|
||||
QtCore.QPoint(center_x + self.dim.width // 6, center_y),
|
||||
self.dim.width // 3, self.dim.height // 3) # Re(Z) = 0.5
|
||||
qp.drawEllipse(
|
||||
QtCore.QPoint(center_x + self.dim.width // 12, center_y),
|
||||
5 * self.dim.width // 12, 5 * self.dim.height // 12) # Re(Z) = 0.2
|
||||
|
||||
qp.drawEllipse(QtCore.QPoint(centerX + int(1 / 3 * self.dim.width / 2), centerY),
|
||||
int(self.dim.width / 3), int(self.dim.height / 3)) # Re(Z) = 0.5
|
||||
qp.drawEllipse(QtCore.QPoint(centerX + int(1 / 6 * self.dim.width / 2), centerY),
|
||||
int(self.dim.width / 2.4), int(self.dim.height / 2.4)) # Re(Z) = 0.2
|
||||
|
||||
qp.drawArc(centerX + int(3/8*self.dim.width), centerY, int(self.dim.width/4),
|
||||
int(self.dim.width/4), 90*16, 152*16) # Im(Z) = -5
|
||||
qp.drawArc(centerX + int(3/8*self.dim.width), centerY, int(self.dim.width/4),
|
||||
-int(self.dim.width/4), -90 * 16, -152 * 16) # Im(Z) = 5
|
||||
qp.drawArc(centerX + int(self.dim.width/4), centerY, int(self.dim.width/2),
|
||||
int(self.dim.height/2), 90*16, 127*16) # Im(Z) = -2
|
||||
qp.drawArc(centerX + int(self.dim.width/4), centerY, int(self.dim.width/2),
|
||||
-int(self.dim.height/2), -90*16, -127*16) # Im(Z) = 2
|
||||
qp.drawArc(centerX, centerY,
|
||||
qp.drawArc(center_x + 3 * self.dim.width // 8, center_y,
|
||||
self.dim.width // 4, self.dim.width // 4,
|
||||
90 * 16, 152 * 16) # Im(Z) = -5
|
||||
qp.drawArc(center_x + 3 * self.dim.width // 8, center_y,
|
||||
self.dim.width // 4, -self.dim.width // 4,
|
||||
-90 * 16, -152 * 16) # Im(Z) = 5
|
||||
qp.drawArc(center_x + self.dim.width // 4, center_y,
|
||||
width_2, height_2,
|
||||
90 * 16, 127 * 16) # Im(Z) = -2
|
||||
qp.drawArc(center_x + self.dim.width // 4, center_y,
|
||||
width_2, -height_2,
|
||||
-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
|
||||
qp.drawArc(centerX, centerY,
|
||||
self.dim.width, -self.dim.height,
|
||||
qp.drawArc(center_x, center_y,
|
||||
self.dim.width, - self.dim.height,
|
||||
-90 * 16, -90 * 16) # Im(Z) = 1
|
||||
qp.drawArc(centerX - int(self.dim.width / 2), centerY,
|
||||
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
|
||||
qp.drawArc(centerX - int(self.dim.width / 2), centerY,
|
||||
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
|
||||
qp.drawArc(centerX - self.dim.width * 2, centerY,
|
||||
qp.drawArc(center_x - self.dim.width * 2, center_y,
|
||||
self.dim.width * 5, self.dim.height * 5,
|
||||
int(93.85 * 16), int(18.85 * 16)) # Im(Z) = -0.2
|
||||
qp.drawArc(centerX - self.dim.width*2, centerY,
|
||||
self.dim.width*5, -self.dim.height*5,
|
||||
qp.drawArc(center_x - self.dim.width * 2, center_y,
|
||||
self.dim.width * 5, -self.dim.height * 5,
|
||||
int(-93.85 * 16), int(-18.85 * 16)) # Im(Z) = 0.2
|
||||
|
||||
self.drawTitle(qp)
|
||||
|
@ -89,8 +95,8 @@ class SmithChart(SquareChart):
|
|||
if swr <= 1:
|
||||
continue
|
||||
gamma = (swr - 1)/(swr + 1)
|
||||
r = round(gamma * self.dim.width/2)
|
||||
qp.drawEllipse(QtCore.QPoint(centerX, centerY), r, r)
|
||||
r = gamma * self.dim.width // 2
|
||||
qp.drawEllipse(QtCore.QPoint(center_x, center_y), r, r)
|
||||
qp.drawText(
|
||||
QtCore.QRect(centerX - 50, centerY - 4 + r, 100, 20),
|
||||
QtCore.Qt.AlignCenter, str(swr))
|
||||
QtCore.QRect(center_x - 50, center_y - 4 + r, 100, 20),
|
||||
QtCore.Qt.AlignCenter, f"{swr}")
|
||||
|
|
|
@ -291,7 +291,7 @@ class TDRChart(Chart):
|
|||
self.leftMargin,
|
||||
self.height() - self.bottomMargin + 5)
|
||||
# Number of ticks does not include the origin
|
||||
ticks = math.floor((self.width() - self.leftMargin) / 100)
|
||||
ticks = (self.width() - self.leftMargin) // 100
|
||||
self.drawTitle(qp)
|
||||
|
||||
if self.tdrWindow.td.size:
|
||||
|
|
Ładowanie…
Reference in New Issue