def updateLabels(self, s11data: List[Datapoint], s21data: List[Datapoint]): from NanoVNASaver.Chart import PhaseChart from NanoVNASaver.NanoVNASaver import NanoVNASaver if self.location != -1: im50, re50, vswr = NanoVNASaver.vswr(s11data[self.location]) if im50 < 0: im50str = " - j" + str(round(-1 * im50, 3)) else: im50str = " + j" + str(round(im50, 3)) self.frequency_label.setText( NanoVNASaver.formatFrequency(s11data[self.location].freq)) self.impedance_label.setText(str(round(re50, 3)) + im50str) self.returnloss_label.setText( str(round(20 * math.log10((vswr - 1) / (vswr + 1)), 3)) + " dB") reactance = NanoVNASaver.reactanceEquivalent( im50, s11data[self.location].freq) self.reactance_label.setText(reactance) self.vswr_label.setText(str(round(vswr, 3))) if len(s21data) == len(s11data): _, _, vswr = NanoVNASaver.vswr(s21data[self.location]) self.gain_label.setText( str(round(20 * math.log10((vswr - 1) / (vswr + 1)), 3)) + " dB") self.phase_label.setText( str(round(PhaseChart.angle(s21data[self.location]), 2)) + "\N{DEGREE SIGN}")
def calculateRolloff(self, location1, location2): from NanoVNASaver.NanoVNASaver import NanoVNASaver frequency1 = self.app.data21[location1].freq frequency2 = self.app.data21[location2].freq gain1 = NanoVNASaver.gain(self.app.data21[location1]) gain2 = NanoVNASaver.gain(self.app.data21[location2]) frequency_factor = frequency2 / frequency1 if frequency_factor < 1: frequency_factor = 1 / frequency_factor attenuation = abs(gain1 - gain2) logger.debug("Measured points: %d Hz and %d Hz", frequency1, frequency2) logger.debug("%f dB over %f factor", attenuation, frequency_factor) octave_attenuation = attenuation / (math.log10(frequency_factor) / math.log10(2)) decade_attenuation = attenuation / math.log10(frequency_factor) return octave_attenuation, decade_attenuation
def updateLabels(self, s11data: List[Datapoint], s21data: List[Datapoint]): from NanoVNASaver.Chart import PhaseChart from NanoVNASaver.NanoVNASaver import NanoVNASaver if self.location != -1: im50, re50, vswr = NanoVNASaver.vswr(s11data[self.location]) rp = (re50**2 + im50**2) / re50 xp = (re50**2 + im50**2) / im50 re50 = round(re50, 4 - max(0, math.floor(math.log10(abs(re50))))) rp = round(rp, 4 - max(0, math.floor(math.log10(abs(rp))))) im50 = round(im50, 4 - max(0, math.floor(math.log10(abs(im50))))) xp = round(xp, 4 - max(0, math.floor(math.log10(abs(xp))))) if im50 < 0: im50str = " -j" + str(-1 * im50) else: im50str = " +j" + str(im50) im50str += "\N{OHM SIGN}" if xp < 0: xpstr = NanoVNASaver.capacitanceEquivalent( xp, s11data[self.location].freq) else: xpstr = NanoVNASaver.inductanceEquivalent( xp, s11data[self.location].freq) self.frequency_label.setText( NanoVNASaver.formatFrequency(s11data[self.location].freq)) self.impedance_label.setText(str(re50) + im50str) self.parallel_r_label.setText(str(rp) + "\N{OHM SIGN}") self.parallel_x_label.setText(xpstr) self.returnloss_label.setText( str(round(20 * math.log10((vswr - 1) / (vswr + 1)), 3)) + " dB") capacitance = NanoVNASaver.capacitanceEquivalent( im50, s11data[self.location].freq) inductance = NanoVNASaver.inductanceEquivalent( im50, s11data[self.location].freq) self.inductance_label.setText(inductance) self.capacitance_label.setText(capacitance) vswr = round(vswr, 3) if vswr < 0: vswr = "-" self.vswr_label.setText(str(vswr)) self.quality_factor_label.setText( str( round(NanoVNASaver.qualifyFactor(s11data[self.location]), 1))) self.s11_phase_label.setText( str(round(-PhaseChart.angle(s11data[self.location]), 2)) + "\N{DEGREE SIGN}") if len(s21data) == len(s11data): _, _, vswr = NanoVNASaver.vswr(s21data[self.location]) self.gain_label.setText( str(round(20 * math.log10((vswr - 1) / (vswr + 1)), 3)) + " dB") self.s21_phase_label.setText( str(round(-PhaseChart.angle(s21data[self.location]), 2)) + "\N{DEGREE SIGN}")
def main(): parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("-d", "--debug", action="store_true", help="Set loglevel to debug") parser.add_argument("-D", "--debug-file", help="File to write debug logging output to") parser.add_argument("--version", action="version", version=f"NanoVNASaver {VERSION}") args = parser.parse_args() console_log_level = logging.WARNING file_log_level = logging.DEBUG print(INFO) if args.debug: console_log_level = logging.DEBUG logger = logging.getLogger("NanoVNASaver") logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(console_log_level) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) logger.addHandler(ch) if args.debug_file: fh = logging.FileHandler(args.debug_file) fh.setLevel(file_log_level) fh.setFormatter(formatter) logger.addHandler(fh) logger.info("Startup...") QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) app = QtWidgets.QApplication(sys.argv) window = NanoVNASaver() window.show() try: app.exec_() except BaseException as exc: logger.exception("%s", exc)
def runAnalysis(self): from NanoVNASaver.NanoVNASaver import NanoVNASaver self.reset() pass_band_location = self.app.markers[0].location logger.debug("Pass band location: %d", pass_band_location) if len(self.app.data21) == 0: logger.debug("No data to analyse") self.result_label.setText("No data to analyse.") return if pass_band_location < 0: logger.debug("No location for %s", self.app.markers[0].name) self.result_label.setText("Please place " + self.app.markers[0].name + " in the passband.") return pass_band_db = NanoVNASaver.gain(self.app.data21[pass_band_location]) logger.debug("Initial passband gain: %d", pass_band_db) initial_cutoff_location = -1 for i in range(pass_band_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found a cutoff location initial_cutoff_location = i break if initial_cutoff_location < 0: self.result_label.setText("Cutoff location not found.") return initial_cutoff_frequency = self.app.data21[initial_cutoff_location].freq logger.debug("Found initial cutoff frequency at %d", initial_cutoff_frequency) peak_location = -1 peak_db = NanoVNASaver.gain(self.app.data21[initial_cutoff_location]) for i in range(0, initial_cutoff_location): db = NanoVNASaver.gain(self.app.data21[i]) if db > peak_db: peak_db = db peak_location = i logger.debug("Found peak of %f at %d", peak_db, self.app.data[peak_location].freq) self.app.markers[0].setFrequency(str(self.app.data21[peak_location].freq)) self.app.markers[0].frequencyInput.setText(str(self.app.data21[peak_location].freq)) cutoff_location = -1 pass_band_db = peak_db for i in range(peak_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found the cutoff location cutoff_location = i break cutoff_frequency = self.app.data21[cutoff_location].freq cutoff_gain = NanoVNASaver.gain(self.app.data21[cutoff_location]) - pass_band_db if cutoff_gain < -4: logger.debug("Cutoff frequency found at %f dB - insufficient data points for true -3 dB point.", cutoff_gain) logger.debug("Found true cutoff frequency at %d", cutoff_frequency) self.cutoff_label.setText(NanoVNASaver.formatFrequency(cutoff_frequency) + " (" + str(round(cutoff_gain, 1)) + " dB)") self.app.markers[1].setFrequency(str(cutoff_frequency)) self.app.markers[1].frequencyInput.setText(str(cutoff_frequency)) six_db_location = -1 for i in range(cutoff_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 6: # We found 6dB location six_db_location = i break if six_db_location < 0: self.result_label.setText("6 dB location not found.") return six_db_cutoff_frequency = self.app.data21[six_db_location].freq self.six_db_label.setText(NanoVNASaver.formatFrequency(six_db_cutoff_frequency)) ten_db_location = -1 for i in range(cutoff_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 10: # We found 6dB location ten_db_location = i break twenty_db_location = -1 for i in range(cutoff_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 20: # We found 6dB location twenty_db_location = i break sixty_db_location = -1 for i in range(six_db_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 60: # We found 60dB location! Wow. sixty_db_location = i break if sixty_db_location > 0: sixty_db_cutoff_frequency = self.app.data21[sixty_db_location].freq self.sixty_db_label.setText(NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency)) else: # # We derive 60 dB instead # factor = 10 * (-54 / decade_attenuation) # sixty_db_cutoff_frequency = round(six_db_cutoff_frequency + six_db_cutoff_frequency * factor) # self.sixty_db_label.setText(NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency) + " (derived)") self.sixty_db_label.setText("Not calculated") if ten_db_location > 0 and twenty_db_location > 0: octave_attenuation, decade_attenuation = self.calculateRolloff(ten_db_location, twenty_db_location) self.db_per_octave_label.setText(str(round(octave_attenuation, 3)) + " dB / octave") self.db_per_decade_label.setText(str(round(decade_attenuation, 3)) + " dB / decade") else: self.db_per_octave_label.setText("Not calculated") self.db_per_decade_label.setText("Not calculated") self.result_label.setText("Analysis complete (" + str(len(self.app.data)) + " points)")
def runAnalysis(self): from NanoVNASaver.NanoVNASaver import NanoVNASaver self.reset() if len(self.app.data21) == 0: logger.debug("No data to analyse") self.result_label.setText("No data to analyse.") return peak_location = -1 peak_db = NanoVNASaver.gain(self.app.data21[0]) for i in range(len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if db > peak_db: peak_db = db peak_location = i logger.debug("Found peak of %f at %d", peak_db, self.app.data[peak_location].freq) lower_cutoff_location = -1 pass_band_db = peak_db for i in range(len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found the cutoff location lower_cutoff_location = i break lower_cutoff_frequency = self.app.data21[lower_cutoff_location].freq lower_cutoff_gain = NanoVNASaver.gain(self.app.data21[lower_cutoff_location]) - pass_band_db if lower_cutoff_gain < -4: logger.debug("Lower cutoff frequency found at %f dB - insufficient data points for true -3 dB point.", lower_cutoff_gain) logger.debug("Found true lower cutoff frequency at %d", lower_cutoff_frequency) self.lower_cutoff_label.setText(NanoVNASaver.formatFrequency(lower_cutoff_frequency) + " (" + str(round(lower_cutoff_gain, 1)) + " dB)") self.app.markers[1].setFrequency(str(lower_cutoff_frequency)) self.app.markers[1].frequencyInput.setText(str(lower_cutoff_frequency)) upper_cutoff_location = -1 for i in range(len(self.app.data21)-1, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found the cutoff location upper_cutoff_location = i break upper_cutoff_frequency = self.app.data21[upper_cutoff_location].freq upper_cutoff_gain = NanoVNASaver.gain(self.app.data21[upper_cutoff_location]) - pass_band_db if upper_cutoff_gain < -4: logger.debug("Upper cutoff frequency found at %f dB - insufficient data points for true -3 dB point.", upper_cutoff_gain) logger.debug("Found true upper cutoff frequency at %d", upper_cutoff_frequency) self.upper_cutoff_label.setText(NanoVNASaver.formatFrequency(upper_cutoff_frequency) + " (" + str(round(upper_cutoff_gain, 1)) + " dB)") self.app.markers[2].setFrequency(str(upper_cutoff_frequency)) self.app.markers[2].frequencyInput.setText(str(upper_cutoff_frequency)) span = upper_cutoff_frequency - lower_cutoff_frequency center_frequency = math.sqrt(lower_cutoff_frequency * upper_cutoff_frequency) q = center_frequency / span self.span_label.setText(NanoVNASaver.formatFrequency(span)) self.center_frequency_label.setText(NanoVNASaver.formatFrequency(center_frequency)) self.quality_label.setText(str(round(q, 2))) self.app.markers[0].setFrequency(str(round(center_frequency))) self.app.markers[0].frequencyInput.setText(str(round(center_frequency))) # Lower roll-off lower_six_db_location = -1 for i in range(lower_cutoff_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 6: # We found 6dB location lower_six_db_location = i break if lower_six_db_location < 0: self.result_label.setText("Lower 6 dB location not found.") return lower_six_db_cutoff_frequency = self.app.data21[lower_six_db_location].freq self.lower_six_db_label.setText(NanoVNASaver.formatFrequency(lower_six_db_cutoff_frequency)) ten_db_location = -1 for i in range(lower_cutoff_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 10: # We found 6dB location ten_db_location = i break twenty_db_location = -1 for i in range(lower_cutoff_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 20: # We found 6dB location twenty_db_location = i break sixty_db_location = -1 for i in range(lower_six_db_location, len(self.app.data21)): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 60: # We found 60dB location! Wow. sixty_db_location = i break if sixty_db_location > 0: sixty_db_cutoff_frequency = self.app.data21[sixty_db_location].freq self.lower_sixty_db_label.setText(NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency)) else: # # We derive 60 dB instead # factor = 10 * (-54 / decade_attenuation) # sixty_db_cutoff_frequency = round(six_db_cutoff_frequency + six_db_cutoff_frequency * factor) # self.sixty_db_label.setText(NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency) + " (derived)") self.lower_sixty_db_label.setText("Not calculated") if ten_db_location > 0 and twenty_db_location > 0: octave_attenuation, decade_attenuation = self.calculateRolloff(ten_db_location, twenty_db_location) self.lower_db_per_octave_label.setText(str(round(octave_attenuation, 3)) + " dB / octave") self.lower_db_per_decade_label.setText(str(round(decade_attenuation, 3)) + " dB / decade") else: self.lower_db_per_octave_label.setText("Not calculated") self.lower_db_per_decade_label.setText("Not calculated") # Upper roll-off upper_six_db_location = -1 for i in range(upper_cutoff_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 6: # We found 6dB location upper_six_db_location = i break if upper_six_db_location < 0: self.result_label.setText("Upper 6 dB location not found.") return upper_six_db_cutoff_frequency = self.app.data21[upper_six_db_location].freq self.upper_six_db_label.setText(NanoVNASaver.formatFrequency(upper_six_db_cutoff_frequency)) six_db_span = upper_six_db_cutoff_frequency - lower_six_db_cutoff_frequency self.six_db_span_label.setText(NanoVNASaver.formatFrequency(six_db_span)) ten_db_location = -1 for i in range(upper_cutoff_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 10: # We found 6dB location ten_db_location = i break twenty_db_location = -1 for i in range(upper_cutoff_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 20: # We found 6dB location twenty_db_location = i break sixty_db_location = -1 for i in range(upper_six_db_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 60: # We found 60dB location! Wow. sixty_db_location = i break if sixty_db_location > 0: sixty_db_cutoff_frequency = self.app.data21[sixty_db_location].freq self.upper_sixty_db_label.setText(NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency)) else: # # We derive 60 dB instead # factor = 10 * (-54 / decade_attenuation) # sixty_db_cutoff_frequency = round(six_db_cutoff_frequency + six_db_cutoff_frequency * factor) # self.sixty_db_label.setText(NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency) + " (derived)") self.upper_sixty_db_label.setText("Not calculated") if ten_db_location > 0 and twenty_db_location > 0: octave_attenuation, decade_attenuation = self.calculateRolloff(ten_db_location, twenty_db_location) self.upper_db_per_octave_label.setText(str(round(octave_attenuation, 3)) + " dB / octave") self.upper_db_per_decade_label.setText(str(round(decade_attenuation, 3)) + " dB / decade") else: self.upper_db_per_octave_label.setText("Not calculated") self.upper_db_per_decade_label.setText("Not calculated") if upper_cutoff_gain < -4 or lower_cutoff_gain < -4: self.result_label.setText("Analysis complete (" + str(len(self.app.data)) + " points)\n" + "Insufficient data for analysis. Increase segment count.") else: self.result_label.setText("Analysis complete (" + str(len(self.app.data)) + " points)")
def drawValues(self, qp: QtGui.QPainter): from NanoVNASaver.NanoVNASaver import NanoVNASaver if len(self.data) == 0 and len(self.reference) == 0: return pen = QtGui.QPen(self.sweepColor) pen.setWidth(2) line_pen = QtGui.QPen(self.sweepColor) line_pen.setWidth(1) highlighter = QtGui.QPen(QtGui.QColor(20, 0, 255)) highlighter.setWidth(1) if len(self.data) > 0: fstart = self.data[0].freq fstop = self.data[len(self.data) - 1].freq else: fstart = self.reference[0].freq fstop = self.reference[len(self.reference) - 1].freq self.fstart = fstart self.fstop = fstop fspan = fstop - fstart # Find scaling minVSWR = 1 maxVSWR = 3 for d in self.data: _, _, vswr = NanoVNASaver.vswr(d) if vswr > maxVSWR: maxVSWR = vswr maxVSWR = min(25, math.ceil(maxVSWR)) span = maxVSWR - minVSWR ticksize = 1 if span > 10 and span % 5 == 0: ticksize = 5 elif span > 12 and span % 4 == 0: ticksize = 4 elif span > 8 and span % 3 == 0: ticksize = 3 elif span > 7 and span % 2 == 0: ticksize = 2 for i in range(minVSWR, maxVSWR, ticksize): y = 30 + round((maxVSWR - i) / span * (self.chartHeight - 10)) if i != minVSWR and i != maxVSWR: qp.setPen(self.textColor) qp.drawText(3, y + 3, str(i)) qp.setPen(QtGui.QPen(QtGui.QColor("lightgray"))) qp.drawLine(self.leftMargin - 5, y, self.leftMargin + self.chartWidth, y) qp.drawLine(self.leftMargin - 5, 30, self.leftMargin + self.chartWidth, 30) qp.setPen(self.textColor) qp.drawText(3, 35, str(maxVSWR)) qp.drawText(3, self.chartHeight + 20, str(minVSWR)) # At least 100 px between ticks qp.drawText(self.leftMargin - 20, 20 + self.chartHeight + 15, Chart.shortenFrequency(fstart)) ticks = math.floor(self.chartWidth / 100) # Number of ticks does not include the origin for i in range(ticks): x = self.leftMargin + round((i + 1) * self.chartWidth / ticks) qp.setPen(QtGui.QPen(QtGui.QColor("lightgray"))) qp.drawLine(x, 20, x, 20 + self.chartHeight + 5) qp.setPen(self.textColor) qp.drawText( x - 20, 20 + self.chartHeight + 15, Chart.shortenFrequency(round(fspan / ticks * (i + 1) + fstart))) if self.mouselocation != 0: qp.setPen(QtGui.QPen(QtGui.QColor(224, 224, 224))) x = self.leftMargin + 1 + round( self.chartWidth * (self.mouselocation - fstart) / fspan) qp.drawLine(x, 20, x, 20 + self.chartHeight + 5) qp.setPen(pen) for i in range(len(self.data)): _, _, vswr = NanoVNASaver.vswr(self.data[i]) x = self.leftMargin + 1 + round( self.chartWidth / len(self.data) * i) y = 30 + round((maxVSWR - vswr) / span * (self.chartHeight - 10)) if y < 30: continue qp.drawPoint(int(x), int(y)) if self.drawLines and i > 0: _, _, vswr = NanoVNASaver.vswr(self.data[i - 1]) prevx = self.leftMargin + 1 + round( self.chartWidth / len(self.data) * (i - 1)) prevy = 30 + round( (maxVSWR - vswr) / span * (self.chartHeight - 10)) if prevy < 30: continue qp.setPen(line_pen) qp.drawLine(x, y, prevx, prevy) qp.setPen(pen) pen.setColor(self.referenceColor) line_pen.setColor(self.referenceColor) qp.setPen(pen) for i in range(len(self.reference)): if self.reference[i].freq < fstart or self.reference[ i].freq > fstop: continue _, _, vswr = NanoVNASaver.vswr(self.reference[i]) x = self.leftMargin + 1 + round( self.chartWidth * (self.reference[i].freq - fstart) / fspan) y = 30 + round((maxVSWR - vswr) / span * (self.chartHeight - 10)) if y < 30: continue qp.drawPoint(int(x), int(y)) if self.drawLines and i > 0: _, _, vswr = NanoVNASaver.vswr(self.reference[i - 1]) prevx = self.leftMargin + 1 + round( self.chartWidth * (self.reference[i - 1].freq - fstart) / fspan) prevy = 30 + round( (maxVSWR - vswr) / span * (self.chartHeight - 10)) if prevy < 30: continue qp.setPen(line_pen) qp.drawLine(x, y, prevx, prevy) qp.setPen(pen) # Now draw the markers for m in self.markers: if m.location != -1: highlighter.setColor(m.color) qp.setPen(highlighter) _, _, vswr = NanoVNASaver.vswr(self.data[m.location]) x = self.leftMargin + 1 + round( self.chartWidth / len(self.data) * m.location) y = 30 + round( (maxVSWR - vswr) / span * (self.chartHeight - 10)) if y < 30: continue qp.drawLine(int(x), int(y) + 3, int(x) - 3, int(y) - 3) qp.drawLine(int(x), int(y) + 3, int(x) + 3, int(y) - 3) qp.drawLine(int(x) - 3, int(y) - 3, int(x) + 3, int(y) - 3)
def runAnalysis(self): from NanoVNASaver.NanoVNASaver import NanoVNASaver self.reset() pass_band_location = self.app.markers[0].location logger.debug("Pass band location: %d", pass_band_location) if len(self.app.data21) == 0: logger.debug("No data to analyse") self.result_label.setText("No data to analyse.") return if pass_band_location < 0: logger.debug("No location for %s", self.app.markers[0].name) self.result_label.setText("Please place " + self.app.markers[0].name + " in the passband.") return pass_band_db = NanoVNASaver.gain(self.app.data21[pass_band_location]) logger.debug("Initial passband gain: %d", pass_band_db) initial_lower_cutoff_location = -1 for i in range(pass_band_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found a cutoff location initial_lower_cutoff_location = i break if initial_lower_cutoff_location < 0: self.result_label.setText("Lower cutoff location not found.") return initial_lower_cutoff_frequency = self.app.data21[ initial_lower_cutoff_location].freq logger.debug("Found initial lower cutoff frequency at %d", initial_lower_cutoff_frequency) initial_upper_cutoff_location = -1 for i in range(pass_band_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found a cutoff location initial_upper_cutoff_location = i break if initial_upper_cutoff_location < 0: self.result_label.setText("Upper cutoff location not found.") return initial_upper_cutoff_frequency = self.app.data21[ initial_upper_cutoff_location].freq logger.debug("Found initial upper cutoff frequency at %d", initial_upper_cutoff_frequency) peak_location = -1 peak_db = NanoVNASaver.gain( self.app.data21[initial_lower_cutoff_location]) for i in range(initial_lower_cutoff_location, initial_upper_cutoff_location, 1): db = NanoVNASaver.gain(self.app.data21[i]) if db > peak_db: peak_db = db peak_location = i logger.debug("Found peak of %f at %d", peak_db, self.app.data[peak_location].freq) lower_cutoff_location = -1 pass_band_db = peak_db for i in range(peak_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found the cutoff location lower_cutoff_location = i break lower_cutoff_frequency = self.app.data21[lower_cutoff_location].freq lower_cutoff_gain = NanoVNASaver.gain( self.app.data21[lower_cutoff_location]) - pass_band_db if lower_cutoff_gain < -4: logger.debug( "Lower cutoff frequency found at %f dB - insufficient data points for true -3 dB point.", lower_cutoff_gain) logger.debug("Found true lower cutoff frequency at %d", lower_cutoff_frequency) self.lower_cutoff_label.setText( NanoVNASaver.formatFrequency(lower_cutoff_frequency) + " (" + str(round(lower_cutoff_gain, 1)) + " dB)") self.app.markers[1].setFrequency(str(lower_cutoff_frequency)) self.app.markers[1].frequencyInput.setText(str(lower_cutoff_frequency)) upper_cutoff_location = -1 pass_band_db = peak_db for i in range(peak_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found the cutoff location upper_cutoff_location = i break upper_cutoff_frequency = self.app.data21[upper_cutoff_location].freq upper_cutoff_gain = NanoVNASaver.gain( self.app.data21[upper_cutoff_location]) - pass_band_db if upper_cutoff_gain < -4: logger.debug( "Upper cutoff frequency found at %f dB - insufficient data points for true -3 dB point.", upper_cutoff_gain) logger.debug("Found true upper cutoff frequency at %d", upper_cutoff_frequency) self.upper_cutoff_label.setText( NanoVNASaver.formatFrequency(upper_cutoff_frequency) + " (" + str(round(upper_cutoff_gain, 1)) + " dB)") self.app.markers[2].setFrequency(str(upper_cutoff_frequency)) self.app.markers[2].frequencyInput.setText(str(upper_cutoff_frequency)) span = upper_cutoff_frequency - lower_cutoff_frequency center_frequency = math.sqrt(lower_cutoff_frequency * upper_cutoff_frequency) q = center_frequency / span self.span_label.setText(NanoVNASaver.formatFrequency(span)) self.center_frequency_label.setText( NanoVNASaver.formatFrequency(center_frequency)) self.quality_label.setText(str(round(q, 2))) self.app.markers[0].setFrequency(str(round(center_frequency))) self.app.markers[0].frequencyInput.setText(str( round(center_frequency))) # Lower roll-off lower_six_db_location = -1 for i in range(lower_cutoff_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 6: # We found 6dB location lower_six_db_location = i break if lower_six_db_location < 0: self.result_label.setText("Lower 6 dB location not found.") return lower_six_db_cutoff_frequency = self.app.data21[ lower_six_db_location].freq self.lower_six_db_label.setText( NanoVNASaver.formatFrequency(lower_six_db_cutoff_frequency)) ten_db_location = -1 for i in range(lower_cutoff_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 10: # We found 6dB location ten_db_location = i break twenty_db_location = -1 for i in range(lower_cutoff_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 20: # We found 6dB location twenty_db_location = i break sixty_db_location = -1 for i in range(lower_six_db_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 60: # We found 60dB location! Wow. sixty_db_location = i break if sixty_db_location > 0: if sixty_db_location > 0: sixty_db_cutoff_frequency = self.app.data21[ sixty_db_location].freq self.lower_sixty_db_label.setText( NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency)) elif ten_db_location != -1 and twenty_db_location != -1: ten = self.app.data21[ten_db_location].freq twenty = self.app.data21[twenty_db_location].freq sixty_db_frequency = ten * 10**( 5 * (math.log10(twenty) - math.log10(ten))) self.lower_sixty_db_label.setText( NanoVNASaver.formatFrequency(sixty_db_frequency) + " (derived)") else: self.lower_sixty_db_label.setText("Not calculated") if ten_db_location > 0 and twenty_db_location > 0 and ten_db_location != twenty_db_location: octave_attenuation, decade_attenuation = self.calculateRolloff( ten_db_location, twenty_db_location) self.lower_db_per_octave_label.setText( str(round(octave_attenuation, 3)) + " dB / octave") self.lower_db_per_decade_label.setText( str(round(decade_attenuation, 3)) + " dB / decade") else: self.lower_db_per_octave_label.setText("Not calculated") self.lower_db_per_decade_label.setText("Not calculated") # Upper roll-off upper_six_db_location = -1 for i in range(upper_cutoff_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 6: # We found 6dB location upper_six_db_location = i break if upper_six_db_location < 0: self.result_label.setText("Upper 6 dB location not found.") return upper_six_db_cutoff_frequency = self.app.data21[ upper_six_db_location].freq self.upper_six_db_label.setText( NanoVNASaver.formatFrequency(upper_six_db_cutoff_frequency)) six_db_span = upper_six_db_cutoff_frequency - lower_six_db_cutoff_frequency self.six_db_span_label.setText( NanoVNASaver.formatFrequency(six_db_span)) ten_db_location = -1 for i in range(upper_cutoff_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 10: # We found 6dB location ten_db_location = i break twenty_db_location = -1 for i in range(upper_cutoff_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 20: # We found 6dB location twenty_db_location = i break sixty_db_location = -1 for i in range(upper_six_db_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 60: # We found 60dB location! Wow. sixty_db_location = i break if sixty_db_location > 0: sixty_db_cutoff_frequency = self.app.data21[sixty_db_location].freq self.upper_sixty_db_label.setText( NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency)) elif ten_db_location != -1 and twenty_db_location != -1: ten = self.app.data21[ten_db_location].freq twenty = self.app.data21[twenty_db_location].freq sixty_db_frequency = ten * 10**( 5 * (math.log10(twenty) - math.log10(ten))) self.upper_sixty_db_label.setText( NanoVNASaver.formatFrequency(sixty_db_frequency) + " (derived)") else: self.upper_sixty_db_label.setText("Not calculated") if ten_db_location > 0 and twenty_db_location > 0 and ten_db_location != twenty_db_location: octave_attenuation, decade_attenuation = self.calculateRolloff( ten_db_location, twenty_db_location) self.upper_db_per_octave_label.setText( str(round(octave_attenuation, 3)) + " dB / octave") self.upper_db_per_decade_label.setText( str(round(decade_attenuation, 3)) + " dB / decade") else: self.upper_db_per_octave_label.setText("Not calculated") self.upper_db_per_decade_label.setText("Not calculated") if upper_cutoff_gain < -4 or lower_cutoff_gain < -4: self.result_label.setText( "Analysis complete (" + str(len(self.app.data)) + " points)\n" + "Insufficient data for analysis. Increase segment count.") else: self.result_label.setText("Analysis complete (" + str(len(self.app.data)) + " points)")
def runAnalysis(self): from NanoVNASaver.NanoVNASaver import NanoVNASaver self.reset() pass_band_location = self.app.markers[0].location logger.debug("Pass band location: %d", pass_band_location) if len(self.app.data21) == 0: logger.debug("No data to analyse") self.result_label.setText("No data to analyse.") return if pass_band_location < 0: logger.debug("No location for %s", self.app.markers[0].name) self.result_label.setText("Please place " + self.app.markers[0].name + " in the passband.") return pass_band_db = NanoVNASaver.gain(self.app.data21[pass_band_location]) logger.debug("Initial passband gain: %d", pass_band_db) initial_lower_cutoff_location = -1 for i in range(pass_band_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found a cutoff location initial_lower_cutoff_location = i break if initial_lower_cutoff_location < 0: self.result_label.setText("Lower cutoff location not found.") return initial_lower_cutoff_frequency = self.app.data21[ initial_lower_cutoff_location].freq logger.debug("Found initial lower cutoff frequency at %d", initial_lower_cutoff_frequency) initial_upper_cutoff_location = -1 for i in range(pass_band_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found a cutoff location initial_upper_cutoff_location = i break if initial_upper_cutoff_location < 0: self.result_label.setText("Upper cutoff location not found.") return initial_upper_cutoff_frequency = self.app.data21[ initial_upper_cutoff_location].freq logger.debug("Found initial upper cutoff frequency at %d", initial_upper_cutoff_frequency) peak_location = -1 peak_db = NanoVNASaver.gain( self.app.data21[initial_lower_cutoff_location]) for i in range(initial_lower_cutoff_location, initial_upper_cutoff_location, 1): db = NanoVNASaver.gain(self.app.data21[i]) if db > peak_db: peak_db = db peak_location = i logger.debug("Found peak of %f at %d", peak_db, self.app.data[peak_location].freq) lower_cutoff_location = -1 pass_band_db = peak_db for i in range(peak_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found the cutoff location lower_cutoff_location = i break lower_cutoff_frequency = self.app.data21[lower_cutoff_location].freq lower_cutoff_gain = NanoVNASaver.gain( self.app.data21[lower_cutoff_location]) - pass_band_db if lower_cutoff_gain < -4: logger.debug( "Lower cutoff frequency found at %f dB - insufficient data points for true -3 dB point.", lower_cutoff_gain) logger.debug("Found true lower cutoff frequency at %d", lower_cutoff_frequency) self.lower_cutoff_label.setText( NanoVNASaver.formatFrequency(lower_cutoff_frequency) + " (" + str(round(lower_cutoff_gain, 1)) + " dB)") self.app.markers[1].setFrequency(str(lower_cutoff_frequency)) self.app.markers[1].frequencyInput.setText(str(lower_cutoff_frequency)) upper_cutoff_location = -1 pass_band_db = peak_db for i in range(peak_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 3: # We found the cutoff location upper_cutoff_location = i break upper_cutoff_frequency = self.app.data21[upper_cutoff_location].freq upper_cutoff_gain = NanoVNASaver.gain( self.app.data21[upper_cutoff_location]) - pass_band_db if upper_cutoff_gain < -4: logger.debug( "Upper cutoff frequency found at %f dB - insufficient data points for true -3 dB point.", upper_cutoff_gain) logger.debug("Found true upper cutoff frequency at %d", upper_cutoff_frequency) self.upper_cutoff_label.setText( NanoVNASaver.formatFrequency(upper_cutoff_frequency) + " (" + str(round(upper_cutoff_gain, 1)) + " dB)") self.app.markers[2].setFrequency(str(upper_cutoff_frequency)) self.app.markers[2].frequencyInput.setText(str(upper_cutoff_frequency)) span = upper_cutoff_frequency - lower_cutoff_frequency center_frequency = math.sqrt(lower_cutoff_frequency * upper_cutoff_frequency) q = center_frequency / span self.span_label.setText(NanoVNASaver.formatFrequency(span)) self.center_frequency_label.setText( NanoVNASaver.formatFrequency(center_frequency)) self.quality_label.setText(str(round(q, 2))) self.app.markers[0].setFrequency(str(round(center_frequency))) self.app.markers[0].frequencyInput.setText(str( round(center_frequency))) # Lower roll-off lower_six_db_location = -1 for i in range(lower_cutoff_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 6: # We found 6dB location lower_six_db_location = i break if lower_six_db_location < 0: self.result_label.setText("Lower 6 dB location not found.") return lower_six_db_cutoff_frequency = self.app.data21[ lower_six_db_location].freq self.lower_six_db_label.setText( NanoVNASaver.formatFrequency(lower_six_db_cutoff_frequency)) lower_six_db_attenuation = NanoVNASaver.gain( self.app.data21[lower_six_db_location]) lower_max_attenuation = NanoVNASaver.gain(self.app.data21[0]) frequency_factor = self.app.data21[ 0].freq / lower_six_db_cutoff_frequency lower_attenuation = (lower_max_attenuation - lower_six_db_attenuation) logger.debug("Measured points: %d Hz and %d Hz", lower_six_db_cutoff_frequency, self.app.data21[0].freq) logger.debug("%d dB over %f factor", lower_attenuation, frequency_factor) octave_attenuation = lower_attenuation / ( math.log10(frequency_factor) / math.log10(2)) self.lower_db_per_octave_label.setText( str(round(octave_attenuation, 3)) + " dB / octave") decade_attenuation = lower_attenuation / math.log10(frequency_factor) self.lower_db_per_decade_label.setText( str(round(decade_attenuation, 3)) + " dB / decade") lower_sixty_db_location = -1 for i in range(lower_six_db_location, -1, -1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 60: # We found 60dB location! Wow. lower_sixty_db_location = i break if lower_sixty_db_location < 0: # # We derive 60 dB instead # factor = 10 * (-54 / decade_attenuation) # sixty_db_cutoff_frequency = round(six_db_cutoff_frequency + six_db_cutoff_frequency * factor) # self.upper_sixty_db_label.setText(NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency) + " (derived)") self.lower_sixty_db_label.setText("Not calculated") else: lower_sixty_db_cutoff_frequency = self.app.data21[ lower_sixty_db_location].freq self.lower_sixty_db_label.setText( NanoVNASaver.formatFrequency(lower_sixty_db_cutoff_frequency)) # Upper roll-off upper_six_db_location = -1 for i in range(upper_cutoff_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 6: # We found 6dB location upper_six_db_location = i break if upper_six_db_location < 0: self.result_label.setText("Upper 6 dB location not found.") return upper_six_db_cutoff_frequency = self.app.data21[ upper_six_db_location].freq self.upper_six_db_label.setText( NanoVNASaver.formatFrequency(upper_six_db_cutoff_frequency)) upper_six_db_attenuation = NanoVNASaver.gain( self.app.data21[upper_six_db_location]) upper_max_attenuation = NanoVNASaver.gain(self.app.data21[0]) frequency_factor = self.app.data21[ 0].freq / upper_six_db_cutoff_frequency upper_attenuation = (upper_max_attenuation - upper_six_db_attenuation) logger.debug("Measured points: %d Hz and %d Hz", upper_six_db_cutoff_frequency, self.app.data21[0].freq) logger.debug("%d dB over %f factor", upper_attenuation, frequency_factor) octave_attenuation = upper_attenuation / ( math.log10(frequency_factor) / math.log10(2)) self.upper_db_per_octave_label.setText( str(round(octave_attenuation, 3)) + " dB / octave") decade_attenuation = upper_attenuation / math.log10(frequency_factor) self.upper_db_per_decade_label.setText( str(round(decade_attenuation, 3)) + " dB / decade") upper_sixty_db_location = -1 for i in range(upper_six_db_location, len(self.app.data21), 1): db = NanoVNASaver.gain(self.app.data21[i]) if (pass_band_db - db) > 60: # We found 60dB location! Wow. upper_sixty_db_location = i break if upper_sixty_db_location < 0: # # We derive 60 dB instead # factor = 10 * (-54 / decade_attenuation) # sixty_db_cutoff_frequency = round(six_db_cutoff_frequency + six_db_cutoff_frequency * factor) # self.upper_sixty_db_label.setText(NanoVNASaver.formatFrequency(sixty_db_cutoff_frequency) + " (derived)") self.upper_sixty_db_label.setText("Not calculated") else: upper_sixty_db_cutoff_frequency = self.app.data21[ upper_sixty_db_location].freq self.upper_sixty_db_label.setText( NanoVNASaver.formatFrequency(upper_sixty_db_cutoff_frequency)) if upper_cutoff_gain < -4 or lower_cutoff_gain < -4: self.result_label.setText( "Analysis complete (" + str(len(self.app.data)) + " points)\n" + "Insufficient data for analysis. Increase segment count.") else: self.result_label.setText("Analysis complete (" + str(len(self.app.data)) + " points)")