# 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 . 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.crossings: 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