コード例 #1
0
    def runAnalysis(self):
        if self.rbtn_data_vswr.isChecked():
            suffix = ""
            data = []
            for d in self.app.data11:
                data.append(d.vswr)
        elif self.rbtn_data_resistance.isChecked():
            suffix = " \N{OHM SIGN}"
            data = []
            for d in self.app.data11:
                data.append(d.impedance().real)
        elif self.rbtn_data_reactance.isChecked():
            suffix = " \N{OHM SIGN}"
            data = []
            for d in self.app.data11:
                data.append(d.impedance().imag)
        elif self.rbtn_data_s21_gain.isChecked():
            suffix = " dB"
            data = []
            for d in self.app.data21:
                data.append(d.gain)
        else:
            logger.warning("Searching for peaks on unknown data")
            return

        if len(data) == 0:
            return

        if self.rbtn_peak_positive.isChecked():
            idx_peak = np.argmax(data)
        elif self.rbtn_peak_negative.isChecked():
            idx_peak = np.argmin(data)
        else:
            # Both is not yet in
            logger.warning("Searching for peaks,"
                           " but neither looking at positive nor negative?")
            return

        self.peak_frequency.setText(
            format_frequency(self.app.data11[idx_peak].freq))
        self.peak_value.setText(str(round(data[idx_peak], 3)) + suffix)

        if self.checkbox_move_marker.isChecked() and len(
                self.app.markers) >= 1:
            self.app.markers[0].setFrequency(
                str(self.app.data11[idx_peak].freq))
            self.app.markers[0].frequencyInput.setText(
                format_frequency(self.app.data11[idx_peak].freq))
コード例 #2
0
ファイル: Widget.py プロジェクト: Lusitanv/nanovna-saver
    def updateLabels(self,
                     s11data: List[RFTools.Datapoint],
                     s21data: List[RFTools.Datapoint]):
        if self.location == -1:
            return
        self.store(self.location, s11data, s21data)

        s11 = s11data[self.location]

        imp = s11.impedance()
        cap_str = format_capacitance(RFTools.impedance_to_capacitance(imp, s11.freq))
        ind_str = format_inductance(RFTools.impedance_to_inductance(imp, s11.freq))

        imp_p = RFTools.serial_to_parallel(imp)
        cap_p_str = format_capacitance(RFTools.impedance_to_capacitance(imp_p, s11.freq))
        ind_p_str = format_inductance(RFTools.impedance_to_inductance(imp_p, s11.freq))

        if imp.imag < 0:
            x_str = cap_str
        else:
            x_str = ind_str

        if imp_p.imag < 0:
            x_p_str = cap_p_str
        else:
            x_p_str = ind_p_str

        self.label['actualfreq'].setText(format_frequency(s11.freq))
        self.label['admittance'].setText(format_complex_imp(imp_p))
        self.label['impedance'].setText(format_complex_imp(imp))
        self.label['parc'].setText(cap_p_str)
        self.label['parl'].setText(ind_p_str)
        self.label['parlc'].setText(x_p_str)
        self.label['parr'].setText(format_resistance(imp_p.real))
        self.label['returnloss'].setText(
            format_gain(s11.gain, self.returnloss_is_positive))
        self.label['s11groupdelay'].setText(
            format_group_delay(RFTools.groupDelay(s11data, self.location)))
        self.label['s11mag'].setText(format_magnitude(abs(s11.z)))
        self.label['s11phase'].setText(format_phase(s11.phase))
        self.label['s11polar'].setText(
            str(round(abs(s11.z), 2)) + "∠" + format_phase(s11.phase))
        self.label['s11q'].setText(format_q_factor(s11.qFactor()))
        self.label['s11z'].setText(format_resistance(abs(imp)))
        self.label['serc'].setText(cap_str)
        self.label['serl'].setText(ind_str)
        self.label['serlc'].setText(x_str)
        self.label['serr'].setText(format_resistance(imp.real))
        self.label['vswr'].setText(format_vswr(s11.vswr))

        if len(s21data) == len(s11data):
            s21 = s21data[self.location]
            self.label['s21gain'].setText(format_gain(s21.gain))
            self.label['s21groupdelay'].setText(
                format_group_delay(RFTools.groupDelay(s21data, self.location) / 2))
            self.label['s21mag'].setText(format_magnitude(abs(s21.z)))
            self.label['s21phase'].setText(format_phase(s21.phase))
            self.label['s21polar'].setText(
                str(round(abs(s21.z), 2)) + "∠" + format_phase(s21.phase))
コード例 #3
0
    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.data.s21) == 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(
                f"Please place {self.app.markers[0].name} in the passband.")
            return

        pass_band_db = self.app.data.s21[pass_band_location].gain

        logger.debug("Initial passband gain: %d", pass_band_db)

        initial_cutoff_location = -1
        for i in range(pass_band_location, len(self.app.data.s21)):
            db = self.app.data.s21[i].gain
            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.data.s21[initial_cutoff_location].freq

        logger.debug("Found initial cutoff frequency at %d", initial_cutoff_frequency)

        peak_location = -1
        peak_db = self.app.data.s21[initial_cutoff_location].gain
        for i in range(0, initial_cutoff_location):
            db = self.app.data.s21[i].gain
            if db > peak_db:
                peak_db = db
                peak_location = i

        logger.debug("Found peak of %f at %d", peak_db, self.app.data.s11[peak_location].freq)

        self.app.markers[0].setFrequency(str(self.app.data.s21[peak_location].freq))
        self.app.markers[0].frequencyInput.setText(str(self.app.data.s21[peak_location].freq))

        cutoff_location = -1
        pass_band_db = peak_db
        for i in range(peak_location, len(self.app.data.s21)):
            db = self.app.data.s21[i].gain
            if (pass_band_db - db) > 3:
                # We found the cutoff location
                cutoff_location = i
                break

        cutoff_frequency = self.app.data.s21[cutoff_location].freq
        cutoff_gain = self.app.data.s21[cutoff_location].gain - 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(
            f"{format_frequency(cutoff_frequency)}"
            f" ({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.data.s21)):
            db = self.app.data.s21[i].gain
            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.data.s21[six_db_location].freq
        self.six_db_label.setText(
            format_frequency(six_db_cutoff_frequency))

        ten_db_location = -1
        for i in range(cutoff_location, len(self.app.data.s21)):
            db = self.app.data.s21[i].gain
            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.data.s21)):
            db = self.app.data.s21[i].gain
            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.data.s21)):
            db = self.app.data.s21[i].gain
            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.data.s21[sixty_db_location].freq
            self.sixty_db_label.setText(
                format_frequency(sixty_db_cutoff_frequency))
        elif ten_db_location != -1 and twenty_db_location != -1:
            ten = self.app.data.s21[ten_db_location].freq
            twenty = self.app.data.s21[twenty_db_location].freq
            sixty_db_frequency = ten * \
                10 ** (5 * (math.log10(twenty) - math.log10(ten)))
            self.sixty_db_label.setText(
                f"{format_frequency(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.s11)) + " points)")
コード例 #4
0
    def runAnalysis(self):
        max_dips_shown = self.max_dips_shown

        data = [d.vswr for d in self.app.data.s11]

        # min_idx = np.argmin(data)
        #
        # logger.debug("Minimum at %d", min_idx)
        # logger.debug("Value at minimum: %f", data[min_idx])
        # logger.debug("Frequency: %d", self.app.data.s11[min_idx].freq)
        #
        # if self.checkbox_move_marker.isChecked():
        #     self.app.markers[0].setFrequency(str(self.app.data.s11[min_idx].freq))
        #     self.app.markers[0].frequencyInput.setText(str(self.app.data.s11[min_idx].freq))

        threshold = self.input_vswr_limit.value()
        minimums = self.find_minimums(data, threshold)

        logger.debug("Found %d sections under %f threshold", len(minimums),
                     threshold)

        results_header = self.layout.indexOf(self.results_label)
        logger.debug("Results start at %d, out of %d", results_header,
                     self.layout.rowCount())
        for _ in range(results_header, self.layout.rowCount()):
            self.layout.removeRow(self.layout.rowCount() - 1)

        if len(minimums) > max_dips_shown:
            self.layout.addRow(
                QtWidgets.QLabel("<b>More than " + str(max_dips_shown) +
                                 " dips found. Lowest shown.</b>"))
            dips = []
            for m in minimums:
                start, lowest, end = m
                dips.append(data[lowest])

            best_dips = []
            for _ in range(max_dips_shown):
                min_idx = np.argmin(dips)
                best_dips.append(minimums[min_idx])
                dips.remove(dips[min_idx])
                minimums.remove(minimums[min_idx])
            minimums = best_dips
        self.minimums = minimums
        if len(minimums) > 0:
            for m in minimums:
                start, lowest, end = m
                if start != end:
                    logger.debug("Section from %d to %d, lowest at %d", start,
                                 end, lowest)
                    self.layout.addRow(
                        "Start",
                        QtWidgets.QLabel(
                            format_frequency(self.app.data.s11[start].freq)))
                    self.layout.addRow(
                        "Minimum",
                        QtWidgets.QLabel(
                            f"{format_frequency(self.app.data.s11[lowest].freq)}"
                            f" ({round(data[lowest], 2)})"))
                    self.layout.addRow(
                        "End",
                        QtWidgets.QLabel(
                            format_frequency(self.app.data.s11[end].freq)))
                    self.layout.addRow(
                        "Span",
                        QtWidgets.QLabel(
                            format_frequency(self.app.data.s11[end].freq -
                                             self.app.data.s11[start].freq)))
                else:
                    self.layout.addRow(
                        "Low spot",
                        QtWidgets.QLabel(
                            format_frequency(self.app.data.s11[lowest].freq)))
                self.layout.addWidget(PeakSearchAnalysis.QHLine())
            # Remove the final separator line
            self.layout.removeRow(self.layout.rowCount() - 1)
        else:
            self.layout.addRow(
                QtWidgets.QLabel("No areas found with VSWR below " +
                                 str(round(threshold, 2)) + "."))
コード例 #5
0
    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.debug("may be the same antenna ... analyzing")

        else:
            logger.warning("resonances changed from %s to %s", len(old_idx),
                           len(new_idx))

            logger.debug("Trying to compare only first %s resonances", i_max)

        split = 0
        max_delta_f = 1000000  # 1M
        for i, k in enumerate(new_idx):
            my_diff = {}

            logger.info("Risonance %s at %s", i,
                        format_frequency(new[k]["freq"]))

            if len(old_idx) <= i + split:
                diff[i] = no_compare()
                continue

            delta_f = new[k]["freq"] - old[old_idx[i + split]]["freq"]
            if abs(delta_f) < max_delta_f:
                logger.debug("can compare")

            else:
                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 ?!?
                        else:
                            logger.debug("new band, non compare ")
                            diff[i] = no_compare()
                            continue
                else:
                    logger.debug("new band, non compare ")
                    diff[i] = no_compare()

                    split -= 1
                    continue

            for d, fn in fields:
                my_diff[d] = fn(new[k][d] - old[old_idx[i + split]][d])
                logger.info("Delta %s =  %s", d, my_diff[d])

            diff[i] = my_diff

        for i in range(i_max, i_tot):
            # add missing in old ... if any

            diff[i] = no_compare()

        return diff
コード例 #6
0
    def runAnalysis(self):
        self.reset()
        # self.results_label = QtWidgets.QLabel("<b>Results</b>")
        # max_dips_shown = self.max_dips_shown
        description = self.input_description.text()
        if description:
            filename = os.path.join("/tmp/", "{}.csv".format(description))
        else:
            filename = None

        crossing = self._get_crossing()

        logger.debug("Found %d sections ", len(crossing))

        results_header = self.layout.indexOf(self.results_label)
        logger.debug("Results start at %d, out of %d", results_header,
                     self.layout.rowCount())
        for _ in range(results_header, self.layout.rowCount()):
            self.layout.removeRow(self.layout.rowCount() - 1)


#         if len(crossing) > max_dips_shown:
#             self.layout.addRow(QtWidgets.QLabel("<b>More than " + str(max_dips_shown) +
#                                                 " dips found. Lowest shown.</b>"))
#         self.crossing = crossing[:max_dips_shown]
        if len(crossing) > 0:
            extended_data = []
            for m in crossing:
                start, lowest, end = m
                my_data = self._get_data(lowest)

                extended_data.append(my_data)
                if start != end:
                    logger.debug("Section from %d to %d, lowest at %d", start,
                                 end, lowest)

                    self.layout.addRow(
                        "Resonance",
                        QtWidgets.QLabel(
                            f"{format_frequency(self.app.data.s11[lowest].freq)}"
                            f" ({format_complex_imp(self.app.data.s11[lowest].impedance())})"
                        ))
                else:
                    self.layout.addRow(
                        "Resonance",
                        QtWidgets.QLabel(
                            format_frequency(self.app.data.s11[lowest].freq)))
                    self.layout.addWidget(PeakSearchAnalysis.QHLine())
            # Remove the final separator line
            self.layout.removeRow(self.layout.rowCount() - 1)
            if filename and extended_data:

                with open(filename, 'w', newline='') as csvfile:
                    fieldnames = extended_data[0].keys()
                    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

                    writer.writeheader()
                    for row in extended_data:
                        writer.writerow(row)

        else:
            self.layout.addRow(QtWidgets.QLabel("No resonance found"))
コード例 #7
0
    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(
                f"Please place {self.app.markers[0].name} in the passband.")
            return

        pass_band_db = self.app.data21[pass_band_location].gain

        logger.debug("Initial passband gain: %d", pass_band_db)

        initial_lower_cutoff_location = -1
        for i in range(pass_band_location, -1, -1):
            if (pass_band_db - self.app.data21[i].gain) > 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):
            if (pass_band_db - self.app.data21[i].gain) > 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 = self.app.data21[initial_lower_cutoff_location].gain
        for i in range(initial_lower_cutoff_location, initial_upper_cutoff_location, 1):
            db = self.app.data21[i].gain
            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):
            if (pass_band_db - self.app.data21[i].gain) > 3:
                # We found the cutoff location
                lower_cutoff_location = i
                break

        lower_cutoff_frequency = self.app.data21[lower_cutoff_location].freq
        lower_cutoff_gain = self.app.data21[lower_cutoff_location].gain - 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(
            f"{format_frequency(lower_cutoff_frequency)}"
            f" ({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):
            if (pass_band_db - self.app.data21[i].gain) > 3:
                # We found the cutoff location
                upper_cutoff_location = i
                break

        upper_cutoff_frequency = self.app.data21[upper_cutoff_location].freq
        upper_cutoff_gain = self.app.data21[upper_cutoff_location].gain - 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(
            f"{format_frequency(upper_cutoff_frequency)}"
            f" ({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(format_frequency(span))
        self.center_frequency_label.setText(
            format_frequency(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):
            if (pass_band_db - self.app.data21[i].gain) > 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(
            format_frequency(lower_six_db_cutoff_frequency))

        ten_db_location = -1
        for i in range(lower_cutoff_location, -1, -1):
            if (pass_band_db - self.app.data21[i].gain) > 10:
                # We found 6dB location
                ten_db_location = i
                break

        twenty_db_location = -1
        for i in range(lower_cutoff_location, -1, -1):
            if (pass_band_db - self.app.data21[i].gain) > 20:
                # We found 6dB location
                twenty_db_location = i
                break

        sixty_db_location = -1
        for i in range(lower_six_db_location, -1, -1):
            if (pass_band_db - self.app.data21[i].gain) > 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(
                    format_frequency(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(
                    f"{format_frequency(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):
            if (pass_band_db - self.app.data21[i].gain) > 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(
            format_frequency(upper_six_db_cutoff_frequency))

        six_db_span = upper_six_db_cutoff_frequency - lower_six_db_cutoff_frequency

        self.six_db_span_label.setText(
            format_frequency(six_db_span))

        ten_db_location = -1
        for i in range(upper_cutoff_location, len(self.app.data21), 1):
            if (pass_band_db - self.app.data21[i].gain) > 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):
            if (pass_band_db - self.app.data21[i].gain) > 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):
            if (pass_band_db - self.app.data21[i].gain) > 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(
                format_frequency(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(
                f"{format_frequency(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(
                f"{round(octave_attenuation, 3)} dB / octave")
            self.upper_db_per_decade_label.setText(
                f"{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(
                f"Analysis complete ({len(self.app.data)} points)\n"
                f"Insufficient data for analysis. Increase segment count.")
        else:
            self.result_label.setText(
                f"Analysis complete ({len(self.app.data)} points)")