Add modulation filter algorithm
This commit is contained in:
@@ -59,11 +59,11 @@ class DownloadWindow(QWidget, Ui_Download_window):
|
|||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def wait_close(self):
|
def wait_close(self):
|
||||||
if self.download_thread.status == ThreadStatus.ok:
|
if self.download_thread.status == ThreadStatus.OK:
|
||||||
self.close()
|
self.close()
|
||||||
elif self.download_thread.status == ThreadStatus.no_connection_err:
|
elif self.download_thread.status == ThreadStatus.NO_CONNECTION_ERR:
|
||||||
self.show_no_connection_warning()
|
self.show_no_connection_warning()
|
||||||
elif self.download_thread.status == ThreadStatus.bad_download_err:
|
elif self.download_thread.status == ThreadStatus.BAD_DOWNLOAD_ERR:
|
||||||
self.show_bad_download_warning
|
self.show_bad_download_warning
|
||||||
else:
|
else:
|
||||||
self.close()
|
self.close()
|
||||||
|
|||||||
65
main.py
65
main.py
@@ -10,8 +10,10 @@ from PyQt5.QtWidgets import (QMainWindow,
|
|||||||
QMessageBox,
|
QMessageBox,
|
||||||
qApp,
|
qApp,
|
||||||
QDesktopWidget,
|
QDesktopWidget,
|
||||||
QListWidgetItem,)
|
QListWidgetItem,
|
||||||
from PyQt5.QtGui import QPixmap
|
QTreeView,
|
||||||
|
QTreeWidgetItem)
|
||||||
|
from PyQt5.QtGui import QPixmap, QStandardItemModel, QStandardItem
|
||||||
from PyQt5 import uic
|
from PyQt5 import uic
|
||||||
from PyQt5.QtCore import (QFileInfo,
|
from PyQt5.QtCore import (QFileInfo,
|
||||||
QSize,
|
QSize,
|
||||||
@@ -35,7 +37,6 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.download_window = DownloadWindow()
|
self.download_window = DownloadWindow()
|
||||||
self.actionExit.triggered.connect(qApp.quit)
|
self.actionExit.triggered.connect(qApp.quit)
|
||||||
self.action_update_database.triggered.connect(self.download_db)
|
self.action_update_database.triggered.connect(self.download_db)
|
||||||
self.db_version = None
|
|
||||||
self.db = None
|
self.db = None
|
||||||
self.current_signal_name = ''
|
self.current_signal_name = ''
|
||||||
self.signal_names = []
|
self.signal_names = []
|
||||||
@@ -267,6 +268,17 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
self.url_button.clicked.connect(self.go_to_web_page_signal)
|
self.url_button.clicked.connect(self.go_to_web_page_signal)
|
||||||
|
|
||||||
|
# Set modulation TreeView
|
||||||
|
|
||||||
|
self.set_mode_tree_widget()
|
||||||
|
self.mode_tree_widget.itemSelectionChanged.connect(self.manage_mode_selections)
|
||||||
|
self.reset_mode_filters_btn.clicked.connect(self.reset_mode_filters)
|
||||||
|
self.apply_remove_mode_filter_btn.set_texts("Apply", "Remove")
|
||||||
|
self.apply_remove_mode_filter_btn.set_slave_filters([self.mode_tree_widget])
|
||||||
|
self.apply_remove_mode_filter_btn.clicked.connect(self.display_signals)
|
||||||
|
self.reset_mode_filters_btn.clicked.connect(self.reset_mode_filters)
|
||||||
|
|
||||||
|
# ##########################################################################################
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
self.load_db()
|
self.load_db()
|
||||||
@@ -279,7 +291,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.volume,
|
self.volume,
|
||||||
self.audio_progress,
|
self.audio_progress,
|
||||||
Constants.data_folder,
|
Constants.data_folder,
|
||||||
Constants.audio_folder)
|
Constants.audio_folder) # Da togliere/////////////////
|
||||||
|
|
||||||
BandLabel = namedtuple("BandLabel", ["left", "center", "right"])
|
BandLabel = namedtuple("BandLabel", ["left", "center", "right"])
|
||||||
self.band_labels = [
|
self.band_labels = [
|
||||||
@@ -296,6 +308,24 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
BandLabel(self.ehf_left, self.ehf, self.ehf_right),
|
BandLabel(self.ehf_left, self.ehf, self.ehf_right),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def set_mode_tree_widget(self):
|
||||||
|
for parent, children in Constants.modes.items():
|
||||||
|
iparent = QTreeWidgetItem([parent])
|
||||||
|
self.mode_tree_widget.addTopLevelItem(iparent)
|
||||||
|
for child in children:
|
||||||
|
ichild = QTreeWidgetItem([child])
|
||||||
|
iparent.addChild(ichild)
|
||||||
|
self.mode_tree_widget.expandAll()
|
||||||
|
|
||||||
|
def manage_mode_selections(self):
|
||||||
|
selected_items = self.mode_tree_widget.selectedItems()
|
||||||
|
parents = Constants.modes.keys()
|
||||||
|
for parent in parents:
|
||||||
|
for item in selected_items:
|
||||||
|
if parent == item.text(0):
|
||||||
|
for i in range(len(Constants.modes[parent])):
|
||||||
|
item.child(i).setSelected(True)
|
||||||
|
|
||||||
def set_initial_size(self):
|
def set_initial_size(self):
|
||||||
"""
|
"""
|
||||||
Function to handle high resolution screens. The function sets bigger sizes
|
Function to handle high resolution screens. The function sets bigger sizes
|
||||||
@@ -494,7 +524,8 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
if text.lower() in signal.lower() and \
|
if text.lower() in signal.lower() and \
|
||||||
self.frequency_filters_ok(signal) and \
|
self.frequency_filters_ok(signal) and \
|
||||||
self.band_filters_ok(signal) and \
|
self.band_filters_ok(signal) and \
|
||||||
self.category_filters_ok(signal):
|
self.category_filters_ok(signal) and \
|
||||||
|
self.mode_filters_ok(signal):
|
||||||
self.result_list.addItem(signal)
|
self.result_list.addItem(signal)
|
||||||
available_signals += 1
|
available_signals += 1
|
||||||
self.update_status_tip(available_signals)
|
self.update_status_tip(available_signals)
|
||||||
@@ -552,6 +583,13 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
f.setChecked(False) if f.isChecked() else None
|
f.setChecked(False) if f.isChecked() else None
|
||||||
self.cat_at_least_one.setChecked(True)
|
self.cat_at_least_one.setChecked(True)
|
||||||
|
|
||||||
|
def reset_mode_filters(self):
|
||||||
|
if self.apply_remove_mode_filter_btn.isChecked():
|
||||||
|
self.apply_remove_mode_filter_btn.setChecked(False)
|
||||||
|
self.apply_remove_mode_filter_btn.clicked.emit()
|
||||||
|
for item in self.mode_tree_widget.selectedItems():
|
||||||
|
item.setSelected(False)
|
||||||
|
|
||||||
def frequency_filters_ok(self, signal_name):
|
def frequency_filters_ok(self, signal_name):
|
||||||
if not self.apply_remove_freq_filter_btn.isChecked():
|
if not self.apply_remove_freq_filter_btn.isChecked():
|
||||||
return True
|
return True
|
||||||
@@ -632,6 +670,22 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
else:
|
else:
|
||||||
return cat_checked == positive_cases and cat_checked > 0
|
return cat_checked == positive_cases and cat_checked > 0
|
||||||
|
|
||||||
|
def mode_filters_ok(self, signal_name):
|
||||||
|
if not self.apply_remove_mode_filter_btn.isChecked():
|
||||||
|
return True
|
||||||
|
selected_items = [item for item in self.mode_tree_widget.selectedItems()]
|
||||||
|
selected_items_text = [i.text(0) for i in selected_items]
|
||||||
|
parents = [item for item in selected_items_text if item in Constants.modes.keys()]
|
||||||
|
children = [item for item in selected_items_text if item not in parents]
|
||||||
|
signal_mode = self.db.at[signal_name, "mode"]
|
||||||
|
ok = []
|
||||||
|
for item in selected_items:
|
||||||
|
if item.text(0) in parents:
|
||||||
|
ok.append(item.text(0) in signal_mode)
|
||||||
|
elif not item.parent().isSelected():
|
||||||
|
ok.append(item.text(0) == signal_mode)
|
||||||
|
return any(ok)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def filters_ok(spinbox, filter_unit, confidence, sign = 1):
|
def filters_ok(spinbox, filter_unit, confidence, sign = 1):
|
||||||
band_filter = spinbox.value() * Constants.conversion_factors[filter_unit.currentText()]
|
band_filter = spinbox.value() * Constants.conversion_factors[filter_unit.currentText()]
|
||||||
@@ -779,6 +833,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.reset_frequency_filters_btn.clicked.emit()
|
self.reset_frequency_filters_btn.clicked.emit()
|
||||||
self.reset_band_filters_btn.clicked.emit()
|
self.reset_band_filters_btn.clicked.emit()
|
||||||
self.reset_cat_filters_btn.clicked.emit()
|
self.reset_cat_filters_btn.clicked.emit()
|
||||||
|
self.reset_mode_filters_btn.clicked.emit()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def go_to_web_page_signal(self):
|
def go_to_web_page_signal(self):
|
||||||
|
|||||||
140
main_window.ui
140
main_window.ui
@@ -323,7 +323,7 @@ QPushButton:!enabled {
|
|||||||
<enum>QTabWidget::Rounded</enum>
|
<enum>QTabWidget::Rounded</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="movable">
|
<property name="movable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@@ -1962,7 +1962,7 @@ QPushButton:checked {
|
|||||||
</string>
|
</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="movable">
|
<property name="movable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@@ -3691,6 +3691,142 @@ Inactive</string>
|
|||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Mode</string>
|
<string>Mode</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="mode_filter_container" native="true">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QWidget#mode_filter_container {
|
||||||
|
border: 1px solid gray;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget#FM_container, QWidget#SK_container, QWidget#SB_container{
|
||||||
|
border: 1px solid gray;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget#xFM_container, QWidget#xSK_container, QWidget#xSB_container{
|
||||||
|
border: 1px solid gray;
|
||||||
|
border-radius: 8px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Include unknown modulations</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_26">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTreeWidget" name="mode_tree_widget">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::MultiSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectItems</enum>
|
||||||
|
</property>
|
||||||
|
<property name="animated">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="headerHidden">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="columnCount">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">1</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="DoubleTextButton" name="apply_remove_mode_filter_btn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Apply</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="reset_mode_filters_btn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_7">
|
<widget class="QWidget" name="tab_7">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
|||||||
18
threads.py
18
threads.py
@@ -9,15 +9,15 @@ from PyQt5.QtCore import QThread
|
|||||||
from utilities import checksum_ok, Constants
|
from utilities import checksum_ok, Constants
|
||||||
|
|
||||||
class ThreadStatus(Enum):
|
class ThreadStatus(Enum):
|
||||||
ok = auto()
|
OK = auto()
|
||||||
no_connection_err = auto()
|
NO_CONNECTION_ERR = auto()
|
||||||
no_file_err = auto()
|
UNKNOWN_ERR = auto()
|
||||||
bad_download_err = auto()
|
BAD_DOWNLOAD_ERR = auto()
|
||||||
|
|
||||||
class DownloadThread(QThread):
|
class DownloadThread(QThread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.__status = ThreadStatus.ok
|
self.__status = ThreadStatus.OK
|
||||||
self.reason = 0
|
self.reason = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -34,14 +34,14 @@ class DownloadThread(QThread):
|
|||||||
# db = urllib.request.urlopen(Constants.db_location)
|
# db = urllib.request.urlopen(Constants.db_location)
|
||||||
# raise urllib.error.URLError('Test')
|
# raise urllib.error.URLError('Test')
|
||||||
except urllib3.exceptions.MaxRetryError: # No internet connection.
|
except urllib3.exceptions.MaxRetryError: # No internet connection.
|
||||||
self.__status = ThreadStatus.no_connection_err
|
self.__status = ThreadStatus.NO_CONNECTION_ERR
|
||||||
return
|
return
|
||||||
if db.status != 200:
|
if db.status != 200:
|
||||||
self.reason = db.reason
|
self.reason = db.reason
|
||||||
self.__status = ThreadStatus.bad_download_err
|
self.__status = ThreadStatus.BAD_DOWNLOAD_ERR
|
||||||
return
|
return
|
||||||
if not checksum_ok(db.data, "folder"):
|
if not checksum_ok(db.data, "folder"):
|
||||||
self.__status = ThreadStatus.bad_download_err
|
self.__status = ThreadStatus.BAD_DOWNLOAD_ERR
|
||||||
return
|
return
|
||||||
if os.path.exists(Constants.data_folder):
|
if os.path.exists(Constants.data_folder):
|
||||||
rmtree(Constants.data_folder)
|
rmtree(Constants.data_folder)
|
||||||
@@ -50,4 +50,4 @@ class DownloadThread(QThread):
|
|||||||
with ZipFile(BytesIO(db.data)) as zipped:
|
with ZipFile(BytesIO(db.data)) as zipped:
|
||||||
zipped.extractall()
|
zipped.extractall()
|
||||||
except:
|
except:
|
||||||
self.__status = ThreadStatus.bad_file_err
|
self.__status = ThreadStatus.UNKNOWN_ERR
|
||||||
|
|||||||
10
utilities.py
10
utilities.py
@@ -36,6 +36,16 @@ class Constants(object):
|
|||||||
active_color = _ReadOnlyProperty("#39eaff")
|
active_color = _ReadOnlyProperty("#39eaff")
|
||||||
inactive_color = _ReadOnlyProperty("#9f9f9f")
|
inactive_color = _ReadOnlyProperty("#9f9f9f")
|
||||||
conversion_factors = _ReadOnlyProperty({"Hz":1, "kHz":1000, "MHz":1000000, "GHz":1000000000})
|
conversion_factors = _ReadOnlyProperty({"Hz":1, "kHz":1000, "MHz":1000000, "GHz":1000000000})
|
||||||
|
modes = _ReadOnlyProperty({"FM": ["NFM", "WFM"],
|
||||||
|
"AM": [],
|
||||||
|
"CW": [],
|
||||||
|
"SK": ["FSK", "PSK", "MSK"],
|
||||||
|
"SB": ["LSB", "USB", "DSB"],
|
||||||
|
"Chirp Spread Spectrum": [],
|
||||||
|
"FHSS-TDM": [],
|
||||||
|
"RAW": [],
|
||||||
|
"SC-FDMA": [],}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def checksum_ok(data, what):
|
def checksum_ok(data, what):
|
||||||
|
|||||||
Reference in New Issue
Block a user