Add modulation filter algorithm

This commit is contained in:
alessandro90
2018-11-11 12:58:17 +01:00
parent 7f124e30ff
commit af54095d19
5 changed files with 220 additions and 19 deletions

View File

@@ -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
View File

@@ -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):

View File

@@ -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">

View File

@@ -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

View File

@@ -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):