diff --git a/NanoVNASaver/RFTools.py b/NanoVNASaver/RFTools.py index 2f71e65..b1b01a3 100644 --- a/NanoVNASaver/RFTools.py +++ b/NanoVNASaver/RFTools.py @@ -15,6 +15,7 @@ # along with this program. If not, see . import collections import math +from numbers import Number from typing import List from NanoVNASaver.SITools import Value, Format @@ -33,7 +34,7 @@ class RFTools: return re50, im50 @staticmethod - def gain(data: Datapoint): + def gain(data: Datapoint) -> float: # re50, im50 = normalize50(data) # Calculate the gain / reflection coefficient # mag = math.sqrt((re50 - 50) * (re50 - 50) + im50 * im50) / \ @@ -43,8 +44,7 @@ class RFTools: mag = math.sqrt(data.re**2 + data.im**2) if mag > 0: return 20 * math.log10(mag) - else: - return 0 + return 0 @staticmethod def qualityFactor(data: Datapoint): @@ -82,85 +82,48 @@ class RFTools: return str(Value(inductance, "H", Format(max_nr_digits=5, space_str=" "))) @staticmethod - def formatFrequency(freq): - return str(Value(freq, "Hz", Format(max_nr_digits=6))) + def formatFrequency(freq: Number) -> str: + return str(Value(freq, "Hz")) @staticmethod - def formatShortFrequency(freq): + def formatShortFrequency(freq: Number) -> str: return str(Value(freq, "Hz", Format(max_nr_digits=4))) @staticmethod - def formatSweepFrequency(freq: int, - mindigits: int = 2, - appendHz: bool = True, - insertSpace: bool = False, - countDot: bool = True, - assumeInfinity: bool = True) -> str: - """ Format frequency with SI prefixes - - mindigits count refers to the number of decimal place digits - that will be shown, padded with zeroes if needed. - """ - freqstr = str(freq) - freqlen = len(freqstr) - - # sanity checks - if freqlen > 15: - if assumeInfinity: - return "\N{INFINITY}" - raise ValueError("Frequency too big. More than 15 digits!") - - if freq < 1: - return " - " + (" " if insertSpace else "") + ("Hz" if appendHz else "") - - si_index = (freqlen - 1) // 3 - dot_pos = freqlen % 3 or 3 - intfstr = freqstr[:dot_pos] - decfstr = freqstr[dot_pos:] - nzdecfstr = decfstr.rstrip('0') - if si_index != 0: - while len(nzdecfstr) < mindigits: - nzdecfstr += '0' - freqstr = intfstr + ("." if len(nzdecfstr) > 0 else "") + nzdecfstr - return freqstr + (" " if insertSpace else "") + PREFIXES[si_index] + ("Hz" if appendHz else "") + def formatSweepFrequency(freq: Number) -> str: + return str(Value(freq, "Hz", Format(max_nr_digits=5))) @staticmethod def parseFrequency(freq: str) -> int: - parser = Value(0, "Hz") + parser = Value(0, "Hz", Format(parse_sloppy_unit=True, parse_sloppy_kilo=True)) try: return round(parser.parse(freq)) except (ValueError, IndexError): return -1 @staticmethod - def phaseAngle(data: Datapoint): + def phaseAngle(data: Datapoint) -> float: re = data.re im = data.im return math.degrees(math.atan2(im, re)) @staticmethod - def phaseAngleRadians(data: Datapoint): + def phaseAngleRadians(data: Datapoint) -> float: re = data.re im = data.im return math.atan2(im, re) @staticmethod def groupDelay(data: List[Datapoint], index: int) -> float: - if index == 0: - angle0 = RFTools.phaseAngleRadians(data[0]) - angle1 = RFTools.phaseAngleRadians(data[1]) - freq0 = data[0].freq - freq1 = data[1].freq - elif index == len(data) - 1: - angle0 = RFTools.phaseAngleRadians(data[-2]) - angle1 = RFTools.phaseAngleRadians(data[-1]) - freq0 = data[-2].freq - freq1 = data[-1].freq - else: - angle0 = RFTools.phaseAngleRadians(data[index-1]) - angle1 = RFTools.phaseAngleRadians(data[index+1]) - freq0 = data[index-1].freq - freq1 = data[index+1].freq + if index <= 0: # fix list boundaries + index = 1 + elif index >= len(data) - 1: + index = len(data -2) + + angle0 = RFTools.phaseAngleRadians(data[index-1]) + angle1 = RFTools.phaseAngleRadians(data[index+1]) + freq0 = data[index-1].freq + freq1 = data[index+1].freq delta_angle = (angle1 - angle0) if abs(delta_angle) > math.tau: if delta_angle > 0: