def calculateRolloff(self, location1, location2): if location1 == location2: return 0, 0 frequency1 = self.app.data21[location1].freq frequency2 = self.app.data21[location2].freq gain1 = RFTools.gain(self.app.data21[location1]) gain2 = RFTools.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 runAnalysis(self): 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 = RFTools.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 = RFTools.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 = RFTools.gain(self.app.data21[initial_cutoff_location]) for i in range(0, initial_cutoff_location): db = RFTools.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 = RFTools.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 = RFTools.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( RFTools.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 = RFTools.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( RFTools.formatFrequency(six_db_cutoff_frequency)) ten_db_location = -1 for i in range(cutoff_location, len(self.app.data21)): db = RFTools.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 = RFTools.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 = RFTools.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( RFTools.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.sixty_db_label.setText( RFTools.formatFrequency(sixty_db_frequency) + " (derived)") else: self.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.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): 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 = RFTools.gain(self.app.data21[0]) for i in range(len(self.app.data21)): db = RFTools.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 = RFTools.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 = RFTools.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( RFTools.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 = RFTools.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 = RFTools.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( RFTools.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(RFTools.formatFrequency(span)) self.center_frequency_label.setText( RFTools.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 = RFTools.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( RFTools.formatFrequency(lower_six_db_cutoff_frequency)) ten_db_location = -1 for i in range(lower_cutoff_location, len(self.app.data21)): db = RFTools.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 = RFTools.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 = RFTools.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( RFTools.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( RFTools.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, -1, -1): db = RFTools.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( RFTools.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(RFTools.formatFrequency(six_db_span)) ten_db_location = -1 for i in range(upper_cutoff_location, -1, -1): db = RFTools.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 = RFTools.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 = RFTools.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( RFTools.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( RFTools.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 updateLabels(self, s11data: List[Datapoint], s21data: List[Datapoint]): if self.location != -1: re50, im50 = RFTools.normalize50(s11data[self.location]) vswr = RFTools.calculateVSWR(s11data[self.location]) if re50 > 0: rp = (re50**2 + im50**2) / re50 rp = round(rp, 3 - max(0, math.floor(math.log10(abs(rp))))) if rp > 10000: rpstr = str(round(rp / 1000, 2)) + "k" elif rp > 1000: rpstr = str(round(rp)) else: rpstr = str(rp) re50 = round(re50, 3 - max(0, math.floor(math.log10(abs(re50))))) if re50 > 10000: re50str = str(round(re50 / 1000, 2)) + "k" elif re50 > 1000: re50str = str(round(re50)) # Remove the ".0" else: re50str = str(re50) else: rpstr = "-" re50 = 0 re50str = "-" if im50 != 0: xp = (re50**2 + im50**2) / im50 xp = round(xp, 3 - max(0, math.floor(math.log10(abs(xp))))) xpcstr = RFTools.capacitanceEquivalent( xp, s11data[self.location].freq) xplstr = RFTools.inductanceEquivalent( xp, s11data[self.location].freq) if xp < 0: xpstr = xpcstr xp50str = " -j" + str(-1 * xp) else: xpstr = xplstr xp50str = " +j" + str(xp) xp50str += " \N{OHM SIGN}" else: xp50str = " +j ? \N{OHM SIGN}" xpstr = xpcstr = xplstr = "-" if im50 != 0: im50 = round(im50, 3 - max(0, math.floor(math.log10(abs(im50))))) if im50 < 0: im50str = " -j" + str(-1 * im50) else: im50str = " +j" + str(im50) im50str += " \N{OHM SIGN}" self.frequency_label.setText( RFTools.formatFrequency(s11data[self.location].freq)) self.impedance_label.setText(re50str + im50str) self.admittance_label.setText(rpstr + xp50str) self.series_r_label.setText(re50str + " \N{OHM SIGN}") self.parallel_r_label.setText(rpstr + " \N{OHM SIGN}") self.parallel_x_label.setText(xpstr) if self.returnloss_is_positive: returnloss = -round(RFTools.gain(s11data[self.location]), 3) else: returnloss = round(RFTools.gain(s11data[self.location]), 3) self.returnloss_label.setText(str(returnloss) + " dB") capacitance = RFTools.capacitanceEquivalent( im50, s11data[self.location].freq) inductance = RFTools.inductanceEquivalent( im50, s11data[self.location].freq) self.inductance_label.setText(inductance) self.capacitance_label.setText(capacitance) self.parallel_c_label.setText(xpcstr) self.parallel_l_label.setText(xplstr) if im50 > 0: self.series_lc_label.setText(inductance) else: self.series_lc_label.setText(capacitance) vswr = round(vswr, 3) if vswr < 0: vswr = "-" self.vswr_label.setText(str(vswr)) q = RFTools.qualityFactor(s11data[self.location]) if q > 10000 or q < 0: q_str = "\N{INFINITY}" elif q > 1000: q_str = str(round(q, 0)) elif q > 100: q_str = str(round(q, 1)) elif q > 10: q_str = str(round(q, 2)) else: q_str = str(round(q, 3)) self.quality_factor_label.setText(q_str) self.s11_phase_label.setText( str(round(RFTools.phaseAngle(s11data[self.location]), 2)) + "\N{DEGREE SIGN}") if len(s21data) == len(s11data): self.gain_label.setText( str(round(RFTools.gain(s21data[self.location]), 3)) + " dB") self.s21_phase_label.setText( str(round(RFTools.phaseAngle(s21data[self.location]), 2)) + "\N{DEGREE SIGN}")