kopia lustrzana https://github.com/NanoVNA-Saver/nanovna-saver
Enhanced formatting for complex and low digit count
rodzic
60d58015c4
commit
88a37c316b
|
@ -4096,7 +4096,7 @@ class CapacitanceChart(FrequencyChart):
|
|||
self.span = span
|
||||
|
||||
target_ticks = math.floor(self.chartHeight / 60)
|
||||
fmt = Format(max_nr_digits=3)
|
||||
fmt = Format(max_nr_digits=1)
|
||||
for i in range(target_ticks):
|
||||
val = minValue + (i / target_ticks) * span
|
||||
y = self.topMargin + round((self.maxValue - val) / self.span * self.chartHeight)
|
||||
|
@ -4223,7 +4223,7 @@ class InductanceChart(FrequencyChart):
|
|||
self.span = span
|
||||
|
||||
target_ticks = math.floor(self.chartHeight / 60)
|
||||
fmt = Format(max_nr_digits=3)
|
||||
fmt = Format(max_nr_digits=1)
|
||||
for i in range(target_ticks):
|
||||
val = minValue + (i / target_ticks) * span
|
||||
y = self.topMargin + round((self.maxValue - val) / self.span * self.chartHeight)
|
||||
|
|
|
@ -23,6 +23,8 @@ FMT_FREQ_INPUTS = SITools.Format(max_nr_digits=10, allow_strip=True, printable_m
|
|||
FMT_Q_FACTOR = SITools.Format(max_nr_digits=4, assume_infinity=False, min_offset=0, max_offset=0, allow_strip=True)
|
||||
FMT_GROUP_DELAY = SITools.Format(max_nr_digits=5, space_str=" ")
|
||||
FMT_REACT = SITools.Format(max_nr_digits=5, space_str=" ", allow_strip=True)
|
||||
FMT_COMPLEX = SITools.Format(max_nr_digits=3, allow_strip=True,
|
||||
printable_min=0, unprintable_under="- ")
|
||||
|
||||
|
||||
def format_frequency(freq: float, fmt=FMT_FREQ) -> str:
|
||||
|
@ -68,7 +70,7 @@ def format_inductance(val: float, allow_negative: bool = True) -> str:
|
|||
|
||||
|
||||
def format_group_delay(val: float) -> str:
|
||||
return str(SITools.Value(val, "s", fmt=FMT_GROUP_DELAY))
|
||||
return str(SITools.Value(val, "s", FMT_GROUP_DELAY))
|
||||
|
||||
|
||||
def format_phase(val: float) -> str:
|
||||
|
@ -76,21 +78,6 @@ def format_phase(val: float) -> str:
|
|||
|
||||
|
||||
def format_complex_imp(z: complex) -> str:
|
||||
if z.real > 0:
|
||||
if z.real >= 1000:
|
||||
s = f"{z.real/1000:.3g}k"
|
||||
else:
|
||||
s = f"{z.real:.4g}"
|
||||
else:
|
||||
s = "- "
|
||||
if z.imag < 0:
|
||||
s += " -j"
|
||||
else:
|
||||
s += " +j"
|
||||
if abs(z.imag) >= 1000:
|
||||
s += f"{abs(z.imag)/1000:.3g}k"
|
||||
elif abs(z.imag) < 0.1:
|
||||
s += f"{abs(z.imag)*1000:.3g}m"
|
||||
else:
|
||||
s += f"{abs(z.imag):.3g}"
|
||||
return s + " \N{OHM SIGN}"
|
||||
re = SITools.Value(z.real, fmt=FMT_COMPLEX)
|
||||
im = SITools.Value(abs(z.imag), fmt=FMT_COMPLEX)
|
||||
return f"{re}{'-' if z.imag < 0 else '+'}j{im} \N{OHM SIGN}"
|
||||
|
|
|
@ -38,20 +38,15 @@ def parallel_to_serial(z: complex) -> complex:
|
|||
def serial_to_parallel(z: complex) -> complex:
|
||||
"""Convert serial impedance to parallel impedance equivalent"""
|
||||
z_sq_sum = z.real ** 2 + z.imag ** 2
|
||||
if z.real != 0 and z.imag != 0:
|
||||
return complex(z_sq_sum / z.real, z_sq_sum / z.imag)
|
||||
elif z.real != 0 and z_sq_sum > 0:
|
||||
return complex(z_sq_sum / z.real, math.inf)
|
||||
elif z.real != 0 and z_sq_sum < 0:
|
||||
return complex(z_sq_sum / z.real, -math.inf)
|
||||
elif z.imag != 0 and z_sq_sum > 0:
|
||||
return complex(math.inf, z_sq_sum / z.real)
|
||||
elif z.imag != 0 and z_sq_sum < 0:
|
||||
return complex(-math.inf, z_sq_sum / z.real)
|
||||
elif z_sq_sum == 0:
|
||||
return complex(0, 0)
|
||||
else:
|
||||
if z.real == 0 and z.imag == 0:
|
||||
return complex(math.inf, math.inf)
|
||||
if z_sq_sum == 0:
|
||||
return complex(0, 0)
|
||||
if z.imag == 0:
|
||||
return complex(z_sq_sum / z.real, math.copysign(math.inf, z_sq_sum))
|
||||
if z.real == 0:
|
||||
return complex(math.copysign(math.inf,z_sq_sum), z_sq_sum / z.real)
|
||||
return complex(z_sq_sum / z.real, z_sq_sum / z.imag)
|
||||
|
||||
|
||||
def impedance_to_capacitance(z: complex, freq: float) -> float:
|
||||
|
|
|
@ -59,7 +59,7 @@ class Value:
|
|||
value: Union[Number, str] = 0,
|
||||
unit: str = "",
|
||||
fmt=Format()):
|
||||
assert 3 <= fmt.max_nr_digits <= 30
|
||||
assert 1 <= fmt.max_nr_digits <= 30
|
||||
assert -8 <= fmt.min_offset <= fmt.max_offset <= 8
|
||||
assert fmt.parse_clamp_min < fmt.parse_clamp_max
|
||||
assert fmt.printable_min < fmt.printable_max
|
||||
|
@ -91,7 +91,7 @@ class Value:
|
|||
|
||||
real = float(self._value) / (10 ** (offset * 3))
|
||||
|
||||
if fmt.max_nr_digits < 4:
|
||||
if fmt.max_nr_digits < 3:
|
||||
formstr = ".0f"
|
||||
else:
|
||||
max_digits = fmt.max_nr_digits + (
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
# NanoVNASaver
|
||||
# A python program to view and export Touchstone data from a NanoVNA
|
||||
# Copyright (C) 2019. Rune B. Broberg
|
||||
#
|
||||
# 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 <https://www.gnu.org/licenses/>.
|
||||
import unittest
|
||||
|
||||
# Import targets to be tested
|
||||
from NanoVNASaver import Formatting as fmt
|
||||
|
||||
|
||||
class TestCases(unittest.TestCase):
|
||||
|
||||
def test_format_frequency(self):
|
||||
self.assertEqual(fmt.format_frequency(1), '1.00000 Hz')
|
||||
self.assertEqual(fmt.format_frequency(12), '12.0000 Hz')
|
||||
self.assertEqual(fmt.format_frequency(123), '123.000 Hz')
|
||||
self.assertEqual(fmt.format_frequency(1234), '1.23400 kHz')
|
||||
self.assertEqual(fmt.format_frequency(1234567), '1.23457 MHz')
|
||||
self.assertEqual(fmt.format_frequency(1234567890), '1.23457 GHz')
|
||||
self.assertEqual(fmt.format_frequency(0), '0.00000 Hz')
|
||||
self.assertEqual(fmt.format_frequency(-1), '-1.00000 Hz')
|
||||
|
||||
def test_format_frequency_inputs(self):
|
||||
self.assertEqual(fmt.format_frequency_inputs(1), '1Hz')
|
||||
self.assertEqual(fmt.format_frequency_inputs(12), '12Hz')
|
||||
self.assertEqual(fmt.format_frequency_inputs(123), '123Hz')
|
||||
self.assertEqual(fmt.format_frequency_inputs(1234), '1.234kHz')
|
||||
self.assertEqual(fmt.format_frequency_inputs(1234567), '1.234567MHz')
|
||||
self.assertEqual(fmt.format_frequency_inputs(1234567890), '1.23456789GHz')
|
||||
self.assertEqual(fmt.format_frequency_inputs(0), '0Hz')
|
||||
self.assertEqual(fmt.format_frequency_inputs(-1), '- Hz')
|
||||
|
||||
def test_format_gain(self):
|
||||
self.assertEqual(fmt.format_gain(1), '1.000 dB')
|
||||
self.assertEqual(fmt.format_gain(12), '12.000 dB')
|
||||
self.assertEqual(fmt.format_gain(1.23456), '1.235 dB')
|
||||
self.assertEqual(fmt.format_gain(-1), '-1.000 dB')
|
||||
self.assertEqual(fmt.format_gain(-1, invert=True), '1.000 dB')
|
||||
|
||||
def test_format_q_factor(self):
|
||||
self.assertEqual(fmt.format_q_factor(1), '1')
|
||||
self.assertEqual(fmt.format_q_factor(12), '12')
|
||||
self.assertEqual(fmt.format_q_factor(123), '123')
|
||||
self.assertEqual(fmt.format_q_factor(1234), '1234')
|
||||
self.assertEqual(fmt.format_q_factor(12345), '\N{INFINITY}')
|
||||
self.assertEqual(fmt.format_q_factor(-1), '\N{INFINITY}')
|
||||
self.assertEqual(fmt.format_q_factor(1.2345), '1.234')
|
||||
|
||||
def test_format_vswr(self):
|
||||
self.assertEqual(fmt.format_vswr(1), '1.000')
|
||||
self.assertEqual(fmt.format_vswr(1.234), '1.234')
|
||||
self.assertEqual(fmt.format_vswr(12345.12345), '12345.123')
|
||||
|
||||
def test_format_resistance(self):
|
||||
self.assertEqual(fmt.format_resistance(1), '1 \N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_resistance(12), '12 \N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_resistance(123), '123 \N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_resistance(1234), '1.234 k\N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_resistance(12345), '12.345 k\N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_resistance(123456), '123.46 k\N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_resistance(-1), '- \N{OHM SIGN}')
|
||||
|
||||
def test_format_capacitance(self):
|
||||
self.assertEqual(fmt.format_capacitance(1), '1 F')
|
||||
self.assertEqual(fmt.format_capacitance(1e-3), '1 mF')
|
||||
self.assertEqual(fmt.format_capacitance(1e-6), '1 µF')
|
||||
self.assertEqual(fmt.format_capacitance(1e-9), '1 nF')
|
||||
self.assertEqual(fmt.format_capacitance(1e-12), '1 pF')
|
||||
self.assertEqual(fmt.format_capacitance(-1), '-1 F')
|
||||
self.assertEqual(fmt.format_capacitance(-1, False), '- pF')
|
||||
|
||||
def test_format_inductance(self):
|
||||
self.assertEqual(fmt.format_inductance(1), '1 H')
|
||||
self.assertEqual(fmt.format_inductance(1e-3), '1 mH')
|
||||
self.assertEqual(fmt.format_inductance(1e-6), '1 µH')
|
||||
self.assertEqual(fmt.format_inductance(1e-9), '1 nH')
|
||||
self.assertEqual(fmt.format_inductance(1e-12), '1 pH')
|
||||
self.assertEqual(fmt.format_inductance(-1), '-1 H')
|
||||
self.assertEqual(fmt.format_inductance(-1, False), '- nH')
|
||||
|
||||
def test_format_group_delay(self):
|
||||
self.assertEqual(fmt.format_group_delay(1), '1.0000 s')
|
||||
self.assertEqual(fmt.format_group_delay(1e-9), '1.0000 ns')
|
||||
self.assertEqual(fmt.format_group_delay(1.23456e-9), '1.2346 ns')
|
||||
|
||||
def test_format_phase(self):
|
||||
self.assertEqual(fmt.format_phase(0), '0.00°')
|
||||
self.assertEqual(fmt.format_phase(1), '57.30°')
|
||||
self.assertEqual(fmt.format_phase(-1), '-57.30°')
|
||||
self.assertEqual(fmt.format_phase(3.1416), '180.00°')
|
||||
self.assertEqual(fmt.format_phase(6.2831), '360.00°')
|
||||
self.assertEqual(fmt.format_phase(9.4247), '540.00°')
|
||||
self.assertEqual(fmt.format_phase(-3.1416), '-180.00°')
|
||||
|
||||
def test_format_complex_imp(self):
|
||||
self.assertEqual(fmt.format_complex_imp(complex(1, 0)), '1+j0 \N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_complex_imp(complex(1234, 1234)), '1.23k+j1.23k \N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_complex_imp(complex(1234, -1234)), '1.23k-j1.23k \N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_complex_imp(complex(1.234, 1234)), '1.23+j1.23k \N{OHM SIGN}')
|
||||
self.assertEqual(fmt.format_complex_imp(complex(-1, 1.23e-3)), '- +j1.23m \N{OHM SIGN}')
|
|
@ -23,13 +23,15 @@ from math import inf
|
|||
|
||||
F_DEFAULT = Format()
|
||||
|
||||
F_ASSERT_DIGITS_1 = Format(max_nr_digits=2)
|
||||
F_ASSERT_DIGITS_0 = Format(max_nr_digits=0)
|
||||
F_ASSERT_DIGITS_2 = Format(max_nr_digits=31)
|
||||
F_ASSERT_OFFSET_1 = Format(min_offset=-9)
|
||||
F_ASSERT_OFFSET_2 = Format(max_offset=9)
|
||||
F_ASSERT_OFFSET_3 = Format(min_offset=9)
|
||||
F_ASSERT_CLAMP = Format(parse_clamp_min=10, parse_clamp_max=9)
|
||||
|
||||
F_DIGITS_1 = Format(max_nr_digits=1, min_offset=-2,
|
||||
max_offset=2, assume_infinity=False)
|
||||
F_DIGITS_3 = Format(max_nr_digits=3, min_offset=-2,
|
||||
max_offset=2, assume_infinity=False)
|
||||
F_DIGITS_4 = Format(max_nr_digits=4)
|
||||
|
@ -42,7 +44,7 @@ F_WITH_UNDERSCORE = Format(space_str="_")
|
|||
class TestTSIToolsValue(unittest.TestCase):
|
||||
|
||||
def test_format_assertions(self):
|
||||
self.assertRaises(AssertionError, Value, fmt=F_ASSERT_DIGITS_1)
|
||||
self.assertRaises(AssertionError, Value, fmt=F_ASSERT_DIGITS_0)
|
||||
self.assertRaises(AssertionError, Value, fmt=F_ASSERT_DIGITS_2)
|
||||
self.assertRaises(AssertionError, Value, fmt=F_ASSERT_OFFSET_1)
|
||||
self.assertRaises(AssertionError, Value, fmt=F_ASSERT_OFFSET_2)
|
||||
|
@ -95,8 +97,8 @@ class TestTSIToolsValue(unittest.TestCase):
|
|||
self.assertEqual(str(Value(1e-30)), "0.00000")
|
||||
self.assertEqual(float(Value(1e-30)), 1e-30)
|
||||
|
||||
def test_format_digits_3(self):
|
||||
v = Value(fmt=F_DIGITS_3)
|
||||
def test_format_digits_1(self):
|
||||
v = Value(fmt=F_DIGITS_1)
|
||||
self.assertEqual(str(v.parse("1")), "1")
|
||||
self.assertEqual(str(v.parse("10")), "10")
|
||||
self.assertEqual(str(v.parse("100")), "100")
|
||||
|
@ -109,6 +111,20 @@ class TestTSIToolsValue(unittest.TestCase):
|
|||
self.assertEqual(str(v.parse("1e-3")), "1m")
|
||||
self.assertEqual(str(v.parse("1e-9")), "0")
|
||||
|
||||
def test_format_digits_3(self):
|
||||
v = Value(fmt=F_DIGITS_3)
|
||||
self.assertEqual(str(v.parse("1")), "1.00")
|
||||
self.assertEqual(str(v.parse("10")), "10.0")
|
||||
self.assertEqual(str(v.parse("100")), "100")
|
||||
self.assertEqual(str(v.parse("1e3")), "1.00k")
|
||||
self.assertEqual(str(v.parse("1e4")), "10.0k")
|
||||
self.assertEqual(str(v.parse("1e5")), "100k")
|
||||
self.assertEqual(str(v.parse("1e9")), "1000M")
|
||||
self.assertEqual(str(v.parse("1e-1")), "100m")
|
||||
self.assertEqual(str(v.parse("1e-2")), "10.0m")
|
||||
self.assertEqual(str(v.parse("1e-3")), "1.00m")
|
||||
self.assertEqual(str(v.parse("1e-9")), "0.00")
|
||||
|
||||
def test_format_digits_4(self):
|
||||
v = Value(fmt=F_DIGITS_4)
|
||||
self.assertEqual(str(v.parse("1")), "1.000")
|
||||
|
|
|
@ -31,7 +31,7 @@ import unittest
|
|||
if __name__ == '__main__':
|
||||
sys.path.append('.')
|
||||
loader = unittest.TestLoader()
|
||||
tests = loader.discover('.')
|
||||
tests = loader.discover('./test')
|
||||
testRunner = unittest.runner.TextTestRunner(
|
||||
failfast=False,
|
||||
verbosity=2)
|
||||
|
|
Ładowanie…
Reference in New Issue