diff --git a/func/Module_SA_label.py b/func/Module_SA_label.py new file mode 100644 index 0000000..7941f95 --- /dev/null +++ b/func/Module_SA_label.py @@ -0,0 +1,32 @@ +from gc import collect +from pathlib import Path +from traceback import format_exc + +import matplotlib.pyplot as plt +from PySide6.QtWidgets import QMessageBox, QMainWindow, QApplication +from matplotlib import gridspec +from matplotlib.backends.backend_qt import NavigationToolbar2QT +from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg +from overrides import overrides +from pandas import read_csv, DataFrame +from scipy.signal import resample +from yaml import dump, load, FullLoader + +from func.utils.PublicFunc import PublicFunc +from func.utils.Constants import Constants, ConfigParams +from func.utils.Result import Result + +from ui.MainWindow.MainWindow_SA_label import Ui_MainWindow_SA_label +# from ui.setting.preprocess_input_setting import Ui_MainWindow_preprocess_input_setting + + +Config = { + +} + +class MainWindow_SA_label(QMainWindow): + + def __init__(self): + super(MainWindow_SA_label, self).__init__() + self.ui = Ui_MainWindow_SA_label() + self.ui.setupUi(self) \ No newline at end of file diff --git a/func/Module_mainwindow.py b/func/Module_mainwindow.py index f6ba025..5e63988 100644 --- a/func/Module_mainwindow.py +++ b/func/Module_mainwindow.py @@ -1,6 +1,7 @@ from pathlib import Path from PySide6.QtWidgets import QMainWindow, QMessageBox, QFileDialog +from PySide6.QtGui import QGuiApplication from matplotlib import use from yaml import dump, load, FullLoader @@ -15,6 +16,7 @@ from func.Module_label_check import MainWindow_label_check from func.Module_precisely_align import MainWindow_precisely_align from func.Module_cut_PSG import MainWindow_cut_PSG from func.Module_artifact_label import MainWindow_artifact_label +from func.Module_SA_label import MainWindow_SA_label from func.utils.Constants import Constants, ConfigParams @@ -34,7 +36,15 @@ class MainWindow(QMainWindow, Ui_Signal_Label): self.ui = Ui_Signal_Label() self.ui.setupUi(self) - self.setFixedSize(720, 1080) # 设置固定大小,禁止缩放 + # self.setFixedSize(720, 1080) # 设置固定大小,禁止缩放 + # 获得屏幕分辨率,以3:4比例设置窗口大小, + screen = QGuiApplication.primaryScreen() + size = screen.availableGeometry() + screen_height = size.height() + + window_height = int(screen_height * 0.75) + window_width = int(window_height * 1 / 2) + self.resize(window_width, window_height) # 消息弹窗初始化 self.msgBox = QMessageBox() @@ -53,6 +63,8 @@ class MainWindow(QMainWindow, Ui_Signal_Label): self.cut_PSG = None self.artifact_label = None + self.SA_label = None + # 绑定槽函数 self.ui.pushButton_open.clicked.connect(self.__slot_btn_open__) self.ui.pushButton_approximately_align.clicked.connect(self.__slot_btn_approximately_align__) @@ -65,6 +77,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label): self.ui.pushButton_precisely_align.clicked.connect(self.__slot_btn_precisely_align__) self.ui.pushButton_cut_PSG.clicked.connect(self.__slot_btn_cut_PSG__) self.ui.pushButton_artifact_label.clicked.connect(self.__slot_btn_artifact_label__) + self.ui.pushButton_SA_label.clicked.connect(self.__slot_btn_SA_label__) @staticmethod def __read_config__(): @@ -105,6 +118,8 @@ class MainWindow(QMainWindow, Ui_Signal_Label): if not self.check_sampID(): return self.approximately_align.show(root_path, int(sampID)) + # 默认最大化显示而非固定分辨率 + self.approximately_align.showMaximized() def __slot_btn_preprocess__(self): self.preprocess = MainWindow_preprocess() @@ -123,6 +138,8 @@ class MainWindow(QMainWindow, Ui_Signal_Label): if not self.check_sampID(): return self.preprocess.show(mode, root_path, int(sampID)) + # 默认最大化显示而非固定分辨率 + self.preprocess.showMaximized() def __slot_btn_detect_Jpeak__(self): self.detect_Jpeak = MainWindow_detect_Jpeak() @@ -133,6 +150,8 @@ class MainWindow(QMainWindow, Ui_Signal_Label): if not self.check_sampID(): return self.detect_Jpeak.show(root_path, int(sampID)) + # 默认最大化显示而非固定分辨率 + self.detect_Jpeak.showMaximized() def __slot_btn_detect_Rpeak__(self): self.detect_Rpeak = MainWindow_detect_Rpeak() @@ -143,6 +162,8 @@ class MainWindow(QMainWindow, Ui_Signal_Label): if not self.check_sampID(): return self.detect_Rpeak.show(root_path, int(sampID)) + # 默认最大化显示而非固定分辨率 + self.detect_Rpeak.showMaximized() def __slot_btn_label_check__(self): self.label_check = MainWindow_label_check() @@ -163,6 +184,9 @@ class MainWindow(QMainWindow, Ui_Signal_Label): else: raise ValueError("模式不存在") self.label_check.show(mode, root_path, int(sampID)) + # 默认最大化显示而非固定分辨率 + self.label_check.showMaximized() + def __slot_btn_precisely_align__(self): self.precisely_align = MainWindow_precisely_align() @@ -173,6 +197,8 @@ class MainWindow(QMainWindow, Ui_Signal_Label): if not self.check_sampID(): return self.precisely_align.show(root_path, int(sampID)) + # 默认最大化显示而非固定分辨率 + self.precisely_align.showMaximized() def __slot_btn_cut_PSG__(self): self.cut_PSG = MainWindow_cut_PSG() @@ -183,6 +209,8 @@ class MainWindow(QMainWindow, Ui_Signal_Label): if not self.check_sampID(): return self.cut_PSG.show(root_path, int(sampID)) + # 默认最大化显示而非固定分辨率 + self.cut_PSG.showMaximized() def __slot_btn_artifact_label__(self): self.artifact_label = MainWindow_artifact_label() @@ -193,6 +221,12 @@ class MainWindow(QMainWindow, Ui_Signal_Label): if not self.check_sampID(): return self.artifact_label.show(root_path, int(sampID)) + # 默认最大化显示而非固定分辨率 + self.artifact_label.showMaximized() + + def __slot_btn_SA_label__(self): + self.SA_label = MainWindow_SA_label() + self.SA_label.show() def seek_sampID(self, path): if not Path(path).exists(): @@ -202,6 +236,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label): sub_folders = [item.name for item in Path(path).iterdir() if item.is_dir()] self.ui.comboBox_sampID.addItems(sub_folders) + def check_root_path(self): if self.ui.plainTextEdit_root_path.toPlainText() == Constants.STRING_IS_EMPTY: PublicFunc.msgbox_output(self, Constants.MAINWINDOW_ROOT_PATH_NOT_EXIST, Constants.MSGBOX_TYPE_ERROR) diff --git a/func/Module_precisely_align.py b/func/Module_precisely_align.py index a47564c..f297148 100644 --- a/func/Module_precisely_align.py +++ b/func/Module_precisely_align.py @@ -1642,10 +1642,10 @@ class Data: orgfs = Config["orgfs"] off = Config["offset_anchor"] - self.res_orgBcg = self.raw_orgBcg - self.res_BCG = self.raw_BCG - self.cut_ECG = self.raw_ECG - self.cut_Rpeak = self.Rpeak + self.res_orgBcg = self.raw_orgBcg.copy() + self.res_BCG = self.raw_BCG.copy() + self.cut_ECG = self.raw_ECG.copy() + self.cut_Rpeak = self.Rpeak.copy() if off > 0: self.cut_ECG = self.cut_ECG[off:] diff --git a/数据结构化输入和输出命名规范.md b/数据结构化输入和输出命名规范.md index d824773..66743ee 100644 --- a/数据结构化输入和输出命名规范.md +++ b/数据结构化输入和输出命名规范.md @@ -6,49 +6,50 @@ ``` .../Label/ - |-Artifact_a.txt - |-Artifact_b.txt - |-Artifact_c.csv + |-Artifact_a_采样率.txt + |-Artifact_b_采样率.txt + |-Artifact_c_采样率.csv |-SQ_label_10s.csv |-SQ_label_30s.csv |-Resp_quality_label.txt - |-Tho_peak.txt + |-Tho_peak_采样率.txt |-SA Label_corrected.csv - |-SA Label_add.csv` -.../OrgBCG_Aligned/ - |-Align_info.yaml - |-BCG_Sync_采样率.txt - |-orgBcg_Sync_采样率.txt - |-Jpeak_Sync.txt -.../OrgBCG_Text/ - |-orgBcg_Raw_采样率.txt - |-BCG_Raw_采样率.txt - |-JPeak_revise.txt - |-JPeak_revise_corrected.txt + |-SA Label_add.csv + |-Precisely_Align_info.txt |-Approximately_Align_Info.csv +.../OrgBCG_Aligned/ + |-BCG_Sync_采样率.txt + |-OrgBCG_Sync_采样率.txt + |-Jpeak_Sync_采样率.txt +.../OrgBCG_Text/ + |-OrgBCG_Raw_采样率.txt + |-BCG_Filter_采样率.txt + |-JPeak_revise_采样率.txt + |-JPeak_revise_corrected_采样率.txt .../OrgBCG_Origin/ |-... .../PSG_Aligned/ - |-Align_info.yaml |-ECG_Sync_采样率.txt - |-Rpeak_Sync.txt + |-Rpeak_Sync_采样率.txt |-5_class_Sync_1.txt |-SA Label_Sync.csv |-Effort Abd_Sync_采样率.txt |-Effort Tho_Sync_采样率.txt - |-Flow Patient_Sync_采样率.txt + |-Flow T_Sync_采样率.txt + |-Flow P_Sync_采样率.txt |-Snore_Sync_采样率.txt |-SpO2_Sync_采样率.txt .../PSG_Text/ - |-orgEcg II_Raw_采样率.txt - |-ECG_Raw_采样率.txt - |-Rpeak_final.txt - |-Rpeak_final_corrected.txt - |-5_class_Raw_1.txt + |-ECG II_Raw_采样率.txt + |-ECG_Filter_采样率.txt + |-Rpeak_final_采样率.txt + |-Rpeak_final_corrected_采样率.txt + |-5_class_Raw_采样率.txt |-SA Label_Raw.csv |-Effort Abd_Raw_采样率.txt |-Effort Tho_Raw_采样率.txt - |-Flow Patient_Raw_采样率.txt + |-Flow T_Raw_采样率.txt + |-Flow P_Raw_采样率.txt |-Snore_Raw_采样率.txt |-SpO2_Raw_采样率.txt |-StartTime_Raw.txt @@ -66,13 +67,13 @@ 输入: -原始orgBcg信号:`./OrgBCG_Text//orgBcg_Raw_采样率.txt` +原始orgBcg信号:`./OrgBCG_Text//OrgBCG_Raw_采样率.txt` 原始PSG信号:`./PSG_Text//Axxxxxxx.edf` 输出: -粗同步后的位置索引:`./OrgBCG_Text//Approximately_Align_Info.csv` +粗同步后的位置索引:`./Label//Approximately_Align_Info.csv` ### 2 预处理 @@ -80,15 +81,15 @@ 输入: -原始orgBcg信号:`./OrgBCG_Text//orgBcg_Raw_采样率.txt` +原始orgBcg信号:`./OrgBCG_Text//OrgBCG_Raw_采样率.txt` 原始ECG信号:`./PSG_Text//ECG II_Raw_采样率.txt` 输出: -带通滤波BCG信号:`./OrgBCG_Text//BCG_Raw_采样率.txt` +带通滤波BCG信号:`./OrgBCG_Text//BCG_Filter_采样率.txt` -滤波后的ECG信号:`./PSG_Text//ECG_Raw_采样率.txt` +滤波后的ECG信号:`./PSG_Text//ECG_Filter_采样率.txt` ### 3 数据精同步 @@ -101,11 +102,11 @@ 输入: -滤波后的ECG信号:`./PSG_Text//ECG_Raw_采样率.txt` +滤波后的ECG信号:`./PSG_Text//ECG_Filter_采样率.txt` 输出: -算法定位的R峰坐标:`./PSG_Text//Rpeak_final.txt` +算法定位的R峰坐标:`./PSG_Text//Rpeak_final_采样率.txt` #### 3.1.2 J峰算法定位 @@ -113,11 +114,11 @@ 输入: -带通滤波BCG信号:`./OrgBCG_Text//BCG_Raw_采样率.txt` +带通滤波BCG信号:`./OrgBCG_Text//BCG_Filter_采样率.txt` 输出: -算法定位的J峰坐标:`./OrgBCG_Text//JPeak_revise.txt` +算法定位的J峰坐标:`./OrgBCG_Text//JPeak_revise_采样率.txt` #### 3.2 人工纠正 @@ -128,15 +129,15 @@ 输入: -滤波后的ECG信号:`./PSG_Text//ECG_Raw_采样率.txt` +滤波后的ECG信号:`./PSG_Text//ECG_Filter_采样率.txt` -算法定位的R峰坐标:`./PSG_Text//Rpeak_final.txt` +算法定位的R峰坐标:`./PSG_Text//Rpeak_final_采样率.txt` -粗同步后的位置索引:`./OrgBCG_Text//Approximately_Align_Info.csv` +粗同步后的位置索引:`./Label//Approximately_Align_Info.csv` 输出: -人工纠正后的R峰坐标:`./PSG_Text//Rpeak_final_corrected.txt` +人工纠正后的R峰坐标:`./PSG_Text//Rpeak_final_corrected_采样率.txt` #### 3.2.2 J峰人工纠正* @@ -144,15 +145,15 @@ 输入: -带通滤波BCG信号:`./OrgBCG_Text//BCG_Raw_采样率.txt` +带通滤波BCG信号:`./OrgBCG_Text//BCG_Filter_采样率.txt` -算法定位的J峰坐标:`./OrgBCG_Text//JPeak_revise.txt` +算法定位的J峰坐标:`./OrgBCG_Text//JPeak_revise_采样率.txt` -粗同步后的位置索引:`./OrgBCG_Text//Approximately_Align_Info.csv` +粗同步后的位置索引:`./Label//Approximately_Align_Info.csv` 输出: -人工纠正后的J峰坐标:`./OrgBCG_Text//JPeak_revise_corrected.txt` +人工纠正后的J峰坐标:`./OrgBCG_Text//JPeak_revise_corrected_采样率.txt` #### 3.3 数据片段起止对齐、数据采样率同步 @@ -160,33 +161,31 @@ 输入: -滤波后的ECG信号:`./PSG_Text//ECG_Raw_采样率.txt` +滤波后的ECG信号:`./PSG_Text//ECG_Filter_采样率.txt` -人工纠正后的R峰坐标:`./PSG_Text//Rpeak_final_corrected.txt` +人工纠正后的R峰坐标:`./PSG_Text//Rpeak_final_corrected_采样率.txt` -带通滤波BCG信号:`./OrgBCG_Text//BCG_Raw_采样率.txt` +带通滤波BCG信号:`./OrgBCG_Text//BCG_Filter_采样率.txt` -人工纠正后的J峰坐标:`./OrgBCG_Text//JPeak_revise_corrected.txt` +人工纠正后的J峰坐标:`./OrgBCG_Text//JPeak_revise_corrected_采样率.txt` -原始orgBcg信号:`./OrgBCG_Text//orgBcg_Raw_采样率.txt` +原始orgBcg信号:`./OrgBCG_Text//OrgBCG_Raw_采样率.txt` -粗同步后的位置索引:`./OrgBCG_Text//Approximately_Align_Info.csv` +粗同步后的位置索引:`./Label//Approximately_Align_Info.csv` 输出: -PSG的对齐信息:`./PSG_Aligned//Align_info.yaml` +精同步对齐信息:`./Label//Precisely_Align_info.txt` 同步后的ECG信号:`./PSG_Aligned//ECG_Sync_采样率.txt` -同步后的R峰坐标:`./PSG_Aligned//Rpeak_Sync.txt` - -BCG的对齐信息:`./OrgBCG_Aligned//Align_info.yaml` +同步后的R峰坐标:`./PSG_Aligned//Rpeak_Sync_采样率.txt` 同步后的BCG信号:`./OrgBCG_Aligned//BCG_Sync_采样率.txt` -同步后的orgBcg信号:`./OrgBCG_Aligned//orgBcg_Sync_采样率.txt` +同步后的orgBcg信号:`./OrgBCG_Aligned//OrgBCG_Sync_采样率.txt` -同步后的J峰坐标:`./OrgBCG_Aligned//Jpeak_Sync.txt` +同步后的J峰坐标:`./OrgBCG_Aligned//Jpeak_Sync_采样率.txt` #### 3.4、冗余数据切割、标签映射 @@ -194,21 +193,19 @@ BCG的对齐信息:`./OrgBCG_Aligned//Align_info.yaml` 输入: -PSG的对齐信息:`./PSG_Aligned//Align_info.yaml` +精同步对齐信息:`./Label//Align_info.txt` -BCG的对齐信息:`./OrgBCG_Aligned//Align_info.yaml` +原始的其他PSG通道信号:`./PSG_Text//通道名_Raw_采样率.txt`(通道名包括:Effort Abd, Effort Tho, Flow T, Flow P, Snore, SpO2) -原始的其他PSG通道信号:`./PSG_Text//通道名_Raw_采样率.txt`(通道名包括:Effort Abd, Effort Tho, Flow Patient, Snore, SpO2) - -原始的睡眠分期标签:`./PSG_Text//5_class_Raw_1.txt` +原始的睡眠分期标签:`./PSG_Text//5_class_Raw_采样率.txt` 原始的睡眠呼吸暂停事件标签:`./PSG_Text//SA Label_Raw.csv` 输出: -同步后的其他PSG通道信号:`./PSG_Aligned//通道名_Sync_采样率.txt`(通道名包括:Effort Abd, Effort Tho, Flow Patient, Snore, SpO2) +同步后的其他PSG通道信号:`./PSG_Aligned//通道名_Sync_采样率.txt`(通道名包括:Effort Abd, Effort Tho, Flow T, Flow P, Snore, SpO2) -同步后的睡眠分期标签:`./PSG_Aligned//5_class_Sync_1.txt` +同步后的睡眠分期标签:`./PSG_Aligned//5_class_Sync_采样率.txt` 同步后的睡眠呼吸暂停事件标签:`./PSG_Aligned//SA Label_Sync.csv` @@ -220,15 +217,15 @@ BCG的对齐信息:`./OrgBCG_Aligned//Align_info.yaml` 同步后的BCG信号:`./OrgBCG_Aligned//BCG_Sync_采样率.txt` -同步后的orgBcg信号:`./OrgBCG_Aligned//orgBcg_Sync_采样率.txt` +同步后的orgBcg信号:`./OrgBCG_Aligned//OrgBCG_Sync_采样率.txt` 输出: -txt格式的体动标签:`./Label//Artifact_a.txt` +txt格式的体动标签:`./Label//Artifact_a_采样率.txt` -体动标签类型数量统计:`./Label//Artifact_b.txt` +体动标签类型数量统计:`./Label//Artifact_b_采样率.txt` -csv格式的体动标签:`./Label//Artifact_c.csv` +csv格式的体动标签:`./Label//Artifact_c_采样率.csv` ### 5 质量评估 @@ -238,7 +235,7 @@ csv格式的体动标签:`./Label//Artifact_c.csv` 同步后的BCG信号:`./OrgBCG_Aligned//BCG_Sync_采样率.txt` -txt格式的体动标签:`./Label//Artifact_a.txt` +txt格式的体动标签:`./Label//Artifact_a_采样率.txt` 输出: @@ -266,13 +263,13 @@ txt格式的体动标签:`./Label//Artifact_a.txt` 同步后的THO信号:`./PSG_Aligned//Effort Tho_Sync_采样率.txt` -txt格式的体动标签:`./Label//Artifact_a.txt` +txt格式的体动标签:`./Label//Artifact_a_采样率.txt` 输出: 呼吸可用性标签:`./Label//Resp_quality_label.txt` -THO信号呼吸间期标签:`./Label//Tho_peak.txt` +THO信号呼吸间期标签:`./Label//Tho_peak_采样率.txt` ### 8 呼吸暂停事件标注 @@ -280,13 +277,13 @@ THO信号呼吸间期标签:`./Label//Tho_peak.txt` 输入: -同步后的orgBcg信号:`./OrgBCG_Aligned//orgBcg_Sync_采样率.txt` +同步后的orgBcg信号:`./OrgBCG_Aligned//OrgBCG_Sync_采样率.txt` -txt格式的体动标签:`./Label//Artifact_a.txt` +txt格式的体动标签:`./Label//Artifact_a_采样率.txt` -同步后的FlowT信号:`./PSG_Aligned//Effort Tho_Sync_采样率.txt` +同步后的Flow T信号:`./PSG_Aligned//Flow T_Sync_采样率.txt` -同步后的FlowP信号:`./PSG_Aligned//Effort Tho_Sync_采样率.txt` +同步后的Flow P信号:`./PSG_Aligned//Flow P_Sync_采样率.txt` 同步后的THO信号:`./PSG_Aligned//Effort Tho_Sync_采样率.txt`