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)")
Beispiel #4
0
    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}")