kopia lustrzana https://github.com/NanoVNA-Saver/nanovna-saver
163 wiersze
5.7 KiB
Python
163 wiersze
5.7 KiB
Python
# NanoVNASaver
|
|
#
|
|
# A python program to view and export Touchstone data from a NanoVNA
|
|
# Copyright (C) 2019, 2020 Rune B. Broberg
|
|
# Copyright (C) 2020ff NanoVNA-Saver Authors
|
|
#
|
|
# 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 csv
|
|
import logging
|
|
|
|
from PyQt5 import QtWidgets
|
|
|
|
import NanoVNASaver.AnalyticTools as at
|
|
from NanoVNASaver.Analysis.ResonanceAnalysis import (
|
|
ResonanceAnalysis, format_resistence_neg
|
|
)
|
|
from NanoVNASaver.Formatting import (
|
|
format_frequency, format_complex_imp, format_frequency_short)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class EFHWAnalysis(ResonanceAnalysis):
|
|
"""
|
|
find only resonance when HI impedance
|
|
"""
|
|
|
|
def __init__(self, app):
|
|
super().__init__(app)
|
|
self.old_data = []
|
|
|
|
def do_resonance_analysis(self):
|
|
s11 = self.app.data.s11
|
|
maximums = sorted(
|
|
at.maxima([d.impedance().real for d in s11],
|
|
threshold=500))
|
|
extended_data = {}
|
|
logger.info("TO DO: find near data")
|
|
for lowest in self.crossing:
|
|
my_data = self._get_data(lowest)
|
|
if lowest in extended_data:
|
|
extended_data[lowest].update(my_data)
|
|
else:
|
|
extended_data[lowest] = my_data
|
|
logger.debug("maximumx %s of type %s", maximums, type(maximums))
|
|
for m in maximums:
|
|
logger.debug("m %s of type %s", m, type(m))
|
|
my_data = self._get_data(m)
|
|
if m in extended_data:
|
|
extended_data[m].update(my_data)
|
|
else:
|
|
extended_data[m] = my_data
|
|
fields = [("freq", format_frequency_short),
|
|
("r", format_resistence_neg), ("lambda", lambda x: round(x, 2))]
|
|
|
|
if self.old_data:
|
|
diff = self.compare(
|
|
self.old_data[-1], extended_data, fields=fields)
|
|
else:
|
|
diff = self.compare({}, extended_data, fields=fields)
|
|
self.old_data.append(extended_data)
|
|
for i, idx in enumerate(sorted(extended_data.keys())):
|
|
self.layout.addRow(
|
|
f"{format_frequency_short(s11[idx].freq)}",
|
|
QtWidgets.QLabel(
|
|
f" ({diff[i]['freq']})"
|
|
f" {format_complex_imp(s11[idx].impedance())}"
|
|
f" ({diff[i]['r']}) {diff[i]['lambda']} m"))
|
|
|
|
if self.filename and extended_data:
|
|
with open(
|
|
self.filename, 'w', newline='', encoding='utf-8'
|
|
) as csvfile:
|
|
fieldnames = extended_data[sorted(
|
|
extended_data.keys())[0]].keys()
|
|
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
|
|
writer.writeheader()
|
|
for idx in sorted(extended_data.keys()):
|
|
writer.writerow(extended_data[idx])
|
|
|
|
def compare(self, old, new, fields=None):
|
|
"""
|
|
Compare data to help changes
|
|
|
|
NB
|
|
must be same sweep
|
|
( same index must be same frequence )
|
|
:param old:
|
|
:param new:
|
|
"""
|
|
fields = fields or [("freq", str), ]
|
|
|
|
def no_compare():
|
|
|
|
return {k: "-" for k, _ in fields}
|
|
|
|
old_idx = sorted(old.keys())
|
|
# 'odict_keys' object is not subscriptable
|
|
new_idx = sorted(new.keys())
|
|
diff = {}
|
|
i_max = min(len(old_idx), len(new_idx))
|
|
i_tot = max(len(old_idx), len(new_idx))
|
|
|
|
if i_max != i_tot:
|
|
logger.warning("resonances changed from %s to %s",
|
|
len(old_idx), len(new_idx))
|
|
|
|
split = 0
|
|
max_delta_f = 1_000_000
|
|
for i, k in enumerate(new_idx):
|
|
if len(old_idx) <= i + split:
|
|
diff[i] = no_compare()
|
|
continue
|
|
|
|
logger.info("Resonance %s at %s", i, new[k]["freq"])
|
|
|
|
delta_f = new[k]["freq"] - old[old_idx[i + split]]["freq"]
|
|
if abs(delta_f) < max_delta_f:
|
|
logger.debug("can compare")
|
|
diff[i] = {
|
|
desc: fnc(new[k][desc] - old[old_idx[i + split]][desc])
|
|
for desc, fnc in fields
|
|
}
|
|
logger.debug("Deltas %s", diff[i])
|
|
continue
|
|
|
|
logger.debug("can't compare, %s is too much ",
|
|
format_frequency(delta_f))
|
|
|
|
if delta_f > 0:
|
|
logger.debug("possible missing band, ")
|
|
if len(old_idx) > (i + split + 1):
|
|
if (abs(new[k]["freq"] -
|
|
old[old_idx[i + split + 1]]["freq"]) <
|
|
max_delta_f):
|
|
logger.debug("new is missing band, compare next ")
|
|
split += 1
|
|
# FIXME: manage 2 or more band missing ?!?
|
|
continue
|
|
logger.debug("new band, non compare ")
|
|
diff[i] = no_compare()
|
|
continue
|
|
|
|
logger.debug("new band, non compare ")
|
|
diff[i] = no_compare()
|
|
split -= 1
|
|
|
|
for i in range(i_max, i_tot):
|
|
# add missing in old ... if any
|
|
diff[i] = no_compare()
|
|
return diff
|