From 94b883032dd1566081d83d158600905a832cd5c5 Mon Sep 17 00:00:00 2001 From: Yorusora <2944763079@qq.com> Date: Thu, 22 May 2025 16:59:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=BA=86=E4=BD=93=E5=8A=A8?= =?UTF-8?q?=E7=9A=84=E4=BF=9D=E5=AD=98=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- func/Module_SA_label.py | 8 ++- func/Module_artifact_label.py | 8 +-- func/Module_bcg_quality_label.py | 89 +++++++++++++++++++++++++++++++ func/Module_mainwindow.py | 16 +++++- func/Module_resp_quality_label.py | 8 ++- func/utils/ConfigParams.py | 46 ++-------------- func/utils/Constants.py | 3 ++ 7 files changed, 128 insertions(+), 50 deletions(-) create mode 100644 func/Module_bcg_quality_label.py diff --git a/func/Module_SA_label.py b/func/Module_SA_label.py index e02be1a..71b2fb9 100644 --- a/func/Module_SA_label.py +++ b/func/Module_SA_label.py @@ -1318,9 +1318,13 @@ class Data: Config["InputConfig"]["SpO2Freq"] = result.data["freq"] else: return result + result = PublicFunc.examine_file(Config["Path"]["Input_Artifact"], ConfigParams.ARTIFACT_A) + if result.status: + Config["Path"]["Input_Artifact"] = result.data["path"] + else: + return result + - Config["Path"]["Input_Artifact"] = str( - Path(Config["Path"]["Input_Artifact"]) / Path(ConfigParams.ARTIFACT_A + ConfigParams.ENDSWITH_TXT)) Config["Path"]["Input_Label"] = str( Path(Config["Path"]["Input_Label"]) / Path(ConfigParams.SA_LABEL_SYNC + ConfigParams.ENDSWITH_CSV)) Config["Path"]["Save"] = str( diff --git a/func/Module_artifact_label.py b/func/Module_artifact_label.py index e0ce628..17aa1cf 100644 --- a/func/Module_artifact_label.py +++ b/func/Module_artifact_label.py @@ -562,7 +562,7 @@ class MainWindow_artifact_label(QMainWindow): except Exception as e: return Result().failure(info=Constants.UPDATE_FAILURE + Constants.FAILURE_REASON["Update_Info_Exception"] + "\n" + format_exc()) - return Result().success(info=Constants.UPDATE_FAILURE) + return Result().success(info=Constants.UPDATE_FINISHED) def __slot_btn_input__(self): PublicFunc.__disableAllButton__(self, ButtonState) @@ -1224,11 +1224,11 @@ class Data: return result Config["Path"]["Save_a"] = str( - Path(Config["Path"]["Save_a"]) / Path(ConfigParams.ARTIFACT_A + ConfigParams.ENDSWITH_TXT)) + Path(Config["Path"]["Save_a"]) / Path(ConfigParams.ARTIFACT_A + str(Config["InputConfig"]["UseFreq"]) + ConfigParams.ENDSWITH_TXT)) Config["Path"]["Save_b"] = str( - Path(Config["Path"]["Save_b"]) / Path(ConfigParams.ARTIFACT_B + ConfigParams.ENDSWITH_TXT)) + Path(Config["Path"]["Save_b"]) / Path(ConfigParams.ARTIFACT_B + str(Config["InputConfig"]["UseFreq"]) + ConfigParams.ENDSWITH_TXT)) Config["Path"]["Save_c"] = str( - Path(Config["Path"]["Save_c"]) / Path(ConfigParams.ARTIFACT_C + ConfigParams.ENDSWITH_CSV)) + Path(Config["Path"]["Save_c"]) / Path(ConfigParams.ARTIFACT_C + str(Config["InputConfig"]["UseFreq"]) + ConfigParams.ENDSWITH_CSV)) try: self.orgBcg = read_csv(Config["Path"]["Input_orgBcg"], diff --git a/func/Module_bcg_quality_label.py b/func/Module_bcg_quality_label.py new file mode 100644 index 0000000..ee26e8a --- /dev/null +++ b/func/Module_bcg_quality_label.py @@ -0,0 +1,89 @@ +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 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_bcg_quality_label import Ui_MainWindow_bcg_quality_label +from ui.setting.bcg_quality_label_input_setting import Ui_MainWindow_bcg_quality_label_input_setting + + +Config = { + +} + +ButtonState = { + "Default": { + "pushButton_input_setting": True, + "pushButton_input": True, + "pushButton_invalid_signal_label": False, + "pushButton_Ctype_signal_label": False, + "pushButton_prev": False, + "pushButton_next": False, + "pushButton_save": False, + "pushButton_a1": False, + "pushButton_a2": False, + "pushButton_b1": False, + "pushButton_b2": False, + "pushButton_c": False, + "pushButton_f": False + }, + "Current": { + "pushButton_input_setting": True, + "pushButton_input": True, + "pushButton_invalid_signal_label": False, + "pushButton_Ctype_signal_label": False, + "pushButton_prev": False, + "pushButton_next": False, + "pushButton_save": False, + "pushButton_a1": False, + "pushButton_a2": False, + "pushButton_b1": False, + "pushButton_b2": False, + "pushButton_c": False, + "pushButton_f": False + } +} + + +class SettingWindow(QMainWindow): + + def __init__(self, root_path, sampID): + super(SettingWindow, self).__init__() + self.ui = Ui_MainWindow_bcg_quality_label_input_setting() + self.ui.setupUi(self) + + self.root_path = root_path + self.sampID = sampID + + self.config = None + + +class MainWindow_bcg_quality_label(QMainWindow): + + def __init__(self): + super(MainWindow_bcg_quality_label, self).__init__() + self.ui = Ui_MainWindow_bcg_quality_label() + self.ui.setupUi(self) + + self.root_path = None + self.sampID = None + + self.data = None + + self.setting = None + + # 初始化进度条 + self.progressbar = None + PublicFunc.add_progressbar(self) \ No newline at end of file diff --git a/func/Module_mainwindow.py b/func/Module_mainwindow.py index b5d294a..a8ceee9 100644 --- a/func/Module_mainwindow.py +++ b/func/Module_mainwindow.py @@ -16,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_bcg_quality_label import MainWindow_bcg_quality_label from func.Module_resp_quality_label import MainWindow_resp_quality_label from func.Module_SA_label import MainWindow_SA_label @@ -63,6 +64,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label): self.precisely_align = None self.cut_PSG = None self.artifact_label = None + self.bcg_quality_label = None self.resp_quality_label = None self.SA_label = None @@ -78,6 +80,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_bcg_quality_label.clicked.connect(self.__slot_btn_bcg_quality_label__) self.ui.pushButton_resp_quality_label.clicked.connect(self.__slot_btn_resp_quality_label__) self.ui.pushButton_SA_label.clicked.connect(self.__slot_btn_SA_label__) @@ -189,7 +192,6 @@ class MainWindow(QMainWindow, Ui_Signal_Label): # 默认最大化显示而非固定分辨率 self.label_check.showMaximized() - def __slot_btn_precisely_align__(self): self.precisely_align = MainWindow_precisely_align() root_path = self.ui.plainTextEdit_root_path.toPlainText() @@ -224,6 +226,18 @@ class MainWindow(QMainWindow, Ui_Signal_Label): # 默认最大化显示而非固定分辨率 self.artifact_label.showMaximized() + def __slot_btn_bcg_quality_label__(self): + self.bcg_quality_label = MainWindow_bcg_quality_label() + root_path = self.ui.plainTextEdit_root_path.toPlainText() + sampID = self.ui.comboBox_sampID.currentText() + if not self.check_root_path(): + return + if not self.check_sampID(): + return + self.bcg_quality_label.show(root_path, int(sampID)) + # 默认最大化显示而非固定分辨率 + self.bcg_quality_label.showMaximized() + def __slot_btn_resp_quality_label__(self): self.resp_quality_label = MainWindow_resp_quality_label() root_path = self.ui.plainTextEdit_root_path.toPlainText() diff --git a/func/Module_resp_quality_label.py b/func/Module_resp_quality_label.py index 38d21b7..86ada06 100644 --- a/func/Module_resp_quality_label.py +++ b/func/Module_resp_quality_label.py @@ -1352,8 +1352,12 @@ class Data(): else: return result - Config["Path"]["Input_Artifact"] = str( - Path(Config["Path"]["Input_Artifact"]) / Path(ConfigParams.ARTIFACT_A + ConfigParams.ENDSWITH_TXT)) + result = PublicFunc.examine_file(Config["Path"]["Input_Artifact"], ConfigParams.ARTIFACT_A) + if result.status: + Config["Path"]["Input_Artifact"] = result.data["path"] + else: + return result + Config["Path"]["Save_Resp_quality_label"] = str( Path(Config["Path"]["Save_Resp_quality_label"]) / Path( ConfigParams.RESP_QUALITY_LABEL + ConfigParams.ENDSWITH_TXT)) diff --git a/func/utils/ConfigParams.py b/func/utils/ConfigParams.py index 404ada5..899488d 100644 --- a/func/utils/ConfigParams.py +++ b/func/utils/ConfigParams.py @@ -50,9 +50,9 @@ class ConfigParams: RPEAK_FINAL_CORRECTED: str = "Rpeak_final_corrected_" APPROXIMATELY_ALIGN_INFO: str = "Approximately_Align_Info" PRECISELY_ALIGN_INFO: str = "Precisely_Align_Info" - ARTIFACT_A: str = "Artifact_a" - ARTIFACT_B: str = "Artifact_b" - ARTIFACT_C: str = "Artifact_c" + ARTIFACT_A: str = "Artifact_a_" + ARTIFACT_B: str = "Artifact_b_" + ARTIFACT_C: str = "Artifact_c_" BCG_SYNC: str = "BCG_Sync_" ECG_SYNC: str = "ECG_Sync_" JPEAK_SYNC: str = "Jpeak_Sync_" @@ -252,6 +252,8 @@ class ConfigParams: ARTIFACT_LABEL_LABEL_TRANSPARENCY: float = 0.3 ARTIFACT_LABEL_ACTION_LABEL_ARTIFACT_SHORTCUT_KEY: str = "Z" + # BCG质量标注 + # 呼吸可用性及间期标注 RESP_QUALITY_LABEL_CONFIG_FILE_PATH: str = "./config/Config_resp_quality_label.yaml" RESP_QUALITY_LABEL_CONFIG_NEW_CONTENT: dict = { @@ -309,16 +311,6 @@ class ConfigParams: SA_LABEL_RADIOBUTTON_2_CLASS_SHORTCUT_KEY: str = "I" SA_LABEL_RADIOBUTTON_3_CLASS_SHORTCUT_KEY: str = "O" - - - - - - - - - - # 质量打标 BCG_QUALITY_LABEL_INPUT_BCG_FILENAME: str = "BCG_sync_" BCG_QUALITY_LABEL_INPUT_ARTIFACT_FILENAME: str = "Artifact_a" @@ -332,34 +324,6 @@ class ConfigParams: BCG_QUALITY_LABEL_MODE_10S_LENGTH = 10 * BCG_QUALITY_LABEL_INPUT_DEFAULT_FS BCG_QUALITY_LABEL_MODE_30S_LENGTH = 30 * BCG_QUALITY_LABEL_INPUT_DEFAULT_FS - # 呼吸可用性及间期标注 - RESP_QUALITY_LABEL_INPUT_XINXIAO_FILENAME: str = "orgBcg_sync_" - RESP_QUALITY_LABEL_INPUT_THO_FILENAME: str = "Effort_Tho_sync_" - RESP_QUALITY_LABEL_INPUT_ARTIFACT_FILENAME: str = "Artifact_a" - RESP_QUALITY_LABEL_SAVE_RESP_QUALITY_LABNEL_FILENAME: str = "Resp_quality_label" - RESP_QUALITY_LABEL_SAVE_THO_PEAK_FILENAME: str = "Tho_peak" - - RESP_QUALITY_LABEL_INPUT_XINXIAO_DEFAULT_FS: int = 1000 - RESP_QUALITY_LABEL_INPUT_THO_DEFAULT_FS: int = 200 - - - - - RESP_QUALITY_LABEL_THRESHOLD1_DEFAULT: float = 0.65 - RESP_QUALITY_LABEL_THRESHOLD2_DEFAULT: float = 0.8 - RESP_QUALITY_LABEL_FINDPEAKS_MIN_INTERVAL_DEFAULT: int = 300 - RESP_QUALITY_LABEL_FINDPEAKS_MIN_HEIGHT_DEFAULT: float = 0.1 - RESP_QUALITY_LABEL_CUSTOM_LOW_DEFAULT: float = 0.1 - RESP_QUALITY_LABEL_CUSTOM_HIGH_DEFAULT: float = 1 - - - - - - - # 睡眠呼吸暂停事件打标 - - # 禁止实例化 def __new__(cls): raise TypeError("Constants class cannot be instantiated") diff --git a/func/utils/Constants.py b/func/utils/Constants.py index f8a2a0e..ade8a2b 100644 --- a/func/utils/Constants.py +++ b/func/utils/Constants.py @@ -379,6 +379,9 @@ class Constants: background-color: #00ff00; /* 鼠标悬停时的背景颜色 */ }""" + # BCG质量标注 + + # 呼吸可用性及间期标注 RESP_QUALITY_LABEL_CALCULATING_PEAK: str = "正在计算峰值" RESP_QUALITY_LABEL_CALCULATE_FINISHED: str = "计算完成"