def test_fir_filter(self): input_signal = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 42], dtype=np.complex64) filter_taps = [0.25, 0.25, 0.25, 0.25] fir_filter = Filter(filter_taps) filtered_signal = fir_filter.apply_fir_filter(input_signal) expected_filtered_signal = np.array([0.25, 0.75, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 16.5], dtype=np.complex64) self.assertTrue(np.array_equal(filtered_signal, expected_filtered_signal))
def build_filter(self) -> Filter: if self.ui.radioButtonMovingAverage.isChecked(): n = self.ui.spinBoxNumTaps.value() return Filter([1/n for _ in range(n)], filter_type=FilterType.moving_average) else: # custom filter try: taps = eval(self.ui.lineEditCustomTaps.text()) try: taps = list(map(float, taps)) self.error_message = "" return Filter(taps) except (ValueError, TypeError) as e: self.error_message = "Error casting taps:\n" + str(e) return None except SyntaxError as e: self.error_message = "Error parsing taps:\n" + str(e) return None
def test_fsk_live_capture(self): data = Signal(get_path_for_data_file("fsk_live.coco"), "").data n = 10 moving_average_filter = Filter([1 / n for _ in range(n)], filter_type=FilterType.moving_average) filtered_data = moving_average_filter.apply_fir_filter(data) rect = afp_demod(filtered_data, 0.0175, 1) center = detect_center(rect) self.assertGreaterEqual(center, -0.0148, msg="Filtered") self.assertLessEqual(center, 0.01, msg="Filtered") rect = afp_demod(data, 0.0175, 1) center = detect_center(rect) self.assertGreaterEqual(center, -0.02, msg="Original") self.assertLessEqual(center, 0.01, msg="Original")
def test_fsk_live_capture(self): data = Signal(get_path_for_data_file("fsk_live.coco"), "").iq_array.data n = 10 moving_average_filter = Filter([1 / n for _ in range(n)], filter_type=FilterType.moving_average) filtered_data = moving_average_filter.apply_fir_filter( data.flatten()).view(np.float32) filtered_data = filtered_data.reshape((len(filtered_data) // 2, 2)) rect = afp_demod(filtered_data, 0.0175, "FSK", 2) center = detect_center(rect) self.assertGreaterEqual(center, -0.0148, msg="Filtered") self.assertLessEqual(center, 0.01, msg="Filtered") rect = afp_demod(data, 0.0175, "FSK", 2) center = detect_center(rect) self.assertGreaterEqual(center, -0.02, msg="Original") self.assertLessEqual(center, 0.01, msg="Original")
def __init__(self, proto_analyzer: ProtocolAnalyzer, undo_stack: QUndoStack, project_manager, proto_bits=None, parent=None): super().__init__(parent) self.undo_stack = undo_stack self.ui = Ui_SignalFrame() self.ui.setupUi(self) fixed_font = QFontDatabase.systemFont(QFontDatabase.FixedFont) fixed_font.setPointSize(QApplication.instance().font().pointSize()) self.ui.txtEdProto.setFont(fixed_font) self.ui.txtEdProto.participants = project_manager.participants self.ui.txtEdProto.messages = proto_analyzer.messages self.ui.gvSignal.participants = project_manager.participants self.setAttribute(Qt.WA_DeleteOnClose) self.project_manager = project_manager self.proto_analyzer = proto_analyzer self.signal = proto_analyzer.signal if self.proto_analyzer is not None else None # type: Signal self.dsp_filter = Filter([0.1] * 10, FilterType.moving_average) self.set_filter_button_caption() self.filter_dialog = FilterDialogController(self.dsp_filter, parent=self) self.proto_selection_timer = QTimer( ) # For Update Proto Selection from ROI self.proto_selection_timer.setSingleShot(True) self.proto_selection_timer.setInterval(1) # Disabled because never used (see also set_protocol_visibilty()) self.ui.chkBoxSyncSelection.hide() if self.signal is not None: self.filter_menu = QMenu() self.apply_filter_to_selection_only = self.filter_menu.addAction( self.tr("Apply only to selection")) self.apply_filter_to_selection_only.setCheckable(True) self.apply_filter_to_selection_only.setChecked(False) self.configure_filter_action = self.filter_menu.addAction( "Configure filter...") self.configure_filter_action.setIcon(QIcon.fromTheme("configure")) self.configure_filter_action.triggered.connect( self.on_configure_filter_action_triggered) self.ui.btnFilter.setMenu(self.filter_menu) if self.signal.qad_demod_file_loaded: self.ui.lSignalTyp.setText("Quad-Demod Signal (*.wav)") elif self.signal.wav_mode: self.ui.lSignalTyp.setText("Realpart Signal (*.wav)") else: self.ui.lSignalTyp.setText("Complex Signal") self.ui.gvLegend.hide() self.ui.lineEditSignalName.setText(self.signal.name) self.ui.lSamplesInView.setText("{0:,}".format( self.signal.num_samples)) self.ui.lSamplesTotal.setText("{0:,}".format( self.signal.num_samples)) self.sync_protocol = self.ui.chkBoxSyncSelection.isChecked() self.ui.chkBoxSyncSelection.hide() self.ui.splitter.setSizes([self.ui.splitter.height(), 0]) self.protocol_selection_is_updateable = True self.scene_manager = SignalSceneManager(self.signal, self) self.ui.gvSignal.scene_manager = self.scene_manager self.ui.gvSignal.setScene(self.scene_manager.scene) self.jump_sync = True self.on_btn_show_hide_start_end_clicked() self.refresh_signal_information(block=True) self.create_connects() self.set_protocol_visibility() self.ui.chkBoxShowProtocol.setChecked(True) self.set_qad_tooltip(self.signal.noise_threshold) self.ui.btnSaveSignal.hide() self.show_protocol(refresh=False) else: self.ui.btnFilter.setDisabled(True) suffix = "" if not proto_analyzer.filename: suffix = "" elif proto_analyzer.filename.endswith(".proto"): suffix = " (*.proto)" elif proto_analyzer.filename.endswith(".txt"): suffix = " (*.txt)" self.ui.lSignalTyp.setText("Protocol" + suffix) scene, nsamples = SignalSceneManager.create_rectangle(proto_bits) self.ui.lSamplesInView.setText("{0:n}".format(int(nsamples))) self.ui.lSamplesTotal.setText("{0:n}".format(int(nsamples))) self.ui.gvSignal.setScene(scene) self.ui.spinBoxSelectionStart.setMaximum(nsamples) self.ui.spinBoxSelectionEnd.setMaximum(nsamples) self.ui.btnReplay.hide() self.create_connects() self.ui.gvSignal.sel_area_active = True self.ui.btnSaveSignal.hide()