kopia lustrzana https://github.com/NanoVNA-Saver/nanovna-saver
cleanup and comments
rodzic
496494900f
commit
4930519fd8
|
@ -4,268 +4,51 @@ Created on 30 giu 2020
|
|||
@author: mauro
|
||||
'''
|
||||
|
||||
from PyQt5 import QtWidgets, QtTest
|
||||
from PyQt5 import QtWidgets
|
||||
import logging
|
||||
import math
|
||||
|
||||
from NanoVNASaver.Analysis import Analysis
|
||||
|
||||
from NanoVNASaver.Hardware import VNA
|
||||
|
||||
import numpy as np
|
||||
from NanoVNASaver.Marker import Marker
|
||||
from NanoVNASaver import RFTools
|
||||
from NanoVNASaver.Analysis.VSWRAnalysis import VSWRAnalysis
|
||||
from NanoVNASaver.Formatting import format_frequency_sweep
|
||||
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Antenna(object):
|
||||
|
||||
@staticmethod
|
||||
def group_consecutives(vals, step=1):
|
||||
"""
|
||||
https://stackoverflow.com/questions/7352684/how-to-find-the-groups-of-consecutive-elements-from-an-array-in-numpy
|
||||
|
||||
Return list of consecutive lists of numbers from vals (number list).
|
||||
:param vals:
|
||||
:param step:
|
||||
"""
|
||||
run = []
|
||||
result = [run]
|
||||
expect = None
|
||||
for v in vals:
|
||||
if (v == expect) or (expect is None):
|
||||
run.append(v)
|
||||
else:
|
||||
run = [v]
|
||||
result.append(run)
|
||||
expect = v + step
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def analyze(cls, frequencies, values, FIELD_NAME, step=5000, vuoto=False):
|
||||
'''
|
||||
dati dati, prova a trovare minimi e bands passanti
|
||||
:param cls:
|
||||
'''
|
||||
|
||||
if FIELD_NAME == "rl":
|
||||
BAND_THRESHOLD = -7.0
|
||||
MIN_CALCOLO_Q = -27
|
||||
|
||||
elif FIELD_NAME == "vswr":
|
||||
BAND_THRESHOLD = 2.62
|
||||
MIN_CALCOLO_Q = 1.1
|
||||
else:
|
||||
raise ValueError("unknown threshold for {}".format(FIELD_NAME))
|
||||
|
||||
bands_raw = np.where(values < BAND_THRESHOLD)[0]
|
||||
|
||||
# raggruppo posizioni in cui il valore è sotto la soglia
|
||||
bands = cls.group_consecutives(bands_raw)
|
||||
# print("raggruppate in ", bands)
|
||||
out = []
|
||||
# print "bands", bands
|
||||
banda_dict = None
|
||||
for band in bands:
|
||||
if band:
|
||||
|
||||
print("band ", band)
|
||||
fmin = frequencies[band[0]]
|
||||
|
||||
fmax = frequencies[band[-1]]
|
||||
estensione = fmax - fmin
|
||||
x = np.argmin(values[band[0]:band[-1] + 1])
|
||||
prog = x + band[0]
|
||||
min_val = values[prog]
|
||||
|
||||
if banda_dict:
|
||||
salto = fmin - banda_dict["fmax"]
|
||||
if salto < (10 * step):
|
||||
logger.warning("unisco band e proseguo")
|
||||
if min_val < banda_dict["min"]:
|
||||
logger.debug("aggiusto nuovo minimo, da %s a %s",
|
||||
banda_dict["min"], min_val)
|
||||
banda_dict["min"] = min_val
|
||||
# invalido eventuale Q e band passante ?!?
|
||||
banda_dict["q"] = None
|
||||
banda_dict["banda_passante"] = None
|
||||
banda_dict["fmax"] = fmax
|
||||
# non servono ulteriori elaborazioni
|
||||
continue
|
||||
|
||||
else:
|
||||
logger.warning("finalizzo band precedente")
|
||||
out.append(banda_dict)
|
||||
banda_dict = None
|
||||
# se sono qui è nuova
|
||||
|
||||
if estensione == 0 and vuoto:
|
||||
logger.warning("ritorno minima estensione")
|
||||
banda_dict = {"fmin": fmin - 30 * step,
|
||||
"fmax": fmin + 30 * step,
|
||||
"banda_passante": None,
|
||||
"q": None,
|
||||
"min": min_val,
|
||||
"freq": fmin,
|
||||
"prog": prog,
|
||||
}
|
||||
else:
|
||||
logger.warning("Nuova band")
|
||||
if min_val <= MIN_CALCOLO_Q:
|
||||
|
||||
# FIXME: verificare che ci siano valori >
|
||||
# BAND_THRESHOLD?!?
|
||||
q = np.sqrt(fmax * fmin) / (fmax - fmin)
|
||||
logger.info("Q=%s", q)
|
||||
else:
|
||||
logger.info(
|
||||
"non calcolo Q perchè minimo %s non è abbastanza", min_val)
|
||||
q = None
|
||||
banda_dict = {"fmin": fmin,
|
||||
"fmax": fmax,
|
||||
"banda_passante": fmax - fmin,
|
||||
"q": q,
|
||||
"min": min_val,
|
||||
"freq": frequencies[prog],
|
||||
"prog": prog,
|
||||
}
|
||||
|
||||
if banda_dict:
|
||||
out.append(banda_dict)
|
||||
return out
|
||||
|
||||
class ChartFactory(object):
|
||||
|
||||
@classmethod
|
||||
def NewChart(cls, chart_class, name, app):
|
||||
from NanoVNASaver.NanoVNASaver import BandsModel
|
||||
new_chart = chart_class(name)
|
||||
new_chart.isPopout = True
|
||||
new_chart.data = app.data
|
||||
new_chart.bands = BandsModel()
|
||||
i=0
|
||||
default_color = app.default_marker_colors[i]
|
||||
color = app.settings.value("Marker" + str(i+1) + "Color", default_color)
|
||||
marker = Marker("Marker " + str(i+1), color)
|
||||
marker.isMouseControlledRadioButton.setChecked(True)
|
||||
new_chart.setMarkers([marker])
|
||||
|
||||
return new_chart
|
||||
|
||||
class MinVswrAnalysis(Antenna, Analysis):
|
||||
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
self._widget = QtWidgets.QWidget()
|
||||
|
||||
def runAnalysis(self):
|
||||
self.reset()
|
||||
|
||||
if len(self.app.data) == 0:
|
||||
logger.debug("No data to analyse")
|
||||
self.result_label.setText("No data to analyse.")
|
||||
return
|
||||
|
||||
frequencies = []
|
||||
values = []
|
||||
for p in self.app.data:
|
||||
frequencies.append(p.freq)
|
||||
vswr = p.vswr
|
||||
values.append(vswr)
|
||||
|
||||
res = self.analyze(np.array(frequencies),
|
||||
np.array(values),
|
||||
"vswr")
|
||||
marker = 0
|
||||
for banda in res:
|
||||
if marker < 3:
|
||||
self.app.markers[marker].setFrequency(
|
||||
str(round(banda["freq"])))
|
||||
marker += 1
|
||||
print("min {min} a {freq}".format(**banda))
|
||||
|
||||
# Charts
|
||||
progr = 0
|
||||
for c in self.app.subscribing_charts:
|
||||
if c.name == "S11 VSWR":
|
||||
new_chart = c.copy()
|
||||
new_chart.isPopout = True
|
||||
new_chart.show()
|
||||
new_chart.setWindowTitle("%s %s" % (new_chart.name, progr))
|
||||
|
||||
vna = self.app.vna
|
||||
if isinstance(vna, InvalidVNA):
|
||||
logger.warning("end analysis, non valid vna")
|
||||
else:
|
||||
logger.warning("band zoom")
|
||||
for banda in res:
|
||||
progr += 1
|
||||
# scan
|
||||
self.app.sweepStartInput.setText(str(banda["fmin"]))
|
||||
self.app.sweepEndInput.setText(str(banda["fmax"]))
|
||||
self.app.sweep()
|
||||
while not self.app.btnSweep.isEnabled():
|
||||
QtTest.QTest.qWait(500)
|
||||
for c in self.app.subscribing_charts:
|
||||
if c.name == "S11 VSWR":
|
||||
new_chart = c.copy()
|
||||
new_chart.isPopout = True
|
||||
new_chart.show()
|
||||
new_chart.setWindowTitle("%s %s" % (new_chart.name, progr))
|
||||
|
||||
|
||||
class ZeroCrossAnalysis(Antenna, Analysis):
|
||||
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
self._widget = QtWidgets.QWidget()
|
||||
|
||||
def runAnalysis(self):
|
||||
self.reset()
|
||||
|
||||
if len(self.app.data) == 0:
|
||||
logger.debug("No data to analyse")
|
||||
self.result_label.setText("No data to analyse.")
|
||||
return
|
||||
|
||||
frequencies = []
|
||||
values = []
|
||||
for p in self.app.data:
|
||||
|
||||
frequencies.append(p.freq)
|
||||
|
||||
values.append(p.z.imag)
|
||||
|
||||
zero_crossings = np.where(np.diff(np.sign(np.array(values))))[0]
|
||||
|
||||
marker = 0
|
||||
for pos in zero_crossings:
|
||||
freq = round(frequencies[pos])
|
||||
if marker < 3:
|
||||
self.app.markers[marker].setFrequency(
|
||||
str(freq))
|
||||
marker += 1
|
||||
print("cross at {}".format(freq))
|
||||
|
||||
class MagLoopAnalysis(VSWRAnalysis):
|
||||
'''
|
||||
Find min vswr and change sweep to zoom.
|
||||
Useful for tuning magloop.
|
||||
|
||||
'''
|
||||
max_dips_shown = 1
|
||||
vswr_limit_value = 2.56
|
||||
bandwith = 250000
|
||||
|
||||
def runAnalysis(self):
|
||||
|
||||
super().runAnalysis()
|
||||
|
||||
for m in self.minimums:
|
||||
if len(self.minimums) > 1:
|
||||
self.layout.addRow("", QtWidgets.QLabel(
|
||||
"Not magloop or try to lower VSWR limit"))
|
||||
|
||||
for m in self.minimums[:1]:
|
||||
# only one time
|
||||
start, lowest, end = m
|
||||
if start != end:
|
||||
Q = self.app.data[lowest].freq/(self.app.data[end].freq-self.app.data[start].freq)
|
||||
self.layout.addRow("Q",QtWidgets.QLabel("{}".format(int(Q))))
|
||||
Q = self.app.data[lowest].freq / \
|
||||
(self.app.data[end].freq - self.app.data[start].freq)
|
||||
self.layout.addRow(
|
||||
"Q", QtWidgets.QLabel("{}".format(int(Q))))
|
||||
self.app.sweepStartInput.setText(self.app.data[start].freq)
|
||||
self.app.sweepStartInput.textEdited.emit(
|
||||
self.app.sweepStartInput.text())
|
||||
self.app.sweepEndInput.setText(self.app.data[end].freq)
|
||||
# self.app.sweepEndInput.textEdited.emit(self.app.sweepEndInput.text())
|
||||
|
||||
self.app.sweepEndInput.textEdited.emit(
|
||||
self.app.sweepEndInput.text())
|
||||
else:
|
||||
self.app.sweepStartInput.setText(
|
||||
self.app.data[start].freq - self.bandwith)
|
||||
self.app.sweepStartInput.textEdited.emit(
|
||||
self.app.sweepStartInput.text())
|
||||
self.app.sweepEndInput.setText(
|
||||
self.app.data[end].freq + self.bandwith)
|
||||
self.app.sweepEndInput.textEdited.emit(
|
||||
self.app.sweepEndInput.text())
|
||||
|
|
Ładowanie…
Reference in New Issue