From baa2923e5b80c487e425270e33d29bcdabc77c70 Mon Sep 17 00:00:00 2001 From: Yorusora Date: Thu, 8 May 2025 19:53:01 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=AE=8C=E6=88=90=E4=BA=86<=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=B2=BE=E5=AF=B9=E9=BD=90>=E7=9A=84=E6=89=80?= =?UTF-8?q?=E6=9C=89=E4=BB=A3=E7=A0=81=EF=BC=8C=E4=BF=AE=E5=A4=8D=E4=BA=86?= =?UTF-8?q?=E9=83=A8=E5=88=86=E5=86=85=E5=AE=B9=202=E3=80=81=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=91=BD=E5=90=8D=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- func/Module_detect_Jpeak.py | 5 +- func/Module_detect_Rpeak.py | 5 +- func/Module_label_check.py | 5 +- func/Module_precisely_align.py | 428 ++++++++++++++---- func/Module_preprocess.py | 6 +- func/utils/ConfigParams.py | 36 +- func/utils/Constants.py | 29 ++ func/utils/precisely_align_util.py | 465 -------------------- ui/setting/precisely_align_input_setting.py | 182 +++++--- ui/setting/precisely_align_input_setting.ui | 154 +++++-- 数据结构化输入和输出命名规范.md | 187 ++++++++ 11 files changed, 827 insertions(+), 675 deletions(-) delete mode 100644 func/utils/precisely_align_util.py create mode 100644 数据结构化输入和输出命名规范.md diff --git a/func/Module_detect_Jpeak.py b/func/Module_detect_Jpeak.py index aa93d0a..91df024 100644 --- a/func/Module_detect_Jpeak.py +++ b/func/Module_detect_Jpeak.py @@ -358,7 +358,7 @@ class MainWindow_detect_Jpeak(QMainWindow): # 保存 PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0) - # status, info = self.data.save() + total_rows = len(DataFrame(self.data.peak.reshape(-1))) chunk_size = ConfigParams.DETECT_JPEAK_SAVE_CHUNK_SIZE with open(Config["Path"]["Save"], 'w') as f: @@ -463,9 +463,6 @@ class Data: return False, Constants.SAVING_FAILURE + Constants.DETECT_JPEAK_FAILURE_REASON["Peak_Not_Exist"] try: - # DataFrame(self.processed_data.reshape(-1)).to_csv(self.file_path_save, - # index=False, - # header=False) chunk.to_csv(self.file_path_save, mode='a', index=False, header=False) except Exception: return False, Constants.SAVING_FAILURE + Constants.DETECT_JPEAK_FAILURE_REASON["Save_Exception"] diff --git a/func/Module_detect_Rpeak.py b/func/Module_detect_Rpeak.py index f9ce3a1..6c35c67 100644 --- a/func/Module_detect_Rpeak.py +++ b/func/Module_detect_Rpeak.py @@ -357,7 +357,7 @@ class MainWindow_detect_Rpeak(QMainWindow): # 保存 PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0) - # status, info = self.data.save() + total_rows = len(DataFrame(self.data.peak.reshape(-1))) chunk_size = ConfigParams.DETECT_RPEAK_SAVE_CHUNK_SIZE with open(Config["Path"]["Save"], 'w') as f: @@ -458,9 +458,6 @@ class Data: return False, Constants.SAVING_FAILURE + Constants.DETECT_RPEAK_FAILURE_REASON["Peak_Not_Exist"] try: - # DataFrame(self.processed_data.reshape(-1)).to_csv(self.file_path_save, - # index=False, - # header=False) chunk.to_csv(self.file_path_save, mode='a', index=False, header=False) except Exception: return False, Constants.SAVING_FAILURE + Constants.DETECT_RPEAK_FAILURE_REASON["Save_Exception"] diff --git a/func/Module_label_check.py b/func/Module_label_check.py index 687cd9d..7b79b5e 100644 --- a/func/Module_label_check.py +++ b/func/Module_label_check.py @@ -536,7 +536,7 @@ class MainWindow_label_check(QMainWindow): # 保存 PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0) - # status, info = self.data.save() + total_rows = len(DataFrame(self.data.corrected_peak.reshape(-1))) chunk_size = ConfigParams.LABEL_CHECK_SAVE_CHUNK_SIZE with open(Config["Path"]["Save"], 'w') as f: @@ -968,9 +968,6 @@ class Data: return False, Constants.SAVING_FAILURE + Constants.LABEL_CHECK_FAILURE_REASON["Peak_Not_Exist"] try: - # DataFrame(self.corrected_peak.reshape(-1)).to_csv(self.file_path_save, - # index=False, - # header=False) chunk.to_csv(self.file_path_save, mode='a', index=False, header=False) except Exception: return False, Constants.SAVING_FAILURE + Constants.LABEL_CHECK_FAILURE_REASON["Save_Exception"] diff --git a/func/Module_precisely_align.py b/func/Module_precisely_align.py index 3c25974..20dcb73 100644 --- a/func/Module_precisely_align.py +++ b/func/Module_precisely_align.py @@ -111,26 +111,48 @@ class SettingWindow(QMainWindow): Config.update({ "Path": { + "Input_orgBcg": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT / + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_INPUT_ORGBCG_FILENAME + + str(Config["InputConfig"]["ECGFreq"]) + + ConfigParams.ENDSWITH_TXT))), "Input_BCG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT / - Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_INPUT_BCG_FILENAME + - str(Config["InputConfig"]["ECGFreq"]) + - ConfigParams.ENDSWITH_TXT))), - "Input_Jpeak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT / - Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_INPUT_JPEAK_FILENAME + + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_INPUT_BCG_FILENAME + + str(Config["InputConfig"]["ECGFreq"]) + ConfigParams.ENDSWITH_TXT))), + "Input_Jpeak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT / + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_INPUT_JPEAK_FILENAME + + ConfigParams.ENDSWITH_TXT))), "Input_ECG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT / - Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_INPUT_ECG_FILENAME + - str(Config["InputConfig"]["ECGFreq"]) + - ConfigParams.ENDSWITH_TXT))), + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_INPUT_ECG_FILENAME + + str(Config["InputConfig"]["ECGFreq"]) + + ConfigParams.ENDSWITH_TXT))), "Input_Rpeak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT / Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_INPUT_RPEAK_FILENAME + ConfigParams.ENDSWITH_TXT))), + "Save_BCG_AlignInfo": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED / + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_SAVE_BCG_ALIGNINFO_FILENAME + + ConfigParams.ENDSWITH_TXT))), + "Save_ECG_AlignInfo": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED / + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_SAVE_ECG_ALIGNINFO_FILENAME + + ConfigParams.ENDSWITH_TXT))), + "Save_orgBcg": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED / + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_SAVE_ORGBCG_FILENAME + + str(Config["InputConfig"]["ECGFreq"]) + + ConfigParams.ENDSWITH_TXT))), "Save_BCG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED / - Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_SAVE_BCG_FILENAME + - ConfigParams.ENDSWITH_TXT))), + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_SAVE_BCG_FILENAME + + str(Config["InputConfig"]["ECGFreq"]) + + ConfigParams.ENDSWITH_TXT))), "Save_ECG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED / Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_SAVE_ECG_FILENAME + - ConfigParams.ENDSWITH_TXT))) + str(Config["InputConfig"]["ECGFreq"]) + + ConfigParams.ENDSWITH_TXT))), + "Save_Jpeak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED / + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_SAVE_JPEAK_FILENAME + + ConfigParams.ENDSWITH_TXT))), + "Save_Rpeak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED / + Path(str(self.sampID)) / Path(ConfigParams.PRECISELY_ALIGN_SAVE_RPEAK_FILENAME + + ConfigParams.ENDSWITH_TXT))) }, "Coordinate": { "BCG_front_1": 0, @@ -177,23 +199,35 @@ class SettingWindow(QMainWindow): # 数据回显 self.ui.spinBox_input_freq_ECG.setValue(Config["InputConfig"]["ECGFreq"]) + self.ui.plainTextEdit_file_path_input_orgBcg.setPlainText(Config["Path"]["Input_orgBcg"]) self.ui.plainTextEdit_file_path_input_BCG.setPlainText(Config["Path"]["Input_BCG"]) self.ui.plainTextEdit_file_path_input_Jpeak.setPlainText(Config["Path"]["Input_Jpeak"]) self.ui.plainTextEdit_file_path_input_ECG.setPlainText(Config["Path"]["Input_ECG"]) self.ui.plainTextEdit_file_path_input_Rpeak.setPlainText(Config["Path"]["Input_Rpeak"]) + self.ui.plainTextEdit_file_path_save_BCG_AlignInfo.setPlainText(Config["Path"]["Save_BCG_AlignInfo"]) + self.ui.plainTextEdit_file_path_save_ECG_AlignInfo.setPlainText(Config["Path"]["Save_ECG_AlignInfo"]) + self.ui.plainTextEdit_file_path_save_orgBcg.setPlainText(Config["Path"]["Save_orgBcg"]) self.ui.plainTextEdit_file_path_save_BCG.setPlainText(Config["Path"]["Save_BCG"]) self.ui.plainTextEdit_file_path_save_ECG.setPlainText(Config["Path"]["Save_ECG"]) + self.ui.plainTextEdit_file_path_save_Jpeak.setPlainText(Config["Path"]["Save_Jpeak"]) + self.ui.plainTextEdit_file_path_save_Rpeak.setPlainText(Config["Path"]["Save_Rpeak"]) def __write_config__(self): # 从界面写入配置 Config["InputConfig"]["ECGFreq"] = self.ui.spinBox_input_freq_ECG.value() + Config["Path"]["Input_orgBcg"] = self.ui.plainTextEdit_file_path_input_orgBcg.toPlainText() Config["Path"]["Input_BCG"] = self.ui.plainTextEdit_file_path_input_BCG.toPlainText() Config["Path"]["Input_Jpeak"] = self.ui.plainTextEdit_file_path_input_Jpeak.toPlainText() Config["Path"]["Input_ECG"] = self.ui.plainTextEdit_file_path_input_ECG.toPlainText() Config["Path"]["Input_Rpeak"] = self.ui.plainTextEdit_file_path_input_Rpeak.toPlainText() + Config["Path"]["Save_BCG_AlignInfo"] = self.ui.plainTextEdit_file_path_save_BCG_AlignInfo.toPlainText() + Config["Path"]["Save_ECG_AlignInfo"] = self.ui.plainTextEdit_file_path_save_ECG_AlignInfo.toPlainText() + Config["Path"]["Save_orgBcg"] = self.ui.plainTextEdit_file_path_save_orgBcg.toPlainText() Config["Path"]["Save_BCG"] = self.ui.plainTextEdit_file_path_save_BCG.toPlainText() Config["Path"]["Save_ECG"] = self.ui.plainTextEdit_file_path_save_ECG.toPlainText() + Config["Path"]["Save_Jpeak"] = self.ui.plainTextEdit_file_path_save_Jpeak.toPlainText() + Config["Path"]["Save_Rpeak"] = self.ui.plainTextEdit_file_path_save_Rpeak.toPlainText() # 保存配置到文件 self.config["InputConfig"]["ECGFreq"] = self.ui.spinBox_input_freq_ECG.value() @@ -209,6 +243,13 @@ class SettingWindow(QMainWindow): def __update_ui__(self): + self.ui.plainTextEdit_file_path_input_orgBcg.setPlainText( + str((Path(self.root_path) / + ConfigParams.PUBLIC_PATH_ORGBCG_TEXT / + Path(str(self.sampID)) / + Path(ConfigParams.PRECISELY_ALIGN_INPUT_ORGBCG_FILENAME + + str(self.ui.spinBox_input_freq_ECG.value()) + + ConfigParams.ENDSWITH_TXT)))) self.ui.plainTextEdit_file_path_input_BCG.setPlainText( str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT / @@ -223,6 +264,39 @@ class SettingWindow(QMainWindow): Path(ConfigParams.PRECISELY_ALIGN_INPUT_ECG_FILENAME + str(self.ui.spinBox_input_freq_ECG.value()) + ConfigParams.ENDSWITH_TXT)))) + self.ui.plainTextEdit_file_path_save_orgBcg.setPlainText( + str((Path(self.root_path) / + ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED / + Path(str(self.sampID)) / + Path(ConfigParams.PRECISELY_ALIGN_SAVE_ORGBCG_FILENAME + + str(self.ui.spinBox_input_freq_ECG.value()) + + ConfigParams.ENDSWITH_TXT)))) + self.ui.plainTextEdit_file_path_save_BCG.setPlainText( + str((Path(self.root_path) / + ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED / + Path(str(self.sampID)) / + Path(ConfigParams.PRECISELY_ALIGN_SAVE_BCG_FILENAME + + str(self.ui.spinBox_input_freq_ECG.value()) + + ConfigParams.ENDSWITH_TXT)))) + self.ui.plainTextEdit_file_path_save_ECG.setPlainText( + str((Path(self.root_path) / + ConfigParams.PUBLIC_PATH_PSG_ALIGNED / + Path(str(self.sampID)) / + Path(ConfigParams.PRECISELY_ALIGN_SAVE_ECG_FILENAME + + str(self.ui.spinBox_input_freq_ECG.value()) + + ConfigParams.ENDSWITH_TXT)))) + self.ui.plainTextEdit_file_path_save_Jpeak.setPlainText( + str((Path(self.root_path) / + ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED / + Path(str(self.sampID)) / + Path(ConfigParams.PRECISELY_ALIGN_SAVE_JPEAK_FILENAME + + ConfigParams.ENDSWITH_TXT)))) + self.ui.plainTextEdit_file_path_save_Rpeak.setPlainText( + str((Path(self.root_path) / + ConfigParams.PUBLIC_PATH_PSG_ALIGNED / + Path(str(self.sampID)) / + Path(ConfigParams.PRECISELY_ALIGN_SAVE_RPEAK_FILENAME + + ConfigParams.ENDSWITH_TXT)))) class MainWindow_precisely_align(QMainWindow): @@ -745,77 +819,190 @@ class MainWindow_precisely_align(QMainWindow): if reply == QMessageBox.Yes: PublicFunc.__disableAllButton__(self, ButtonState) - # 保存 - PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0) - status, info = self.data.save() + # 保存对齐信息 + PublicFunc.progressbar_update(self, 1, 6, Constants.PRECISELY_ALIGN_SAVING_ALIGNINFO, 0) + status, info = self.data.save_alignInfo() if not status: - PublicFunc.text_output(self.ui, "(1/1)" + info, Constants.TIPS_TYPE_ERROR) + PublicFunc.text_output(self.ui, "(1/6)" + info, Constants.TIPS_TYPE_ERROR) PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR) PublicFunc.finish_operation(self, ButtonState) return else: - PublicFunc.text_output(self.ui, "(1/1)" + info, Constants.TIPS_TYPE_INFO) - PublicFunc.msgbox_output(self, info, Constants.TIPS_TYPE_INFO) + PublicFunc.text_output(self.ui, "(1/6)" + info, Constants.TIPS_TYPE_INFO) + + # 保存切割后orgBcg + PublicFunc.progressbar_update(self, 2, 6, Constants.PRECISELY_ALIGN_SAVING_RES_ORGBCG, 0) + + total_rows = len(DataFrame(self.data.res_orgBcg.reshape(-1))) + chunk_size = ConfigParams.PRECISELY_ALIGN_SAVE_CHUNK_SIZE + with open(Config["Path"]["Save_orgBcg"], 'w') as f: + for start in range(0, total_rows, chunk_size): + end = min(start + chunk_size, total_rows) + chunk = DataFrame(self.data.res_orgBcg.reshape(-1)).iloc[start:end] + status, info = self.data.save_res_orgBcg(chunk) + progress = int((end / total_rows) * 100) + self.progressbar.setValue(progress) + QApplication.processEvents() + + if not status: + PublicFunc.text_output(self.ui, "(2/6)" + info, Constants.TIPS_TYPE_ERROR) + PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR) + PublicFunc.finish_operation(self, ButtonState) + return + else: + PublicFunc.text_output(self.ui, "(2/6)" + info, Constants.TIPS_TYPE_INFO) + + # 保存切割后BCG + PublicFunc.progressbar_update(self, 3, 6, Constants.PRECISELY_ALIGN_SAVING_RES_BCG, 0) + + total_rows = len(DataFrame(self.data.res_BCG.reshape(-1))) + chunk_size = ConfigParams.PRECISELY_ALIGN_SAVE_CHUNK_SIZE + with open(Config["Path"]["Save_orgBcg"], 'w') as f: + for start in range(0, total_rows, chunk_size): + end = min(start + chunk_size, total_rows) + chunk = DataFrame(self.data.res_BCG.reshape(-1)).iloc[start:end] + status, info = self.data.save_res_BCG(chunk) + progress = int((end / total_rows) * 100) + self.progressbar.setValue(progress) + QApplication.processEvents() + + if not status: + PublicFunc.text_output(self.ui, "(3/6)" + info, Constants.TIPS_TYPE_ERROR) + PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR) + PublicFunc.finish_operation(self, ButtonState) + return + else: + PublicFunc.text_output(self.ui, "(3/6)" + info, Constants.TIPS_TYPE_INFO) + + # 保存切割后ECG + PublicFunc.progressbar_update(self, 4, 6, Constants.PRECISELY_ALIGN_SAVING_CUT_ECG, 0) + + total_rows = len(DataFrame(self.data.cut_ECG.reshape(-1))) + chunk_size = ConfigParams.PRECISELY_ALIGN_SAVE_CHUNK_SIZE + with open(Config["Path"]["Save_ECG"], 'w') as f: + for start in range(0, total_rows, chunk_size): + end = min(start + chunk_size, total_rows) + chunk = DataFrame(self.data.cut_ECG.reshape(-1)).iloc[start:end] + status, info = self.data.save_cut_ECG(chunk) + progress = int((end / total_rows) * 100) + self.progressbar.setValue(progress) + QApplication.processEvents() + + if not status: + PublicFunc.text_output(self.ui, "(4/6)" + info, Constants.TIPS_TYPE_ERROR) + PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR) + PublicFunc.finish_operation(self, ButtonState) + return + else: + PublicFunc.text_output(self.ui, "(4/6)" + info, Constants.TIPS_TYPE_INFO) + + # 保存切割后J峰 + PublicFunc.progressbar_update(self, 5, 6, Constants.PRECISELY_ALIGN_SAVING_CUT_JPEAK, 0) + + total_rows = len(DataFrame(self.data.cut_Jpeak.reshape(-1))) + chunk_size = ConfigParams.PRECISELY_ALIGN_SAVE_PEAK_CHUNK_SIZE + with open(Config["Path"]["Save_Jpeak"], 'w') as f: + for start in range(0, total_rows, chunk_size): + end = min(start + chunk_size, total_rows) + chunk = DataFrame(self.data.cut_Jpeak.reshape(-1)).iloc[start:end] + status, info = self.data.save_Jpeak(chunk) + progress = int((end / total_rows) * 100) + self.progressbar.setValue(progress) + QApplication.processEvents() + + if not status: + PublicFunc.text_output(self.ui, "(5/6)" + info, Constants.TIPS_TYPE_ERROR) + PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR) + PublicFunc.finish_operation(self, ButtonState) + return + else: + PublicFunc.text_output(self.ui, "(5/6)" + info, Constants.TIPS_TYPE_INFO) + + # 保存切割后R峰 + PublicFunc.progressbar_update(self, 6, 6, Constants.PRECISELY_ALIGN_SAVING_CUT_RPEAK, 0) + + total_rows = len(DataFrame(self.data.cut_Rpeak.reshape(-1))) + chunk_size = ConfigParams.PRECISELY_ALIGN_SAVE_PEAK_CHUNK_SIZE + with open(Config["Path"]["Save_Rpeak"], 'w') as f: + for start in range(0, total_rows, chunk_size): + end = min(start + chunk_size, total_rows) + chunk = DataFrame(self.data.cut_Rpeak.reshape(-1)).iloc[start:end] + status, info = self.data.save_Rpeak(chunk) + progress = int((end / total_rows) * 100) + self.progressbar.setValue(progress) + QApplication.processEvents() + + if not status: + PublicFunc.text_output(self.ui, "(6/6)" + info, Constants.TIPS_TYPE_ERROR) + PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR) + PublicFunc.finish_operation(self, ButtonState) + return + else: + PublicFunc.text_output(self.ui, "(6/6)" + info, Constants.TIPS_TYPE_INFO) + PublicFunc.msgbox_output(self, Constants.SAVING_FINISHED, Constants.TIPS_TYPE_INFO) PublicFunc.finish_operation(self, ButtonState) def __update_coordinate__(self): - if self.data is not None: - if self.data.Jpeak is None or self.data.Rpeak is None: - PublicFunc.msgbox_output(self, Constants.PRECISELY_ALIGN_FAILURE_REASON["Data_Not_Exist"], Constants.MSGBOX_TYPE_ERROR) - return + try: + if self.data is not None: + if self.data.Jpeak is None or self.data.Rpeak is None: + PublicFunc.msgbox_output(self, Constants.PRECISELY_ALIGN_FAILURE_REASON["Data_Not_Exist"], Constants.MSGBOX_TYPE_ERROR) + return - sender = self.sender() + sender = self.sender() - if sender == self.ui.spinBox_BCG_front_JJIV_1: - if self.ui.spinBox_BCG_front_JJIV_1.value() >= len(self.data.Jpeak[:-2]): - self.ui.spinBox_BCG_front_JJIV_1.setValue(len(self.data.Jpeak[:-2]) - 1) - Config["IV_Coordinate"]["BCG_front_1"] = self.ui.spinBox_BCG_front_JJIV_1.value() - Config["Coordinate"]["BCG_front_1"] = self.data.Jpeak[:-2][self.ui.spinBox_BCG_front_JJIV_1.value()] - self.ui.spinBox_BCG_front_Signal_1.setValue(Config["Coordinate"]["BCG_front_1"]) - elif sender == self.ui.spinBox_BCG_front_JJIV_2: - if self.ui.spinBox_BCG_front_JJIV_2.value() >= len(self.data.Jpeak[:-2]): - self.ui.spinBox_BCG_front_JJIV_2.setValue(len(self.data.Jpeak[:-2]) - 1) - Config["IV_Coordinate"]["BCG_front_2"] = self.ui.spinBox_BCG_front_JJIV_2.value() - Config["Coordinate"]["BCG_front_2"] = self.data.Jpeak[:-2][self.ui.spinBox_BCG_front_JJIV_2.value()] - self.ui.spinBox_BCG_front_Signal_2.setValue(Config["Coordinate"]["BCG_front_2"]) - elif sender == self.ui.spinBox_BCG_back_JJIV_1: - if self.ui.spinBox_BCG_back_JJIV_1.value() >= len(self.data.Jpeak[:-2]): - self.ui.spinBox_BCG_back_JJIV_1.setValue(len(self.data.Jpeak[:-2]) - 1) - Config["IV_Coordinate"]["BCG_back_1"] = self.ui.spinBox_BCG_back_JJIV_1.value() - Config["Coordinate"]["BCG_back_1"] = self.data.Jpeak[:-2][self.ui.spinBox_BCG_back_JJIV_1.value()] - self.ui.spinBox_BCG_back_Signal_1.setValue(Config["Coordinate"]["BCG_back_1"]) - elif sender == self.ui.spinBox_BCG_back_JJIV_2: - if self.ui.spinBox_BCG_back_JJIV_2.value() >= len(self.data.Jpeak[:-2]): - self.ui.spinBox_BCG_back_JJIV_2.setValue(len(self.data.Jpeak[:-2]) - 1) - Config["IV_Coordinate"]["BCG_back_2"] = self.ui.spinBox_BCG_back_JJIV_2.value() - Config["Coordinate"]["BCG_back_2"] = self.data.Jpeak[:-2][self.ui.spinBox_BCG_back_JJIV_2.value()] - self.ui.spinBox_BCG_back_Signal_2.setValue(Config["Coordinate"]["BCG_back_2"]) - elif sender == self.ui.spinBox_ECG_front_RRIV_1: - if self.ui.spinBox_ECG_front_RRIV_1.value() >= len(self.data.Rpeak[:-2]): - self.ui.spinBox_ECG_front_RRIV_1.setValue(len(self.data.Rpeak[:-2]) - 1) - Config["IV_Coordinate"]["ECG_front_1"] = self.ui.spinBox_ECG_front_RRIV_1.value() - Config["Coordinate"]["ECG_front_1"] = self.data.Rpeak[:-2][self.ui.spinBox_ECG_front_RRIV_1.value()] - self.ui.spinBox_ECG_front_Signal_1.setValue(Config["Coordinate"]["ECG_front_1"]) - elif sender == self.ui.spinBox_ECG_front_RRIV_2: - if self.ui.spinBox_ECG_front_RRIV_2.value() >= len(self.data.Rpeak[:-2]): - self.ui.spinBox_ECG_front_RRIV_2.setValue(len(self.data.Rpeak[:-2]) - 1) - Config["IV_Coordinate"]["ECG_front_2"] = self.ui.spinBox_ECG_front_RRIV_2.value() - Config["Coordinate"]["ECG_front_2"] = self.data.Rpeak[:-2][self.ui.spinBox_ECG_front_RRIV_2.value()] - self.ui.spinBox_ECG_front_Signal_2.setValue(Config["Coordinate"]["ECG_front_2"]) - elif sender == self.ui.spinBox_ECG_back_RRIV_1: - if self.ui.spinBox_ECG_back_RRIV_1.value() >= len(self.data.Rpeak[:-2]): - self.ui.spinBox_ECG_back_RRIV_1.setValue(len(self.data.Rpeak[:-2]) - 1) - Config["IV_Coordinate"]["ECG_back_1"] = self.ui.spinBox_ECG_back_RRIV_1.value() - Config["Coordinate"]["ECG_back_1"] = self.data.Rpeak[:-2][self.ui.spinBox_ECG_back_RRIV_1.value()] - self.ui.spinBox_ECG_back_Signal_1.setValue(Config["Coordinate"]["ECG_back_1"]) - elif sender == self.ui.spinBox_ECG_back_RRIV_2: - if self.ui.spinBox_ECG_back_RRIV_2.value() >= len(self.data.Rpeak[:-2]): - self.ui.spinBox_ECG_back_RRIV_2.setValue(len(self.data.Rpeak[:-2]) - 1) - Config["IV_Coordinate"]["ECG_back_2"] = self.ui.spinBox_ECG_back_RRIV_2.value() - Config["Coordinate"]["ECG_back_2"] = self.data.Rpeak[:-2][self.ui.spinBox_ECG_back_RRIV_2.value()] - self.ui.spinBox_ECG_back_Signal_2.setValue(Config["Coordinate"]["ECG_back_2"]) + if sender == self.ui.spinBox_BCG_front_JJIV_1: + if self.ui.spinBox_BCG_front_JJIV_1.value() >= len(self.data.Jpeak[:-2]): + self.ui.spinBox_BCG_front_JJIV_1.setValue(len(self.data.Jpeak[:-2]) - 1) + Config["IV_Coordinate"]["BCG_front_1"] = self.ui.spinBox_BCG_front_JJIV_1.value() + Config["Coordinate"]["BCG_front_1"] = self.data.Jpeak[:-2][self.ui.spinBox_BCG_front_JJIV_1.value()] + self.ui.spinBox_BCG_front_Signal_1.setValue(Config["Coordinate"]["BCG_front_1"]) + elif sender == self.ui.spinBox_BCG_front_JJIV_2: + if self.ui.spinBox_BCG_front_JJIV_2.value() >= len(self.data.Jpeak[:-2]): + self.ui.spinBox_BCG_front_JJIV_2.setValue(len(self.data.Jpeak[:-2]) - 1) + Config["IV_Coordinate"]["BCG_front_2"] = self.ui.spinBox_BCG_front_JJIV_2.value() + Config["Coordinate"]["BCG_front_2"] = self.data.Jpeak[:-2][self.ui.spinBox_BCG_front_JJIV_2.value()] + self.ui.spinBox_BCG_front_Signal_2.setValue(Config["Coordinate"]["BCG_front_2"]) + elif sender == self.ui.spinBox_BCG_back_JJIV_1: + if self.ui.spinBox_BCG_back_JJIV_1.value() >= len(self.data.Jpeak[:-2]): + self.ui.spinBox_BCG_back_JJIV_1.setValue(len(self.data.Jpeak[:-2]) - 1) + Config["IV_Coordinate"]["BCG_back_1"] = self.ui.spinBox_BCG_back_JJIV_1.value() + Config["Coordinate"]["BCG_back_1"] = self.data.Jpeak[:-2][self.ui.spinBox_BCG_back_JJIV_1.value()] + self.ui.spinBox_BCG_back_Signal_1.setValue(Config["Coordinate"]["BCG_back_1"]) + elif sender == self.ui.spinBox_BCG_back_JJIV_2: + if self.ui.spinBox_BCG_back_JJIV_2.value() >= len(self.data.Jpeak[:-2]): + self.ui.spinBox_BCG_back_JJIV_2.setValue(len(self.data.Jpeak[:-2]) - 1) + Config["IV_Coordinate"]["BCG_back_2"] = self.ui.spinBox_BCG_back_JJIV_2.value() + Config["Coordinate"]["BCG_back_2"] = self.data.Jpeak[:-2][self.ui.spinBox_BCG_back_JJIV_2.value()] + self.ui.spinBox_BCG_back_Signal_2.setValue(Config["Coordinate"]["BCG_back_2"]) + elif sender == self.ui.spinBox_ECG_front_RRIV_1: + if self.ui.spinBox_ECG_front_RRIV_1.value() >= len(self.data.Rpeak[:-2]): + self.ui.spinBox_ECG_front_RRIV_1.setValue(len(self.data.Rpeak[:-2]) - 1) + Config["IV_Coordinate"]["ECG_front_1"] = self.ui.spinBox_ECG_front_RRIV_1.value() + Config["Coordinate"]["ECG_front_1"] = self.data.Rpeak[:-2][self.ui.spinBox_ECG_front_RRIV_1.value()] + self.ui.spinBox_ECG_front_Signal_1.setValue(Config["Coordinate"]["ECG_front_1"]) + elif sender == self.ui.spinBox_ECG_front_RRIV_2: + if self.ui.spinBox_ECG_front_RRIV_2.value() >= len(self.data.Rpeak[:-2]): + self.ui.spinBox_ECG_front_RRIV_2.setValue(len(self.data.Rpeak[:-2]) - 1) + Config["IV_Coordinate"]["ECG_front_2"] = self.ui.spinBox_ECG_front_RRIV_2.value() + Config["Coordinate"]["ECG_front_2"] = self.data.Rpeak[:-2][self.ui.spinBox_ECG_front_RRIV_2.value()] + self.ui.spinBox_ECG_front_Signal_2.setValue(Config["Coordinate"]["ECG_front_2"]) + elif sender == self.ui.spinBox_ECG_back_RRIV_1: + if self.ui.spinBox_ECG_back_RRIV_1.value() >= len(self.data.Rpeak[:-2]): + self.ui.spinBox_ECG_back_RRIV_1.setValue(len(self.data.Rpeak[:-2]) - 1) + Config["IV_Coordinate"]["ECG_back_1"] = self.ui.spinBox_ECG_back_RRIV_1.value() + Config["Coordinate"]["ECG_back_1"] = self.data.Rpeak[:-2][self.ui.spinBox_ECG_back_RRIV_1.value()] + self.ui.spinBox_ECG_back_Signal_1.setValue(Config["Coordinate"]["ECG_back_1"]) + elif sender == self.ui.spinBox_ECG_back_RRIV_2: + if self.ui.spinBox_ECG_back_RRIV_2.value() >= len(self.data.Rpeak[:-2]): + self.ui.spinBox_ECG_back_RRIV_2.setValue(len(self.data.Rpeak[:-2]) - 1) + Config["IV_Coordinate"]["ECG_back_2"] = self.ui.spinBox_ECG_back_RRIV_2.value() + Config["Coordinate"]["ECG_back_2"] = self.data.Rpeak[:-2][self.ui.spinBox_ECG_back_RRIV_2.value()] + self.ui.spinBox_ECG_back_Signal_2.setValue(Config["Coordinate"]["ECG_back_2"]) + except AttributeError: + pass def reset_axes(self): @@ -900,6 +1087,8 @@ class MainWindow_precisely_align(QMainWindow): return True, Constants.DRAWING_FINISHED + return False, Constants.DRAWING_FAILURE + def redraw_correlation_align(self, plot_element=None): if plot_element is not None and plot_element["mode"] == "select": @@ -937,6 +1126,8 @@ class MainWindow_precisely_align(QMainWindow): return True, Constants.DRAWING_FINISHED + return False, Constants.DRAWING_FAILURE + def toggle_home(self): if self.ax0 is not None: @@ -1217,16 +1408,25 @@ class MainWindow_precisely_align(QMainWindow): raise ValueError("this_line不存在") self.__slot_btn_correlation_align__() + class Data: def __init__(self): + + self.file_path_input_orgBcg = Config["Path"]["Input_orgBcg"] self.file_path_input_BCG = Config["Path"]["Input_BCG"] self.file_path_input_Jpeak = Config["Path"]["Input_Jpeak"] self.file_path_input_ECG = Config["Path"]["Input_ECG"] self.file_path_input_Rpeak = Config["Path"]["Input_Rpeak"] + self.file_path_save_BCG_AlignInfo = Config["Path"]["Save_BCG_AlignInfo"] + self.file_path_save_ECG_AlignInfo = Config["Path"]["Save_ECG_AlignInfo"] + self.file_path_save_orgBcg = Config["Path"]["Save_orgBcg"] self.file_path_save_BCG = Config["Path"]["Save_BCG"] self.file_path_save_ECG = Config["Path"]["Save_ECG"] + self.file_path_save_Jpeak = Config["Path"]["Save_Jpeak"] + self.file_path_save_Rpeak = Config["Path"]["Save_Rpeak"] + self.raw_orgBcg = None self.raw_BCG = None self.Jpeak = None self.Jpeak_y = None @@ -1234,10 +1434,11 @@ class Data: self.Rpeak = None self.Rpeak_y = None - self.cut_ECG = None + self.res_orgBcg = None self.res_BCG = None - self.cut_Rpeak = None + self.cut_ECG = None self.cut_Jpeak = None + self.cut_Rpeak = None self.RRIs = None self.JJIs = None @@ -1268,6 +1469,9 @@ class Data: return False, Constants.INPUT_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["Data_Path_Not_Exist"] try: + self.raw_orgBcg = read_csv(self.file_path_input_orgBcg, + encoding=ConfigParams.UTF8_ENCODING, + header=None).to_numpy().reshape(-1) self.raw_BCG = read_csv(self.file_path_input_BCG, encoding=ConfigParams.UTF8_ENCODING, header=None).to_numpy().reshape(-1) @@ -1457,8 +1661,9 @@ class Data: orgfs = Config["orgfs"] off = Config["offset_anchor"] - self.cut_ECG = self.raw_ECG + self.res_orgBcg = self.raw_orgBcg self.res_BCG = self.raw_BCG + self.cut_ECG = self.raw_ECG self.cut_Rpeak = self.Rpeak if off > 0: @@ -1469,10 +1674,12 @@ class Data: self.cut_Rpeak = self.cut_Rpeak[idxs] - off else: self.res_BCG = self.res_BCG[-off:] + self.res_orgBcg = self.res_orgBcg[-off:] anchor0[1] = anchor0[1] + off anchor1[1] = anchor1[1] + off self.res_BCG = resample(self.res_BCG, orgfs, Config["InputConfig"]["ECGFreq"]) + self.res_orgBcg = resample(self.res_orgBcg, orgfs, Config["InputConfig"]["ECGFreq"]) anchor0[1] = round(int(anchor0[1]) * Config["InputConfig"]["ECGFreq"] / orgfs) anchor1[1] = round(int(anchor1[1]) * Config["InputConfig"]["ECGFreq"] / orgfs) @@ -1486,12 +1693,14 @@ class Data: self.cut_Rpeak = self.cut_Rpeak[idxs] - off else: self.res_BCG = self.res_BCG[-off:] + self.res_orgBcg = self.res_orgBcg[-off:] anchor0[1] = anchor0[1] + off anchor1[1] = anchor1[1] + off datalen = np_min([len(self.cut_ECG), len(self.res_BCG)]) self.cut_ECG = self.cut_ECG[:datalen] self.res_BCG = self.res_BCG[:datalen] + self.res_orgBcg = self.res_orgBcg[:datalen] a = np_max([np_max(self.cut_ECG), np_max(self.res_BCG)]) b = np_min([np_min(self.cut_ECG), np_min(self.res_BCG)]) peak_ECG, _ = find_peaks(self.cut_ECG) @@ -1544,12 +1753,14 @@ class Data: self.cut_Rpeak = self.cut_Rpeak[where(self.cut_Rpeak > off)[0]] - off else: self.res_BCG = self.res_BCG[-off:] + self.res_orgBcg = self.res_orgBcg[-off:] anchor0[1] = anchor0[1] + off anchor1[1] = anchor1[1] + off datalen = np_min([len(self.cut_ECG), len(self.res_BCG)]) self.cut_ECG = self.cut_ECG[:datalen] self.res_BCG = self.res_BCG[:datalen] + self.res_orgBcg = self.res_orgBcg[:datalen] idxs = where(self.cut_Rpeak < datalen)[0] self.cut_Rpeak = self.cut_Rpeak[idxs] @@ -1573,13 +1784,12 @@ class Data: Config["backcut_index_BCG"] = backcut_index_BCG Config["frontcut_index_ECG"] = frontcut_index_ECG Config["backcut_index_ECG"] = backcut_index_ECG - except Exception: return False, Constants.PRECISELY_ALIGN_POSTPROCESS_VIEW_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["PostProcess_Align_Exception"] return True, f"{Constants.PRECISELY_ALIGN_POSTPROCESS_VIEW_FINISHED},BCG前后段被切割的坐标值为[{frontcut_index_BCG}, {backcut_index_BCG}],ECG前后段被切割的坐标值为[{frontcut_index_ECG}, {backcut_index_ECG}]" - def save(self): + def save_alignInfo(self): try: save_data = { @@ -1613,13 +1823,73 @@ class Data: } } save_data = [str(save_data)] - DataFrame(save_data).to_csv(self.file_path_save_BCG, index=False, header=False) - DataFrame(save_data).to_csv(self.file_path_save_ECG, index=False, header=False) + DataFrame(save_data).to_csv(self.file_path_save_BCG_AlignInfo, index=False, header=False) + DataFrame(save_data).to_csv(self.file_path_save_ECG_AlignInfo, index=False, header=False) except Exception as e: print(e) - return False, Constants.SAVING_FAILURE + Constants.DETECT_RPEAK_FAILURE_REASON["Save_Exception"] + return False, Constants.PRECISELY_ALIGN_SAVING_ALIGNINFO_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["Save_Exception"] - return True, Constants.SAVING_FINISHED + return True, Constants.PRECISELY_ALIGN_SAVING_ALIGNINFO_FINISHED + + def save_res_orgBcg(self, chunk): + + if self.res_orgBcg is None: + return False, Constants.PRECISELY_ALIGN_SAVING_RES_ORGBCG_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["res_orgBcg_Not_Exist"] + + try: + chunk.to_csv(self.file_path_save_orgBcg, mode='a', index=False, header=False) + except Exception: + return False, Constants.PRECISELY_ALIGN_SAVING_RES_ORGBCG_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["Save_Exception"] + + return True, Constants.PRECISELY_ALIGN_SAVING_RES_ORGBCG_FINISHED + + def save_res_BCG(self, chunk): + + if self.res_BCG is None: + return False, Constants.PRECISELY_ALIGN_SAVING_RES_BCG_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["res_BCG_Not_Exist"] + + try: + chunk.to_csv(self.file_path_save_BCG, mode='a', index=False, header=False) + except Exception: + return False, Constants.PRECISELY_ALIGN_SAVING_RES_BCG_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["Save_Exception"] + + return True, Constants.PRECISELY_ALIGN_SAVING_RES_BCG_FINISHED + + def save_cut_ECG(self, chunk): + + if self.cut_ECG is None: + return False, Constants.PRECISELY_ALIGN_SAVING_CUT_ECG_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["cut_ECG_Not_Exist"] + + try: + chunk.to_csv(self.file_path_save_ECG, mode='a', index=False, header=False) + except Exception: + return False, Constants.PRECISELY_ALIGN_SAVING_CUT_ECG_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["Save_Exception"] + + return True, Constants.PRECISELY_ALIGN_SAVING_CUT_ECG_FINISHED + + def save_Jpeak(self, chunk): + + if self.cut_Jpeak is None: + return False, Constants.PRECISELY_ALIGN_SAVING_CUT_JPEAK_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["cut_Jpeak_Not_Exist"] + + try: + chunk.to_csv(self.file_path_save_Jpeak, mode='a', index=False, header=False) + except Exception: + return False, Constants.PRECISELY_ALIGN_SAVING_CUT_JPEAK_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["Save_Exception"] + + return True, Constants.PRECISELY_ALIGN_SAVING_CUT_JPEAK_FINISHED + + def save_Rpeak(self, chunk): + + if self.cut_Rpeak is None: + return False, Constants.PRECISELY_ALIGN_SAVING_CUT_RPEAK_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["cut_Rpeak_Not_Exist"] + + try: + chunk.to_csv(self.file_path_save_Rpeak, mode='a', index=False, header=False) + except Exception: + return False, Constants.PRECISELY_ALIGN_SAVING_CUT_RPEAK_FAILURE + Constants.PRECISELY_ALIGN_FAILURE_REASON["Save_Exception"] + + return True, Constants.PRECISELY_ALIGN_SAVING_CUT_RPEAK_FINISHED class CustomNavigationToolbar(NavigationToolbar2QT): diff --git a/func/Module_preprocess.py b/func/Module_preprocess.py index b927fa0..e0b8b84 100644 --- a/func/Module_preprocess.py +++ b/func/Module_preprocess.py @@ -370,7 +370,7 @@ class MainWindow_preprocess(QMainWindow): # 保存 PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0) - # status, info = self.data.save() + total_rows = len(DataFrame(self.data.processed_data.reshape(-1))) chunk_size = ConfigParams.PREPROCESS_SAVE_CHUNK_SIZE with open(Config["Path"]["Save"], 'w') as f: @@ -459,10 +459,6 @@ class Data: return False, Constants.SAVING_FAILURE + Constants.PREPROCESS_FAILURE_REASON["Processed_Data_Not_Exist"] try: - # DataFrame(self.processed_data.reshape(-1)).to_csv(self.file_path_save, - # index=False, - # header=False, - # float_format='%.4f') chunk.to_csv(self.file_path_save, mode='a', index=False, header=False, float_format='%.4f') except Exception: return False, Constants.SAVING_FAILURE + Constants.PREPROCESS_FAILURE_REASON["Save_Exception"] diff --git a/func/utils/ConfigParams.py b/func/utils/ConfigParams.py index 51fb2de..1061583 100644 --- a/func/utils/ConfigParams.py +++ b/func/utils/ConfigParams.py @@ -51,8 +51,8 @@ class ConfigParams: } PREPROCESS_INPUT_BCG_FILENAME: str = "orgBcg_Raw_" PREPROCESS_INPUT_ECG_FILENAME: str = "ECG I_Raw_" - PREPROCESS_SAVE_BCG_FILENAME: str = "DSbcg_sig_" - PREPROCESS_SAVE_ECG_FILENAME: str = "ECG_filter_" + PREPROCESS_SAVE_BCG_FILENAME: str = "BCG_Raw_" + PREPROCESS_SAVE_ECG_FILENAME: str = "ECG_Raw_" PREPROCESS_SAVE_CHUNK_SIZE: int = 1000000 # BCG的J峰算法定位 @@ -73,7 +73,7 @@ class ConfigParams: "UseCPU": False, "DetectMethod": "" } - DETECT_JPEAK_INPUT_BCG_FILENAME: str = "DSbcg_sig_" + DETECT_JPEAK_INPUT_BCG_FILENAME: str = "BCG_Raw_" DETECT_JPEAK_SAVE_FILENAME: str = "JPeak_revise" DETECT_JPEAK_SAVE_CHUNK_SIZE: int = 100 @@ -90,8 +90,8 @@ class ConfigParams: "PeaksValue": 200, "DetectMethod": "" } - DETECT_RPEAK_INPUT_ECG_FILENAME: str = "ECG_filter_" - DETECT_RPEAK_SAVE_FILENAME: str = "final_Rpeak" + DETECT_RPEAK_INPUT_ECG_FILENAME: str = "ECG_Raw_" + DETECT_RPEAK_SAVE_FILENAME: str = "Rpeak_final" DETECT_RPEAK_SAVE_CHUNK_SIZE: int = 100 # 人工纠正 @@ -118,12 +118,12 @@ class ConfigParams: "MoveSpeed": 1000 } } - LABEL_CHECK_INPUT_BCG_FILENAME: str = "DSbcg_sig_" + LABEL_CHECK_INPUT_BCG_FILENAME: str = "BCG_Raw_" LABEL_CHECK_INPUT_JPEAK_FILENAME: str = "JPeak_revise" LABEL_CHECK_SAVE_JPEAK_FILENAME: str = "JPeak_revise_corrected" - LABEL_CHECK_INPUT_ECG_FILENAME: str = "ECG_filter_" - LABEL_CHECK_INPUT_RPEAK_FILENAME: str = "final_Rpeak" - LABEL_CHECK_SAVE_RPEAK_FILENAME: str = "final_Rpeak_corrected" + LABEL_CHECK_INPUT_ECG_FILENAME: str = "ECG_Raw_" + LABEL_CHECK_INPUT_RPEAK_FILENAME: str = "Rpeak_final" + LABEL_CHECK_SAVE_RPEAK_FILENAME: str = "Rpeak_final_corrected" LABEL_CHECK_SAVE_CHUNK_SIZE: int = 100 LABEL_CHECK_LABEL_TRANSPARENCY: float = 0.2 LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY: str = "Z" @@ -135,13 +135,21 @@ class ConfigParams: "ECGFreq": 1000 } } - PRECISELY_ALIGN_INPUT_BCG_FILENAME: str = "DSbcg_sig_" + PRECISELY_ALIGN_INPUT_ORGBCG_FILENAME: str = "orgBcg_Raw_" + PRECISELY_ALIGN_INPUT_BCG_FILENAME: str = "BCG_Raw_" PRECISELY_ALIGN_INPUT_JPEAK_FILENAME: str = "JPeak_revise_corrected" - PRECISELY_ALIGN_SAVE_BCG_FILENAME: str = "Align_info" - PRECISELY_ALIGN_INPUT_ECG_FILENAME: str = "ECG_filter_" - PRECISELY_ALIGN_INPUT_RPEAK_FILENAME: str = "final_Rpeak_corrected" - PRECISELY_ALIGN_SAVE_ECG_FILENAME: str = "Align_info" + PRECISELY_ALIGN_SAVE_BCG_ALIGNINFO_FILENAME: str = "Align_info" + PRECISELY_ALIGN_INPUT_ECG_FILENAME: str = "ECG_Raw_" + PRECISELY_ALIGN_INPUT_RPEAK_FILENAME: str = "Rpeak_final_corrected" + PRECISELY_ALIGN_SAVE_ECG_ALIGNINFO_FILENAME: str = "Align_info" + PRECISELY_ALIGN_SAVE_ORGBCG_FILENAME: str = "orgBcg_Sync_" + PRECISELY_ALIGN_SAVE_BCG_FILENAME: str = "BCG_Sync_" + PRECISELY_ALIGN_SAVE_ECG_FILENAME: str = "ECG_Sync_" + PRECISELY_ALIGN_SAVE_JPEAK_FILENAME: str = "JPeak_Sync" + PRECISELY_ALIGN_SAVE_RPEAK_FILENAME: str = "Rpeak_Sync" PRECISELY_ALIGN_ACTION_GET_RANGE_SHORTCUT_KEY: str = "Z" + PRECISELY_ALIGN_SAVE_CHUNK_SIZE: int = 1000000 + PRECISELY_ALIGN_SAVE_PEAK_CHUNK_SIZE: int = 100 # 体动标注 diff --git a/func/utils/Constants.py b/func/utils/Constants.py index 2487567..435c123 100644 --- a/func/utils/Constants.py +++ b/func/utils/Constants.py @@ -216,6 +216,30 @@ class Constants: PRECISELY_ALIGN_POSTPROCESS_VIEW_FINISHED: str = "数据后处理完成" PRECISELY_ALIGN_POSTPROCESS_VIEW_FAILURE: str = "数据后处理失败" + PRECISELY_ALIGN_SAVING_ALIGNINFO: str = "正在保存对齐信息" + PRECISELY_ALIGN_SAVING_ALIGNINFO_FINISHED: str = "保存对齐信息完成" + PRECISELY_ALIGN_SAVING_ALIGNINFO_FAILURE: str = "保存对齐信息失败" + + PRECISELY_ALIGN_SAVING_RES_ORGBCG: str = "正在保存切割后orgBcg" + PRECISELY_ALIGN_SAVING_RES_ORGBCG_FINISHED: str = "保存切割后orgBcg完成" + PRECISELY_ALIGN_SAVING_RES_ORGBCG_FAILURE: str = "保存切割后orgBcg失败" + + PRECISELY_ALIGN_SAVING_RES_BCG: str = "正在保存切割后BCG" + PRECISELY_ALIGN_SAVING_RES_BCG_FINISHED: str = "保存切割后BCG完成" + PRECISELY_ALIGN_SAVING_RES_BCG_FAILURE: str = "保存切割后BCG失败" + + PRECISELY_ALIGN_SAVING_CUT_ECG: str = "正在保存切割后ECG" + PRECISELY_ALIGN_SAVING_CUT_ECG_FINISHED: str = "保存切割后ECG完成" + PRECISELY_ALIGN_SAVING_CUT_ECG_FAILURE: str = "保存切割后ECG失败" + + PRECISELY_ALIGN_SAVING_CUT_JPEAK: str = "正在保存切割后J峰" + PRECISELY_ALIGN_SAVING_CUT_JPEAK_FINISHED: str = "保存切割后J峰完成" + PRECISELY_ALIGN_SAVING_CUT_JPEAK_FAILURE: str = "保存切割后J峰失败" + + PRECISELY_ALIGN_SAVING_CUT_RPEAK: str = "正在保存切割后R峰" + PRECISELY_ALIGN_SAVING_CUT_RPEAK_FINISHED: str = "保存切割后R峰完成" + PRECISELY_ALIGN_SAVING_CUT_RPEAK_FAILURE: str = "保存切割后R峰失败" + PRECISELY_ALIGN_FAILURE_REASON = { "Data_Path_Not_Exist": "(数据路径不存在)", "Read_Data_Exception": "(读取数据异常)", @@ -226,6 +250,11 @@ class Constants: "Calculate_Correlation_Exception": "(计算相关性异常)", "Correlation_Align_Exception": "(处理相关对齐异常)", "PostProcess_Align_Exception": "(数据后处理异常)", + "res_orgBcg_Not_Exist": "(切割后orgBcg不存在)", + "res_BCG_Not_Exist": "(切割后BCG不存在)", + "cut_ECG_Not_Exist": "(切割后ECG不存在)", + "cut_Jpeak_Not_Exist": "(切割后J峰不存在)", + "cut_Rpeak_Not_Exist": "(切割后R峰不存在)", "Save_Exception": "(保存异常)" } diff --git a/func/utils/precisely_align_util.py b/func/utils/precisely_align_util.py deleted file mode 100644 index 3f6252f..0000000 --- a/func/utils/precisely_align_util.py +++ /dev/null @@ -1,465 +0,0 @@ -import os -import shutil -import pandas as pd - -from resampy import resample -from scipy import signal - - -import numpy as np -import matplotlib.pyplot as plt - -def read_data(root): - orgBCGpath = os.path.join(root, 'raw_org.txt') - BCGpath = os.path.join(root, 'DSbcg_sig_1000hz3.txt') - ECGpath = os.path.join(root, 'filter_ecg.txt') - Jpeakspath = os.path.join(root, 'Jpeak.txt') - Rpeakspath = os.path.join(root, 'final_Rpeak.txt') - - orgBCG = np.array(pd.read_csv(orgBCGpath, header=None)).reshape(-1) - # B, A = signal.butter(4, np.array([2,8])*2/1000, 'bandpass') - # BCG = signal.filtfilt(B, A, orgBCG) - BCG = np.array(pd.read_csv(BCGpath)).reshape(-1) - ECG = np.array(pd.read_csv(ECGpath, header=None)).reshape(-1) - - - Jpeaks = np.loadtxt(Jpeakspath).astype(int) - Rpeaks = np.loadtxt(Rpeakspath).astype(int) - - return orgBCG, BCG, ECG, Jpeaks, Rpeaks - - - -def Align_two_way(Jpeaks, Rpeaks, fs=1000): - def get_info(Jpeaks, Rpeaks): - """ - - :param Jpeaks: - :param Rpeaks: - :return: - """ - RRIs = np.diff(Rpeaks) - JJIs = np.diff(Jpeaks) - RRIVs = np.diff(RRIs) - JJIVs = np.diff(JJIs) - - N_JJIV = get_area(Jpeaks, JJIVs, Rpeaks, RRIVs, title='JJIV') - N_RRIV = get_area(Rpeaks, RRIVs, Jpeaks, JJIVs, N_JJIV=N_JJIV[0], title='RRIV') - JJIs_cut = JJIs[N_JJIV[1, 0]: N_JJIV[1, 1]] - RRIs_cut = RRIs[N_RRIV[1, 0]: N_RRIV[1, 1]] - Rpeaks_cut = Rpeaks[N_RRIV[1, 0]:N_RRIV[1, 1] + 2] - Jpeaks_cut = Jpeaks[N_JJIV[1, 0]:N_JJIV[1, 1] + 2] - RRI = np.diff(Rpeaks_cut) - # shift = get_IIV_shift(JJIs_cut, RRIs_cut) - shift, correlation_IIV, correlation_II, total_time_ratio = get_IIV_shift(JJIs_cut, RRIs_cut) - offset_interval = np.sum(RRI[:shift]) - (Jpeaks_cut[0] - Rpeaks_cut[0]) # BCG 相对于ECG的偏移量 - anchor_R = Rpeaks[N_RRIV[1, 0] + shift] - anchor_J = Jpeaks[N_JJIV[1, 0]] - - # info = {'N_JJIV':N_JJIV, 'N_RRIV':N_RRIV, 'shift':shift, 'offset_interval':offset_interval, 'anchors':[anchor_R, anchor_J]} - info = {'N_JJIV': N_JJIV, 'N_RRIV': N_RRIV, 'correlation_IIV': correlation_IIV, - 'correlation_II': correlation_II, 'shift': shift, 'total_time_ratio': total_time_ratio, - 'offset_interval': offset_interval, 'anchors': [anchor_R, anchor_J]} - return info - - info1 = get_info(Jpeaks, Rpeaks) - offset_interval1 = info1['offset_interval'] - anchor1 = info1['anchors'] - offset_interval1_T = offset_interval1 / fs # 前端偏移时间量,大于0 - print("前端对齐的偏移量为:{}s".format(offset_interval1_T)) - - # while True: - info2 = get_info(Jpeaks, Rpeaks) - anchor2 = info2['anchors'] - offset_interval2 = info2['offset_interval'] - offset_interval2_T = offset_interval2 / fs # 后端偏移时间量,大于0 - print("后端对齐的偏移量为:{}s".format(offset_interval2_T)) - - orgfs = (int(anchor2[1]) - int(anchor1[1])) * fs / (int(anchor2[0]) - int(anchor1[0])) - - offset_anchor = anchor1[0] - anchor1[1] - info = {'1': info1, '2': info2, 'offset_anchor': offset_anchor, 'orgfs': orgfs} - - return info - - -################################################ Align utils ############################################################# -def get_area(peaks1_, data1, peaks2_, data2, fs=1000, N_JJIV=None, title='JJIV'): - global N, line0, line1 - - peaks1 = peaks1_[:-2] / fs - peaks2 = peaks2_[:-2] / fs - ylim = [-500, 500] - - '''手动选择区域''' - N = np.array([]).astype(int) - fig, ax = plt.subplots(nrows=2, ncols=1, sharex=True, sharey=True) - ax0, ax1 = ax[0], ax[1] - ax0.set_title(title) - ax0.stem(peaks1, data1, markerfmt='C0.') - line0, = ax0.plot(peaks1, data1, 'o', c='b', markersize=2, picker=True, pickradius=5) - line1, = ax0.plot(peaks1[N], data1[N] + 1, 'v', c='r', picker=True, pickradius=5) - ax0.set_ylim(ylim[0], ylim[1]) - ax0.grid() - ax1.stem(peaks2, data2, markerfmt='C0.') - if N_JJIV is not None: - N_JJIV2 = np.copy(N_JJIV) - N_JJIV2 = N_JJIV2 / fs - ax1.plot([N_JJIV2[0], N_JJIV2[0]], [ylim[0], ylim[1]], 'k--') - ax1.plot([N_JJIV2[1], N_JJIV2[1]], [ylim[0], ylim[1]], 'k--') - ax1.set_ylim(ylim[0], ylim[1]) - - def onpick(event): - global line0, line1 - global N - thisline = event.artist - xdata = thisline.get_xdata() - ind = event.ind[-1] - MM = ind - if thisline == line0: - if len(N) < 2: - N = np.append(N, MM) - N.sort() - elif thisline == line1: - N = np.delete(N, int(ind)) - - xlime = ax0.get_xlim() - ylime = ax0.get_ylim() - ax0.clear() - ax0.set_title(title) - ax0.stem(peaks1, data1, markerfmt='C0.') - line0, = ax0.plot(peaks1, data1, 'o', c='b', markersize=2, picker=True, pickradius=5) - line1, = ax0.plot(peaks1[N], data1[N] + 1, 'v', c='r', picker=True, pickradius=5) - ax0.set_xlim(xlime) - ax0.set_ylim(ylime) - ax0.grid() - plt.draw() - - fig.canvas.mpl_connect('pick_event', onpick) - plt.show() - - if len(N) == 0: - N = np.array([0, len(data1) - 1]).astype(int) - - N_peak = peaks1_[N] - N_out = np.asarray([N_peak[:2], N[:2]]).astype(int) - - return N_out - - -def get_IIV_shift(JJIs, RRIs): - global shift, line0 - - RRIVs = np.diff(RRIs) - JJIVs = np.diff(JJIs) - corre_ = np.correlate(RRIVs, JJIVs, 'valid') - - '''手动选择偏移''' - corre = np.copy(corre_) - shift = np.argmax(corre) - RRIVs_cut = RRIVs[shift:shift + len(JJIVs)] - RRIs_cut = RRIs[shift:shift + len(JJIs)] - - correlation = np.corrcoef(RRIVs_cut, JJIVs) - correlation_IIV = (correlation[0, 1] + correlation[1, 0]) / 2 - - correlation = np.corrcoef(RRIs_cut, JJIs) - correlation_II = (correlation[0, 1] + correlation[1, 0]) / 2 - - tmp = RRIVs_cut * JJIVs - same_sign_rate = np.sum(tmp > 0) / len(JJIVs) - total_time_ratio = np.sum(JJIs) / np.sum(RRIs[shift:shift + len(JJIs)]) - fig, ax = plt.subplots(2, 1) - ax0, ax1 = ax[0], ax[1] - ax0.set_title( - "corre_IIV: {}, corre_II: {}\n same_sign_rate:{}, total_time_ratio: {}\n shift: {}".format(correlation_IIV, - correlation_II, - same_sign_rate, - total_time_ratio, - shift)) - ax0.stem(corre, markerfmt='C0.', label='corre(RRIV, JJIV)') - line0, = ax0.plot(corre, 'o', c='b', markersize=2, picker=True, pickradius=5) - ax0.plot(shift, corre[shift] + 1, 'v', c='r', picker=True, pickradius=5) - ax0.legend() - ax0.grid() - ax1.stem(RRIVs, markerfmt='b.', label='RRIV') - ax1.stem(np.arange(shift, shift + len(JJIVs)), JJIVs, markerfmt='ko', label='JJIV') - ax1.legend() - - def onpick(event): - global line0 - global shift - thisline = event.artist - xdata = thisline.get_xdata() - ind = event.ind[-1] - shift = int(xdata[ind]) - RRIVs_cut = RRIVs[shift:shift + len(JJIVs)] - RRIs_cut = RRIs[shift:shift + len(JJIs)] - - correlation = np.corrcoef(RRIVs_cut, JJIVs) - correlation_IIV = (correlation[0, 1] + correlation[1, 0]) / 2 - - correlation = np.corrcoef(RRIs_cut, JJIs) - correlation_II = (correlation[0, 1] + correlation[1, 0]) / 2 - - tmp = RRIVs_cut * JJIVs - same_sign_rate = np.sum(tmp > 0) / len(JJIVs) - total_time_ratio = np.sum(JJIs) / np.sum(RRIs[shift:shift + len(JJIs)]) - - xlime = ax0.get_xlim() - ylime = ax0.get_ylim() - ax0.clear() - ax0.set_title( - "corre_IIV: {}, corre_II: {}\n same_sign_rate:{}, total_time_ratio: {}\n shift: {}".format(correlation_IIV, - correlation_II, - same_sign_rate, - total_time_ratio, - shift)) - ax0.stem(corre, markerfmt='C0.', label='corre(RRIV, JJIV)') - line0, = ax0.plot(corre, 'o', c='b', markersize=2, picker=True, pickradius=5) - ax0.plot(shift, corre[shift] + 1, 'v', c='r', picker=True, pickradius=5) - ax0.legend() - ax0.grid() - ax0.set_xlim(xlime) - ax0.set_ylim(ylime) - xlime = ax1.get_xlim() - ylime = ax1.get_ylim() - ax1.clear() - ax1.stem(RRIVs, markerfmt='b.', label='RRIV') - ax1.stem(np.arange(shift, shift + len(JJIVs)), JJIVs, markerfmt='ko', label='JJIV') - ax1.legend() - ax1.set_xlim(xlime) - ax1.set_ylim(ylime) - plt.draw() - - fig.canvas.mpl_connect('pick_event', onpick) - plt.show() - - # return shift - return shift, correlation_IIV, correlation_II, total_time_ratio - - -def main(): - def offset_correct(BCG, ECG, anchors): - global line0, line1, N, M - a = np.max([np.max(ECG), np.max(BCG)]) - b = np.min([np.min(ECG), np.min(BCG)]) - peaks_ECG, _ = signal.find_peaks(ECG) - peaks_BCG, _ = signal.find_peaks(BCG) - N, M = np.array([]).astype(int), np.array([]).astype(int) - fig, ax = plt.subplots() - ax.set_title("offset correct") - ax.plot(ECG) - ax.plot(BCG) - ax.plot([anchors[0], anchors[0]], [b, a], 'k--') - ax.plot([anchors[1], anchors[1]], [b, a], 'k--') - ax.plot(N, ECG[N] + 1, 'rv') - ax.plot(M, BCG[M] + 1, 'yv') - line0, = ax.plot(peaks_ECG, ECG[peaks_ECG], 'o', markersize=2, c='g', picker=True, pickradius=5) - line1, = ax.plot(peaks_BCG, BCG[peaks_BCG], 'o', markersize=2, c='g', picker=True, pickradius=5) - ax.grid() - - def onpick(event): - global line0, line1, N, M - thisline = event.artist - xdata = thisline.get_xdata() - ind = event.ind[-1] - nm = int(xdata[ind]) - if thisline == line0: - if nm in N: - idx = np.where(N == nm)[0] - N = np.delete(N, idx) - elif len(N) < 2: - N = np.append(N, nm) - elif thisline == line1: - if nm in M: - idx = np.where(M == nm)[0] - M = np.delete(M, idx) - elif len(M) < 2: - M = np.append(M, nm) - - xlime = ax.get_xlim() - ylime = ax.get_ylim() - ax.clear() - ax.set_title("offset correct") - ax.plot(ECG) - ax.plot(BCG) - ax.plot([anchors[0], anchors[0]], [b, a], 'k--') - ax.plot([anchors[1], anchors[1]], [b, a], 'k--') - ax.plot(N, ECG[N] + 1, 'rv') - ax.plot(M, BCG[M] + 1, 'yv') - line0, = ax.plot(peaks_ECG, ECG[peaks_ECG], 'o', markersize=2, c='g', picker=True, pickradius=5) - line1, = ax.plot(peaks_BCG, BCG[peaks_BCG], 'o', markersize=2, c='g', picker=True, pickradius=5) - ax.grid() - ax.set_xlim(xlime) - ax.set_ylim(ylime) - plt.draw() - - fig.canvas.mpl_connect('pick_event', onpick) - plt.show() - - if len(N) == 0 or len(M) == 0: - off = 0 - else: - M.sort() - N.sort() - off = round(((int(N[1]) - int(M[1])) + (int(N[0]) - int(M[0]))) / 2) - - return off - - '''输入信息(如数据路径、采样频率)''' - fs = 1000 - root = r"E:\data_annotation\pratice_data\282" # E:\BCG_data\703 - - saveroot = os.path.join(root, 'Align') - if not os.path.exists(saveroot): - os.mkdir(saveroot) - else: - shutil.rmtree(saveroot) - os.mkdir(saveroot) - - '''获取数据(BCG、ECG、J_peak、R_peak)''' - raw_org_, DSbcg_sig_1000hz3_, filter_ecg_, Jpeak_, final_Rpeak_ = read_data(root) - - orgBCG = raw_org_ - BCG = DSbcg_sig_1000hz3_ - ECG = filter_ecg_ - Rpeaks = final_Rpeak_ - Jpeaks = Jpeak_ - - orgbcg_len = len(BCG) - argmax_bcg = np.argmax(BCG) - orgecg_len = len(ECG) - argmax_ecg = np.argmax(ECG) - - # plt.figure() - # plt.subplot(2,1,1) - # plt.plot(BCG[:3600000]) - # plt.subplot(2,1,2) - # plt.plot(ECG) - - info = Align_two_way(Jpeaks, Rpeaks, fs=fs) - - print(info) - - anchor0 = info['1']['anchors'] - anchor1 = info['2']['anchors'] - - off = info['offset_anchor'] - orgfs = info['orgfs'] - - if off > 0: - ECG = ECG[off:] - anchor0[0] = anchor0[0] - off - anchor1[0] = anchor1[0] - off - idxs = np.where(Rpeaks > off)[0] - Rpeaks = Rpeaks[idxs] - off - else: - BCG = BCG[-off:] - orgBCG = orgBCG[-off:] - anchor0[1] = anchor0[1] + off - anchor1[1] = anchor1[1] + off - - BCG_res = resample(BCG, orgfs, fs) - orgBCG_res = resample(orgBCG, orgfs, fs) - - # ———————————————————————————————————————————————————————————————— - anchor0[1] = round(int(anchor0[1]) * fs / orgfs) - anchor1[1] = round(int(anchor1[1]) * fs / orgfs) - off = anchor1[0] - anchor1[1] - if off > 0: - ECG = ECG[off:] - anchor0[0] = anchor0[0] - off - anchor1[0] = anchor1[0] - off - idxs = np.where(Rpeaks > off)[0] - Rpeaks = Rpeaks[idxs] - off - else: - BCG_res = BCG_res[-off:] - orgBCG_res = orgBCG_res[-off:] - anchor0[1] = anchor0[1] + off - anchor1[1] = anchor1[1] + off - - datalen = np.min([len(ECG), len(BCG_res)]) - ECG = ECG[:datalen] - BCG_res = BCG_res[:datalen] - orgBCG_res = orgBCG_res[:datalen] - - idxs = np.where(Rpeaks < datalen)[0] - Rpeaks = Rpeaks[idxs] - - # —————————————————————————————————————————————————————————————————— - off = offset_correct(BCG_res, ECG, [anchor0[0], anchor1[0]]) - if off > 0: - ECG = ECG[off:] - anchor0[0] = anchor0[0] - off - anchor1[0] = anchor1[0] - off - idxs = np.where(Rpeaks > off)[0] - Rpeaks = Rpeaks[idxs] - off - else: - BCG_res = BCG_res[-off:] - orgBCG_res = orgBCG_res[-off:] - anchor0[1] = anchor0[1] + off - anchor1[1] = anchor1[1] + off - - info['offset_correct'] = off - - datalen = np.min([len(ECG), len(BCG_res)]) - ECG = ECG[:datalen] - BCG_res = BCG_res[:datalen] - orgBCG_res = orgBCG_res[:datalen] - - idxs = np.where(Rpeaks < datalen)[0] - Rpeaks = Rpeaks[idxs] - - Jpeaks = [] - peaks, _ = signal.find_peaks(BCG_res) - for i in Rpeaks: - tmp = np.abs(peaks - i) - idx = np.argmin(tmp) - Jpeaks.append(peaks[idx]) - Jpeaks = np.asarray(Jpeaks).astype(int) - - # ----------------2024.4.17 CYS 新增计算BCG与ECG前后两端切割的横坐标---------------- - orgfs = info['orgfs'] # 原始数据采样频率 - frontcut_index_bcg = int((argmax_bcg - np.argmax(BCG_res) / 1000 * orgfs)) - backcut_index_bcg = int((len(BCG_res) / 1000 * orgfs + argmax_bcg - np.argmax(BCG_res) / 1000 * orgfs)) - - frontcut_index_ecg = argmax_ecg - np.argmax(ECG) - backcut_index_ecg = len(ECG) + argmax_ecg - np.argmax(ECG) - - print("1. BCG前段被切割的坐标值为:", frontcut_index_bcg) - print("1. BCG后段被切割的坐标值为:", backcut_index_bcg) - print("2. ECG前段被切割的坐标值为:", frontcut_index_ecg) - print("2. ECG后段被切割的坐标值为:", backcut_index_ecg) - info = {'0': info, 'frontcut_index_bcg': frontcut_index_bcg, 'backcut_index_bcg': backcut_index_bcg, - 'frontcut_index_ecg': frontcut_index_ecg, 'backcut_index_ecg': backcut_index_ecg} - # ------------------------------------------------------------------------------ - - plt.figure() - plt.plot(ECG, label='ECG') - plt.plot(BCG_res, label='BCG') - plt.plot(Rpeaks, ECG[Rpeaks], 'ko', label='Rpeaks') - plt.plot(Jpeaks, BCG_res[Jpeaks], 'rv', label='Jpeaks') - # plt.legend() - plt.show() - - savepath = os.path.join(saveroot, 'Align_info.npy') - np.save(savepath, info) - savepath = os.path.join(saveroot, 'Align_info.txt') - with open(savepath, 'w') as file: - file.write(str(info)) - - savepath = os.path.join(saveroot, 'orgData_sync.txt') - pd.DataFrame(np.round(orgBCG_res, 4)).to_csv(savepath, index=None, header=None) - savepath = os.path.join(saveroot, 'BCG_sync.txt') - pd.DataFrame(np.round(BCG_res, 4)).to_csv(savepath, index=None, header=None) - savepath = os.path.join(saveroot, 'ECG_sync.txt') - pd.DataFrame(ECG).to_csv(savepath, index=None, header=None) - savepath = os.path.join(saveroot, 'Jpeaks_sync.txt') - pd.DataFrame(Jpeaks).to_csv(savepath, index=None, header=None) - savepath = os.path.join(saveroot, 'Rpeaks_sync.txt') - pd.DataFrame(Rpeaks).to_csv(savepath, index=None, header=None) - - -if __name__ == "__main__": - main() diff --git a/ui/setting/precisely_align_input_setting.py b/ui/setting/precisely_align_input_setting.py index 2eb9e05..3c8ecf4 100644 --- a/ui/setting/precisely_align_input_setting.py +++ b/ui/setting/precisely_align_input_setting.py @@ -24,7 +24,7 @@ class Ui_MainWindow_precisely_align_input_setting(object): def setupUi(self, MainWindow_precisely_align_input_setting): if not MainWindow_precisely_align_input_setting.objectName(): MainWindow_precisely_align_input_setting.setObjectName(u"MainWindow_precisely_align_input_setting") - MainWindow_precisely_align_input_setting.resize(540, 760) + MainWindow_precisely_align_input_setting.resize(840, 1010) self.centralwidget = QWidget(MainWindow_precisely_align_input_setting) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) @@ -42,33 +42,76 @@ class Ui_MainWindow_precisely_align_input_setting(object): font1 = QFont() font1.setPointSize(10) self.groupBox.setFont(font1) - self.verticalLayout_2 = QVBoxLayout(self.groupBox) - self.verticalLayout_2.setObjectName(u"verticalLayout_2") - self.groupBox_file_path_input_BCG = QGroupBox(self.groupBox) - self.groupBox_file_path_input_BCG.setObjectName(u"groupBox_file_path_input_BCG") - self.verticalLayout_5 = QVBoxLayout(self.groupBox_file_path_input_BCG) - self.verticalLayout_5.setObjectName(u"verticalLayout_5") - self.plainTextEdit_file_path_input_BCG = QPlainTextEdit(self.groupBox_file_path_input_BCG) - self.plainTextEdit_file_path_input_BCG.setObjectName(u"plainTextEdit_file_path_input_BCG") + self.gridLayout_2 = QGridLayout(self.groupBox) + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.groupBox_file_path_save_2 = QGroupBox(self.groupBox) + self.groupBox_file_path_save_2.setObjectName(u"groupBox_file_path_save_2") + self.verticalLayout_9 = QVBoxLayout(self.groupBox_file_path_save_2) + self.verticalLayout_9.setObjectName(u"verticalLayout_9") + self.plainTextEdit_file_path_save_orgBcg = QPlainTextEdit(self.groupBox_file_path_save_2) + self.plainTextEdit_file_path_save_orgBcg.setObjectName(u"plainTextEdit_file_path_save_orgBcg") - self.verticalLayout_5.addWidget(self.plainTextEdit_file_path_input_BCG) + self.verticalLayout_9.addWidget(self.plainTextEdit_file_path_save_orgBcg) - self.verticalLayout_5.setStretch(0, 3) + self.plainTextEdit_file_path_save_BCG = QPlainTextEdit(self.groupBox_file_path_save_2) + self.plainTextEdit_file_path_save_BCG.setObjectName(u"plainTextEdit_file_path_save_BCG") - self.verticalLayout_2.addWidget(self.groupBox_file_path_input_BCG) + self.verticalLayout_9.addWidget(self.plainTextEdit_file_path_save_BCG) - self.groupBox_file_path_input_Jpeak = QGroupBox(self.groupBox) - self.groupBox_file_path_input_Jpeak.setObjectName(u"groupBox_file_path_input_Jpeak") - self.verticalLayout_3 = QVBoxLayout(self.groupBox_file_path_input_Jpeak) - self.verticalLayout_3.setObjectName(u"verticalLayout_3") - self.plainTextEdit_file_path_input_Jpeak = QPlainTextEdit(self.groupBox_file_path_input_Jpeak) - self.plainTextEdit_file_path_input_Jpeak.setObjectName(u"plainTextEdit_file_path_input_Jpeak") + self.plainTextEdit_file_path_save_ECG = QPlainTextEdit(self.groupBox_file_path_save_2) + self.plainTextEdit_file_path_save_ECG.setObjectName(u"plainTextEdit_file_path_save_ECG") - self.verticalLayout_3.addWidget(self.plainTextEdit_file_path_input_Jpeak) + self.verticalLayout_9.addWidget(self.plainTextEdit_file_path_save_ECG) - self.verticalLayout_3.setStretch(0, 2) - self.verticalLayout_2.addWidget(self.groupBox_file_path_input_Jpeak) + self.gridLayout_2.addWidget(self.groupBox_file_path_save_2, 6, 0, 1, 1) + + self.groupBox_file_path_save_3 = QGroupBox(self.groupBox) + self.groupBox_file_path_save_3.setObjectName(u"groupBox_file_path_save_3") + self.verticalLayout_10 = QVBoxLayout(self.groupBox_file_path_save_3) + self.verticalLayout_10.setObjectName(u"verticalLayout_10") + self.plainTextEdit_file_path_save_Jpeak = QPlainTextEdit(self.groupBox_file_path_save_3) + self.plainTextEdit_file_path_save_Jpeak.setObjectName(u"plainTextEdit_file_path_save_Jpeak") + + self.verticalLayout_10.addWidget(self.plainTextEdit_file_path_save_Jpeak) + + self.plainTextEdit_file_path_save_Rpeak = QPlainTextEdit(self.groupBox_file_path_save_3) + self.plainTextEdit_file_path_save_Rpeak.setObjectName(u"plainTextEdit_file_path_save_Rpeak") + + self.verticalLayout_10.addWidget(self.plainTextEdit_file_path_save_Rpeak) + + + self.gridLayout_2.addWidget(self.groupBox_file_path_save_3, 6, 1, 1, 1) + + self.groupBox_file_path_save = QGroupBox(self.groupBox) + self.groupBox_file_path_save.setObjectName(u"groupBox_file_path_save") + self.verticalLayout_4 = QVBoxLayout(self.groupBox_file_path_save) + self.verticalLayout_4.setObjectName(u"verticalLayout_4") + self.plainTextEdit_file_path_save_BCG_AlignInfo = QPlainTextEdit(self.groupBox_file_path_save) + self.plainTextEdit_file_path_save_BCG_AlignInfo.setObjectName(u"plainTextEdit_file_path_save_BCG_AlignInfo") + + self.verticalLayout_4.addWidget(self.plainTextEdit_file_path_save_BCG_AlignInfo) + + self.plainTextEdit_file_path_save_ECG_AlignInfo = QPlainTextEdit(self.groupBox_file_path_save) + self.plainTextEdit_file_path_save_ECG_AlignInfo.setObjectName(u"plainTextEdit_file_path_save_ECG_AlignInfo") + + self.verticalLayout_4.addWidget(self.plainTextEdit_file_path_save_ECG_AlignInfo) + + + self.gridLayout_2.addWidget(self.groupBox_file_path_save, 5, 0, 1, 2) + + self.groupBox_file_path_input_Rpeak = QGroupBox(self.groupBox) + self.groupBox_file_path_input_Rpeak.setObjectName(u"groupBox_file_path_input_Rpeak") + self.verticalLayout_7 = QVBoxLayout(self.groupBox_file_path_input_Rpeak) + self.verticalLayout_7.setObjectName(u"verticalLayout_7") + self.plainTextEdit_file_path_input_Rpeak = QPlainTextEdit(self.groupBox_file_path_input_Rpeak) + self.plainTextEdit_file_path_input_Rpeak.setObjectName(u"plainTextEdit_file_path_input_Rpeak") + + self.verticalLayout_7.addWidget(self.plainTextEdit_file_path_input_Rpeak) + + self.verticalLayout_7.setStretch(0, 2) + + self.gridLayout_2.addWidget(self.groupBox_file_path_input_Rpeak, 4, 0, 1, 2) self.groupBox_file_path_input_ECG = QGroupBox(self.groupBox) self.groupBox_file_path_input_ECG.setObjectName(u"groupBox_file_path_input_ECG") @@ -101,43 +144,54 @@ class Ui_MainWindow_precisely_align_input_setting(object): self.verticalLayout_6.setStretch(0, 2) self.verticalLayout_6.setStretch(1, 3) - self.verticalLayout_2.addWidget(self.groupBox_file_path_input_ECG) + self.gridLayout_2.addWidget(self.groupBox_file_path_input_ECG, 3, 0, 1, 2) - self.groupBox_file_path_input_Rpeak = QGroupBox(self.groupBox) - self.groupBox_file_path_input_Rpeak.setObjectName(u"groupBox_file_path_input_Rpeak") - self.verticalLayout_7 = QVBoxLayout(self.groupBox_file_path_input_Rpeak) - self.verticalLayout_7.setObjectName(u"verticalLayout_7") - self.plainTextEdit_file_path_input_Rpeak = QPlainTextEdit(self.groupBox_file_path_input_Rpeak) - self.plainTextEdit_file_path_input_Rpeak.setObjectName(u"plainTextEdit_file_path_input_Rpeak") + self.groupBox_file_path_input_Jpeak = QGroupBox(self.groupBox) + self.groupBox_file_path_input_Jpeak.setObjectName(u"groupBox_file_path_input_Jpeak") + self.verticalLayout_3 = QVBoxLayout(self.groupBox_file_path_input_Jpeak) + self.verticalLayout_3.setObjectName(u"verticalLayout_3") + self.plainTextEdit_file_path_input_Jpeak = QPlainTextEdit(self.groupBox_file_path_input_Jpeak) + self.plainTextEdit_file_path_input_Jpeak.setObjectName(u"plainTextEdit_file_path_input_Jpeak") - self.verticalLayout_7.addWidget(self.plainTextEdit_file_path_input_Rpeak) + self.verticalLayout_3.addWidget(self.plainTextEdit_file_path_input_Jpeak) - self.verticalLayout_7.setStretch(0, 2) + self.verticalLayout_3.setStretch(0, 2) - self.verticalLayout_2.addWidget(self.groupBox_file_path_input_Rpeak) + self.gridLayout_2.addWidget(self.groupBox_file_path_input_Jpeak, 2, 0, 1, 2) - self.groupBox_file_path_save = QGroupBox(self.groupBox) - self.groupBox_file_path_save.setObjectName(u"groupBox_file_path_save") - self.verticalLayout_4 = QVBoxLayout(self.groupBox_file_path_save) - self.verticalLayout_4.setObjectName(u"verticalLayout_4") - self.plainTextEdit_file_path_save_BCG = QPlainTextEdit(self.groupBox_file_path_save) - self.plainTextEdit_file_path_save_BCG.setObjectName(u"plainTextEdit_file_path_save_BCG") + self.groupBox_file_path_input_BCG = QGroupBox(self.groupBox) + self.groupBox_file_path_input_BCG.setObjectName(u"groupBox_file_path_input_BCG") + self.verticalLayout_5 = QVBoxLayout(self.groupBox_file_path_input_BCG) + self.verticalLayout_5.setObjectName(u"verticalLayout_5") + self.plainTextEdit_file_path_input_BCG = QPlainTextEdit(self.groupBox_file_path_input_BCG) + self.plainTextEdit_file_path_input_BCG.setObjectName(u"plainTextEdit_file_path_input_BCG") - self.verticalLayout_4.addWidget(self.plainTextEdit_file_path_save_BCG) + self.verticalLayout_5.addWidget(self.plainTextEdit_file_path_input_BCG) - self.plainTextEdit_file_path_save_ECG = QPlainTextEdit(self.groupBox_file_path_save) - self.plainTextEdit_file_path_save_ECG.setObjectName(u"plainTextEdit_file_path_save_ECG") + self.verticalLayout_5.setStretch(0, 3) - self.verticalLayout_4.addWidget(self.plainTextEdit_file_path_save_ECG) + self.gridLayout_2.addWidget(self.groupBox_file_path_input_BCG, 1, 0, 1, 2) + self.groupBox_file_path_input_orgBcg = QGroupBox(self.groupBox) + self.groupBox_file_path_input_orgBcg.setObjectName(u"groupBox_file_path_input_orgBcg") + self.verticalLayout_8 = QVBoxLayout(self.groupBox_file_path_input_orgBcg) + self.verticalLayout_8.setObjectName(u"verticalLayout_8") + self.plainTextEdit_file_path_input_orgBcg = QPlainTextEdit(self.groupBox_file_path_input_orgBcg) + self.plainTextEdit_file_path_input_orgBcg.setObjectName(u"plainTextEdit_file_path_input_orgBcg") - self.verticalLayout_2.addWidget(self.groupBox_file_path_save) + self.verticalLayout_8.addWidget(self.plainTextEdit_file_path_input_orgBcg) - self.verticalLayout_2.setStretch(0, 5) - self.verticalLayout_2.setStretch(1, 4) - self.verticalLayout_2.setStretch(2, 5) - self.verticalLayout_2.setStretch(3, 4) - self.verticalLayout_2.setStretch(4, 8) + self.verticalLayout_8.setStretch(0, 3) + + self.gridLayout_2.addWidget(self.groupBox_file_path_input_orgBcg, 0, 0, 1, 2) + + self.gridLayout_2.setRowStretch(0, 3) + self.gridLayout_2.setRowStretch(1, 3) + self.gridLayout_2.setRowStretch(2, 3) + self.gridLayout_2.setRowStretch(3, 4) + self.gridLayout_2.setRowStretch(4, 3) + self.gridLayout_2.setRowStretch(5, 6) + self.gridLayout_2.setRowStretch(6, 3) self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 4) @@ -161,22 +215,32 @@ class Ui_MainWindow_precisely_align_input_setting(object): MainWindow_precisely_align_input_setting.setWindowTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u5bfc\u5165\u8bbe\u7f6e", None)) self.pushButton_cancel.setText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u53d6\u6d88", None)) self.groupBox.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u6587\u4ef6\u8def\u5f84", None)) - self.groupBox_file_path_input_BCG.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u9884\u5904\u7406\u540e\u7684BCG\u8def\u5f84", None)) - self.plainTextEdit_file_path_input_BCG.setPlainText("") - self.plainTextEdit_file_path_input_BCG.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u6587\u4ef6\u8def\u5f84", None)) - self.groupBox_file_path_input_Jpeak.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4eba\u5de5\u7ea0\u6b63\u540e\u7684J\u5cf0\u5cf0\u503c\u8def\u5f84", None)) - self.plainTextEdit_file_path_input_Jpeak.setPlainText("") - self.plainTextEdit_file_path_input_Jpeak.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u6587\u4ef6\u8def\u5f84", None)) + self.groupBox_file_path_save_2.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u5bf9\u9f50orgBcg\u3001BCG\u548cECG\u4fdd\u5b58\u8def\u5f84", None)) + self.plainTextEdit_file_path_save_orgBcg.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4fdd\u5b58\u8def\u5f84", None)) + self.plainTextEdit_file_path_save_BCG.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4fdd\u5b58\u8def\u5f84", None)) + self.plainTextEdit_file_path_save_ECG.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4fdd\u5b58\u8def\u5f84", None)) + self.groupBox_file_path_save_3.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u5bf9\u9f50J\u5cf0\u548cR\u5cf0\u4fdd\u5b58\u8def\u5f84", None)) + self.plainTextEdit_file_path_save_Jpeak.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4fdd\u5b58\u8def\u5f84", None)) + self.plainTextEdit_file_path_save_Rpeak.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4fdd\u5b58\u8def\u5f84", None)) + self.groupBox_file_path_save.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u5bf9\u9f50\u4fe1\u606f\u4fdd\u5b58\u8def\u5f84", None)) + self.plainTextEdit_file_path_save_BCG_AlignInfo.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4fdd\u5b58\u8def\u5f84", None)) + self.plainTextEdit_file_path_save_ECG_AlignInfo.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4fdd\u5b58\u8def\u5f84", None)) + self.groupBox_file_path_input_Rpeak.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4eba\u5de5\u7ea0\u6b63\u540e\u7684R\u5cf0\u8def\u5f84", None)) + self.plainTextEdit_file_path_input_Rpeak.setPlainText("") + self.plainTextEdit_file_path_input_Rpeak.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u6587\u4ef6\u8def\u5f84", None)) self.groupBox_file_path_input_ECG.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u9884\u5904\u7406\u540e\u7684ECG\u8def\u5f84", None)) self.label_3.setText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u91c7\u6837\u7387(Hz)\uff1a", None)) self.plainTextEdit_file_path_input_ECG.setPlainText("") self.plainTextEdit_file_path_input_ECG.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u6587\u4ef6\u8def\u5f84", None)) - self.groupBox_file_path_input_Rpeak.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4eba\u5de5\u7ea0\u6b63\u540e\u7684R\u5cf0\u5cf0\u503c\u8def\u5f84", None)) - self.plainTextEdit_file_path_input_Rpeak.setPlainText("") - self.plainTextEdit_file_path_input_Rpeak.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u6587\u4ef6\u8def\u5f84", None)) - self.groupBox_file_path_save.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u5bf9\u9f50\u4fe1\u606f\u4fdd\u5b58\u8def\u5f84", None)) - self.plainTextEdit_file_path_save_BCG.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4fdd\u5b58\u8def\u5f84", None)) - self.plainTextEdit_file_path_save_ECG.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4fdd\u5b58\u8def\u5f84", None)) + self.groupBox_file_path_input_Jpeak.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u4eba\u5de5\u7ea0\u6b63\u540e\u7684J\u5cf0\u8def\u5f84", None)) + self.plainTextEdit_file_path_input_Jpeak.setPlainText("") + self.plainTextEdit_file_path_input_Jpeak.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u6587\u4ef6\u8def\u5f84", None)) + self.groupBox_file_path_input_BCG.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u9884\u5904\u7406\u540e\u7684BCG\u8def\u5f84", None)) + self.plainTextEdit_file_path_input_BCG.setPlainText("") + self.plainTextEdit_file_path_input_BCG.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u6587\u4ef6\u8def\u5f84", None)) + self.groupBox_file_path_input_orgBcg.setTitle(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u539f\u59cborgBcg\u8def\u5f84", None)) + self.plainTextEdit_file_path_input_orgBcg.setPlainText("") + self.plainTextEdit_file_path_input_orgBcg.setPlaceholderText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u6587\u4ef6\u8def\u5f84", None)) self.pushButton_confirm.setText(QCoreApplication.translate("MainWindow_precisely_align_input_setting", u"\u786e\u5b9a", None)) # retranslateUi diff --git a/ui/setting/precisely_align_input_setting.ui b/ui/setting/precisely_align_input_setting.ui index 69e0c90..efeb5eb 100644 --- a/ui/setting/precisely_align_input_setting.ui +++ b/ui/setting/precisely_align_input_setting.ui @@ -6,8 +6,8 @@ 0 0 - 540 - 760 + 840 + 1010 @@ -37,15 +37,91 @@ 文件路径 - - - + + + - 预处理后的BCG路径 + 对齐orgBcg、BCG和ECG保存路径 - + - + + + 保存路径 + + + + + + + 保存路径 + + + + + + + 保存路径 + + + + + + + + + + 对齐J峰和R峰保存路径 + + + + + + 保存路径 + + + + + + + 保存路径 + + + + + + + + + + 对齐信息保存路径 + + + + + + 保存路径 + + + + + + + 保存路径 + + + + + + + + + + 人工纠正后的R峰路径 + + + + @@ -57,26 +133,7 @@ - - - - 人工纠正后的J峰峰值路径 - - - - - - - - - 文件路径 - - - - - - - + 预处理后的ECG路径 @@ -126,14 +183,14 @@ - - + + - 人工纠正后的R峰峰值路径 + 人工纠正后的J峰路径 - + - + @@ -145,23 +202,38 @@ - - + + - 对齐信息保存路径 + 预处理后的BCG路径 - + - + + + + - 保存路径 + 文件路径 + + + + + + + 原始orgBcg路径 + + - + + + + - 保存路径 + 文件路径 diff --git a/数据结构化输入和输出命名规范.md b/数据结构化输入和输出命名规范.md new file mode 100644 index 0000000..2f254c9 --- /dev/null +++ b/数据结构化输入和输出命名规范.md @@ -0,0 +1,187 @@ +# 文件命名规范 + +### 1 数据粗同步 + +输入: + +原始orgBcg信号:`./OrgBCG_Text//orgBcg_Raw_采样率.txt` +原始PSG信号:`./PSG_Text//Axxxxxxx.edf` + +输出: + +粗同步后的位置索引:`./Sync_Index//Approximately_Align_Info.csv` + +### 2 预处理 + +输入: + +原始orgBcg信号:`./OrgBCG_Text//orgBcg_Raw_采样率.txt` +原始ECG信号:`./PSG_Text//ECG I_采样率.txt` + +输出: + +带通滤波BCG信号:`./OrgBCG_Text//BCG_Raw_采样率.txt` +滤波后的ECG信号:`./PSG_Text//ECG_Raw_采样率.txt` + +### 3 数据精同步 + +输入: + +带通滤波BCG信号:`./OrgBCG_Text//BCG_Raw_采样率.txt` +滤波后的ECG信号:`./PSG_Text//ECG_Raw_采样率.txt` + +输出: + +PSG的对齐信息:`./PSG_Aligned//Align_info.txt` +同步后的ECG信号:`./PSG_Aligned//ECG_Sync_采样率.txt` +同步后的R峰坐标:`./PSG_Aligned//Rpeaks_Sync.txt` +同步后的其他PSG通道信号:`./PSG_Aligned//通道名_Sync_采样率.txt` +BCG的对齐信息:`./OrgBCG_Aligned//Align_info.txt` +同步后的BCG信号:`./OrgBCG_Aligned//BCG_Sync_采样率.txt` +同步后的orgBcg信号:`./OrgBCG_Aligned//orgBcg_Sync_采样率.txt` +同步后的J峰坐标:`./OrgBCG_Aligned//Jpeaks_Sync.txt` + +#### 3.1 算法定位 + +#### 3.1.1 R峰算法定位 + +输入: + +滤波后的ECG信号:`./PSG_Text//ECG_Raw_采样率.txt` + +输出: + +算法定位的R峰坐标:`./PSG_Text//Rpeak_final.txt` + +#### 3.1.2 J峰算法定位 + +输入: + +带通滤波BCG信号:`./OrgBCG_Text//BCG_Raw_采样率.txt` + +输出: + +算法定位的J峰坐标:`./OrgBCG_Text//JPeak_revise.txt` + +#### 3.2 人工纠正 + +#### 3.2.1 R峰人工纠正 + +输入: + +滤波后的ECG信号:`./PSG_Text//ECG_filter_采样率.txt` +算法定位的R峰坐标:`./PSG_Text//Rpeak_final.txt` + +输出: + +人工纠正后的R峰坐标:`./PSG_Text//Rpeak_final_corrected.txt` + +#### 3.2.2 J峰人工纠正* + +输入: + +带通滤波BCG信号:`./OrgBCG_Text//DSbcg_sig_采样率.txt` +算法定位的J峰坐标:`./OrgBCG_Text//JPeak_revise.txt` + +输出: + +人工纠正后的J峰坐标:`./OrgBCG_Text//JPeak_revise_corrected.txt` + +#### 3.3 数据片段起止对齐、数据采样率同步 + +输入: + +滤波后的ECG信号:`./PSG_Text//ECG_Raw_采样率.txt` +人工纠正后的R峰坐标:`./PSG_Text//Rpeak_final_corrected.txt` +带通滤波BCG信号:`./OrgBCG_Text//BCG_Raw_采样率.txt` +人工纠正后的J峰坐标:`./OrgBCG_Text//JPeak_revise_corrected.txt` + +输出: + +PSG的对齐信息:`./PSG_Aligned//Align_info.txt` +同步后的ECG信号:`./PSG_Aligned//ECG_Sync_采样率.txt` +同步后的R峰坐标:`./PSG_Aligned//Rpeak_Sync.txt` +BCG的对齐信息:`./OrgBCG_Aligned//Align_info.txt` +同步后的BCG信号:`./OrgBCG_Aligned//BCG_Sync_采样率.txt` +同步后的orgBcg信号:`./OrgBCG_Aligned//orgBcg_Sync_采样率.txt` +同步后的J峰坐标:`./OrgBCG_Aligned//Jpeak_Sync.txt` + +#### 3.4、冗余数据切割、标签映射 + +输入: + +PSG的对齐信息:`./PSG_Aligned//Align_info.txt` +BCG的对齐信息:`./OrgBCG_Aligned//Align_info.txt` + +输出: + +同步后的其他PSG通道信号:`./PSG_Aligned//通道名_Sync_采样率.txt` + +### 4 体动标记 + +输入: + +同步后的BCG信号:`./OrgBCG_Aligned//BCG_Sync_采样率.txt` +同步后的orgBcg信号:`./OrgBCG_Aligned//orgBcg_Sync_采样率.txt` + +输出: + +txt格式的体动标签:`./Label//Artifact_a.txt` +体动标签类型数量统计:`./Label//Artifact_b.txt` +csv格式的体动标签:`./Label//Artifact_c.csv` + +### 5 质量评估 + +输入: + +同步后的BCG信号:`./OrgBCG_Aligned//BCG_Sync_采样率.txt` +txt格式的体动标签:`./Label//Artifact_a.txt` + +输出: + +质量标签:`./Label//SQ_label_10s.csv`或`./Label//SQ_label_30s.csv` + +### 6 心搏定位数据标注 + +输入: + +同步后的ECG信号:`./PSG_Aligned//ECG_Sync_采样率.txt` +同步后的BCG信号:`./OrgBCG_Aligned//BCG_Sync_采样率.txt` +同步后的R峰坐标:`./PSG_Aligned//Rpeak_Sync.txt` +同步后的J峰坐标:`./OrgBCG_Aligned//Jpeak_Sync.txt` +txt格式的体动标签:`./Label//Artifact_a.txt` +质量标签:`./Label//SQ_label_10s.csv`或`./Label//SQ_label_30s.csv` + +输出: + +? + +### 7 呼吸提取 + +输入: + +同步后的orgBcg信号:`./OrgBCG_Aligned//orgBcg_Sync_采样率.txt` +同步后的THO信号:`./PSG_Aligned//Effort_Tho_Sync_采样率.txt` +txt格式的体动标签:`./Label//Artifact_a.txt` + +输出: + +呼吸可用性标签:`./Label//Resp_quality_label.txt` +THO信号呼吸间期标签:`./Label//Tho_peak.txt` + +### 8 呼吸暂停事件标注 + +输入: + +同步后的orgBcg信号:`./OrgBCG_Aligned//orgBcg_Sync_采样率.txt` +txt格式的体动标签:`./Label//Artifact_a.txt` +同步后的FlowT信号:`./PSG_Aligned//Effort_Tho_Sync_采样率.txt` +同步后的FlowP信号:`./PSG_Aligned//Effort_Tho_Sync_采样率.txt` +同步后的THO信号:`./PSG_Aligned//Effort_Tho_Sync_采样率.txt` +同步后的ABD信号:`./PSG_Aligned//Effort_Abd_Sync_采样率.txt` +同步后的SpO2信号:`./PSG_Aligned//SpO2_Sync_采样率.txt` +原始呼吸暂停标签:`./PSG_`? + +输出: + +? \ No newline at end of file