From 364d475d1978b14b7964980feb93ff58ebd93d29 Mon Sep 17 00:00:00 2001 From: marques <20172333133@m.scnu.edu.cn> Date: Wed, 4 Jun 2025 15:35:48 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B2=BE=E5=AF=B9=E9=BD=90=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E7=B2=97=E5=AF=B9=E9=BD=90=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=AF=B9=E5=BA=94ECG=E5=8C=BA=E9=97=B4=E7=9A=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E4=BC=98=E5=8C=96=E7=9B=B8=E5=85=B3=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- func/Module_approximately_align.py | 4 +- func/Module_precisely_align.py | 256 +++++++++++++++++++++++------ func/utils/Constants.py | 7 + 3 files changed, 216 insertions(+), 51 deletions(-) diff --git a/func/Module_approximately_align.py b/func/Module_approximately_align.py index 86a6057..d013997 100644 --- a/func/Module_approximately_align.py +++ b/func/Module_approximately_align.py @@ -1304,8 +1304,8 @@ class Data: tho_seg_pos = argmax(tho_relate_seg) - len(orgBcg_seg) abd_seg_pos = argmax(abd_relate_seg) - len(orgBcg_seg) - tho_bias_list.append(tho_seg_pos // temp_freq) - abd_bias_list.append(abd_seg_pos // temp_freq) + tho_bias_list.append(tho_seg_pos / temp_freq) + abd_bias_list.append(abd_seg_pos / temp_freq) result = { diff --git a/func/Module_precisely_align.py b/func/Module_precisely_align.py index 98934a6..81dcdd7 100644 --- a/func/Module_precisely_align.py +++ b/func/Module_precisely_align.py @@ -25,7 +25,6 @@ from func.utils.Result import Result from ui.MainWindow.MainWindow_precisely_align import Ui_MainWindow_precisely_align from ui.setting.precisely_align_input_setting import Ui_MainWindow_precisely_align_input_setting - Config = { } @@ -191,7 +190,8 @@ class SettingWindow(QMainWindow): 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_input_approximately_align.setPlainText(Config["Path"]["Input_Approximately_Align"]) + self.ui.plainTextEdit_file_path_input_approximately_align.setPlainText( + Config["Path"]["Input_Approximately_Align"]) self.ui.plainTextEdit_file_path_save_AlignInfo.setPlainText(Config["Path"]["Save_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"]) @@ -209,7 +209,8 @@ class SettingWindow(QMainWindow): 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"]["Input_Approximately_Align"] = self.ui.plainTextEdit_file_path_input_approximately_align.toPlainText() + Config["Path"][ + "Input_Approximately_Align"] = self.ui.plainTextEdit_file_path_input_approximately_align.toPlainText() Config["Path"]["Save_AlignInfo"] = self.ui.plainTextEdit_file_path_save_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() @@ -488,7 +489,8 @@ class MainWindow_precisely_align(QMainWindow): self.ax1.axvline(x=self.data.approximately_align_pos, color=Constants.PLOT_COLOR_BLACK, linestyle="--", label="Start Line") else: - self.ax0.axvline(x=self.data.approximately_align_pos, color=Constants.PLOT_COLOR_BLACK, linestyle="--", label="Start Line") + self.ax0.axvline(x=self.data.approximately_align_pos, color=Constants.PLOT_COLOR_BLACK, linestyle="--", + label="Start Line") self.ax1.axvline(x=self.data.approximately_align_pos, color=Constants.PLOT_COLOR_BLACK, linestyle="--", label="Start Line") @@ -496,7 +498,8 @@ class MainWindow_precisely_align(QMainWindow): self.ax1.legend(loc=Constants.PLOT_UPPER_RIGHT) self.canvas.draw() return Result().success(info=Constants.DRAW_FINISHED) - elif sender == self.ui.pushButton_calculate_correlation and plot_element is not None and plot_element["mode"] == "init": + elif sender == self.ui.pushButton_calculate_correlation and plot_element is not None and plot_element[ + "mode"] == "init": self.gs = gridspec.GridSpec(2, 2, height_ratios=[1, 1], width_ratios=[1, 1]) self.fig.subplots_adjust(top=0.88, bottom=0.05, right=0.98, left=0.05, hspace=0.15, wspace=0.15) self.ax0 = self.fig.add_subplot(self.gs[0]) @@ -522,7 +525,8 @@ class MainWindow_precisely_align(QMainWindow): self.ax0.stem(plot_element["front"]["corre"], markerfmt="C0.", label=Constants.PRECISELY_ALIGN_PLOT_LABEL_CORRE_RRIV_JJIV) self.selected_point0, = self.ax0.plot(plot_element["front"]["shift"], - plot_element["front"]["corre"][plot_element["front"]["shift"]] + 1, 'v', + plot_element["front"]["corre"][plot_element["front"]["shift"]] + 1, + 'v', color=Constants.PLOT_COLOR_RED, picker=True, pickradius=5, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_SELECTED_POINT) self.ax0.plot(plot_element["front"]["corre"], 'o', color=Constants.PLOT_COLOR_BLUE, @@ -530,8 +534,10 @@ class MainWindow_precisely_align(QMainWindow): self.ax1.stem(plot_element["front"]["RRIVs"], markerfmt="b.", linefmt=Constants.PLOT_COLOR_ORANGE, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_RRIV) self.stem_black0 = self.ax1.stem(arange(plot_element["front"]["shift"], - plot_element["front"]["shift"] + len(plot_element["front"]["JJIVs"])), - plot_element["front"]["JJIVs"], markerfmt="ko", linefmt=Constants.PLOT_COLOR_GREEN, + plot_element["front"]["shift"] + len( + plot_element["front"]["JJIVs"])), + plot_element["front"]["JJIVs"], markerfmt="ko", + linefmt=Constants.PLOT_COLOR_GREEN, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_JJIV) self.ax2.set_title( "back\ncorre_IIV: {}, corre_II: {}\nsame_sign_rate:{}, total_time_ratio: {}\nshift: {}, alignment offset: {} seconds\noffset_interval: {}, anchor_J: {}, anchor_R: {}".format( @@ -547,12 +553,13 @@ class MainWindow_precisely_align(QMainWindow): color=Constants.PLOT_COLOR_RED, picker=True, pickradius=5, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_SELECTED_POINT) self.ax2.plot(plot_element["back"]["corre"], 'o', color=Constants.PLOT_COLOR_BLUE, - markersize=3, picker=True, pickradius=5) + markersize=3, picker=True, pickradius=5) self.ax3.stem(plot_element["back"]["RRIVs"], markerfmt="b.", linefmt=Constants.PLOT_COLOR_ORANGE, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_RRIV) self.stem_black1 = self.ax3.stem(arange(plot_element["back"]["shift"], plot_element["back"]["shift"] + len(plot_element["back"]["JJIVs"])), - plot_element["back"]["JJIVs"], markerfmt="ko", linefmt=Constants.PLOT_COLOR_GREEN, + plot_element["back"]["JJIVs"], markerfmt="ko", + linefmt=Constants.PLOT_COLOR_GREEN, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_JJIV) self.ax0.legend(loc=Constants.PLOT_UPPER_RIGHT) @@ -562,7 +569,8 @@ class MainWindow_precisely_align(QMainWindow): self.canvas.draw() return Result().success(info=Constants.DRAW_FINISHED) - elif sender == self.ui.pushButton_correlation_align or (plot_element is not None and plot_element["mode"] == "select"): + elif sender == self.ui.pushButton_correlation_align or ( + plot_element is not None and plot_element["mode"] == "select"): self.gs = gridspec.GridSpec(1, 1, height_ratios=[1]) self.fig.subplots_adjust(top=0.95, bottom=0.05, right=0.98, left=0.05, hspace=0, wspace=0) self.ax4 = self.fig.add_subplot(self.gs[0]) @@ -570,14 +578,20 @@ class MainWindow_precisely_align(QMainWindow): self.ax4.xaxis.set_major_formatter(Params.FORMATTER) self.ax4.set_title("offset correct") - self.ax4.plot(plot_element["cut_ECG"], color=Constants.PLOT_COLOR_GREEN, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_ECG) - self.ax4.plot(plot_element["res_BCG"], color=Constants.PLOT_COLOR_ORANGE, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_BCG) - self.ax4.plot([plot_element["anchor00"], plot_element["anchor00"]], [plot_element["b"], plot_element["a"]], 'k--') - self.ax4.plot([plot_element["anchor10"], plot_element["anchor10"]], [plot_element["b"], plot_element["a"]], 'k--') + self.ax4.plot(plot_element["cut_ECG"], color=Constants.PLOT_COLOR_GREEN, + label=Constants.PRECISELY_ALIGN_PLOT_LABEL_ECG) + self.ax4.plot(plot_element["res_BCG"], color=Constants.PLOT_COLOR_ORANGE, + label=Constants.PRECISELY_ALIGN_PLOT_LABEL_BCG) + self.ax4.plot([plot_element["anchor00"], plot_element["anchor00"]], [plot_element["b"], plot_element["a"]], + 'k--') + self.ax4.plot([plot_element["anchor10"], plot_element["anchor10"]], [plot_element["b"], plot_element["a"]], + 'k--') self.point0, = self.ax4.plot(plot_element["peak_ECG"], plot_element["cut_ECG"][plot_element["peak_ECG"]], - 'o', markersize=3, color=Constants.PLOT_COLOR_BLUE, picker=True, pickradius=5, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_RPEAK) + 'o', markersize=3, color=Constants.PLOT_COLOR_BLUE, picker=True, pickradius=5, + label=Constants.PRECISELY_ALIGN_PLOT_LABEL_RPEAK) self.point1, = self.ax4.plot(plot_element["peak_BCG"], plot_element["res_BCG"][plot_element["peak_BCG"]], - 'o', markersize=3, color=Constants.PLOT_COLOR_RED, picker=True, pickradius=5, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_JPEAK) + 'o', markersize=3, color=Constants.PLOT_COLOR_RED, picker=True, pickradius=5, + label=Constants.PRECISELY_ALIGN_PLOT_LABEL_JPEAK) self.ax4.legend(loc=Constants.PLOT_UPPER_RIGHT) @@ -591,10 +605,14 @@ class MainWindow_precisely_align(QMainWindow): self.ax4.xaxis.set_major_formatter(Params.FORMATTER) self.ax4.set_title("result preview") - self.ax4.plot(self.data.cut_ECG, color=Constants.PLOT_COLOR_GREEN, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_ECG) - self.ax4.plot(self.data.res_BCG, color=Constants.PLOT_COLOR_ORANGE, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_BCG) - self.ax4.plot(self.data.cut_Rpeak, self.data.cut_ECG[self.data.cut_Rpeak], 'v', color=Constants.PLOT_COLOR_BLUE, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_RPEAK) - self.ax4.plot(self.data.cut_Jpeak, self.data.res_BCG[self.data.cut_Jpeak], 'v', color=Constants.PLOT_COLOR_RED, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_JPEAK) + self.ax4.plot(self.data.cut_ECG, color=Constants.PLOT_COLOR_GREEN, + label=Constants.PRECISELY_ALIGN_PLOT_LABEL_ECG) + self.ax4.plot(self.data.res_BCG, color=Constants.PLOT_COLOR_ORANGE, + label=Constants.PRECISELY_ALIGN_PLOT_LABEL_BCG) + self.ax4.plot(self.data.cut_Rpeak, self.data.cut_ECG[self.data.cut_Rpeak], 'v', + color=Constants.PLOT_COLOR_BLUE, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_RPEAK) + self.ax4.plot(self.data.cut_Jpeak, self.data.res_BCG[self.data.cut_Jpeak], 'v', + color=Constants.PLOT_COLOR_RED, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_JPEAK) self.ax4.legend(loc=Constants.PLOT_UPPER_RIGHT) @@ -953,7 +971,8 @@ class MainWindow_precisely_align(QMainWindow): try: if self.data is not None: if self.data.Jpeak is None or self.data.Rpeak is None: - PublicFunc.msgbox_output(self, Constants.FAILURE_REASON["Data_Not_Exist"], Constants.MSGBOX_TYPE_ERROR) + PublicFunc.msgbox_output(self, Constants.FAILURE_REASON["Data_Not_Exist"], + Constants.MSGBOX_TYPE_ERROR) return sender = self.sender() @@ -970,6 +989,13 @@ class MainWindow_precisely_align(QMainWindow): 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"]) + PublicFunc.text_output(self.ui, Constants.CORRESPONDING_INTERVAL_PROMOTE_TEMPLATE.format( + Config["Coordinate"]["BCG_front_1"], + Config["Coordinate"]["BCG_front_2"], + self.data.get_corresponding_interval(Config["Coordinate"]["BCG_front_1"]).data["new_point"], + self.data.get_corresponding_interval(Config["Coordinate"]["BCG_front_2"]).data["new_point"], + ), Constants.TIPS_TYPE_INFO) + 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) @@ -982,6 +1008,13 @@ class MainWindow_precisely_align(QMainWindow): 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"]) + PublicFunc.text_output(self.ui, Constants.CORRESPONDING_INTERVAL_PROMOTE_TEMPLATE.format( + Config["Coordinate"]["BCG_back_1"], + Config["Coordinate"]["BCG_back_2"], + self.data.get_corresponding_interval(Config["Coordinate"]["BCG_back_1"]).data["new_point"], + self.data.get_corresponding_interval(Config["Coordinate"]["BCG_back_2"]).data["new_point"], + ), Constants.TIPS_TYPE_INFO) + 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) @@ -994,6 +1027,17 @@ class MainWindow_precisely_align(QMainWindow): 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"]) + PublicFunc.text_output( + self.ui, Constants.CORRESPONDING_INTERVAL_PROMOTE_TEMPLATE.format( + Config["Coordinate"]["ECG_front_1"], + Config["Coordinate"]["ECG_front_2"], + self.data.get_corresponding_interval(Config["Coordinate"]["ECG_front_1"], bcg2ecg=False).data[ + "new_point"], + self.data.get_corresponding_interval(Config["Coordinate"]["ECG_front_2"], bcg2ecg=False).data[ + "new_point"], + ), Constants.TIPS_TYPE_INFO + ) + 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) @@ -1006,7 +1050,19 @@ class MainWindow_precisely_align(QMainWindow): 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: + PublicFunc.text_output( + self.ui, Constants.CORRESPONDING_INTERVAL_PROMOTE_TEMPLATE.format( + Config["Coordinate"]["ECG_back_1"], + Config["Coordinate"]["ECG_back_2"], + self.data.get_corresponding_interval(Config["Coordinate"]["ECG_back_1"], bcg2ecg=False).data[ + "new_point"], + + self.data.get_corresponding_interval(Config["Coordinate"]["ECG_back_2"], bcg2ecg=False).data[ + "new_point"], + ), Constants.TIPS_TYPE_INFO + ) + except AttributeError as e: + print(e) pass def reset_axes(self): @@ -1063,12 +1119,15 @@ class MainWindow_precisely_align(QMainWindow): plot_element["back"]["offset_interval"], plot_element["back"]["anchor_J"], plot_element["back"]["anchor_R"])) self.selected_point0, = self.ax0.plot(plot_element["front"]["shift"], - plot_element["front"]["corre"][plot_element["front"]["shift"]] + 1, 'v', + plot_element["front"]["corre"][plot_element["front"]["shift"]] + 1, + 'v', color=Constants.PLOT_COLOR_RED, picker=True, pickradius=5, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_SELECTED_POINT) self.stem_black0 = self.ax1.stem(arange(plot_element["front"]["shift"], - plot_element["front"]["shift"] + len(plot_element["front"]["JJIVs"])), - plot_element["front"]["JJIVs"], markerfmt="ko", linefmt=Constants.PLOT_COLOR_GREEN, + plot_element["front"]["shift"] + len( + plot_element["front"]["JJIVs"])), + plot_element["front"]["JJIVs"], markerfmt="ko", + linefmt=Constants.PLOT_COLOR_GREEN, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_JJIV) self.selected_point1, = self.ax2.plot(plot_element["back"]["shift"], plot_element["back"]["corre"][plot_element["back"]["shift"]] + 1, 'v', @@ -1076,7 +1135,8 @@ class MainWindow_precisely_align(QMainWindow): label=Constants.PRECISELY_ALIGN_PLOT_LABEL_SELECTED_POINT) self.stem_black1 = self.ax3.stem(arange(plot_element["back"]["shift"], plot_element["back"]["shift"] + len(plot_element["back"]["JJIVs"])), - plot_element["back"]["JJIVs"], markerfmt="ko", linefmt=Constants.PLOT_COLOR_GREEN, + plot_element["back"]["JJIVs"], markerfmt="ko", + linefmt=Constants.PLOT_COLOR_GREEN, label=Constants.PRECISELY_ALIGN_PLOT_LABEL_JJIV) self.ax0.autoscale(False) @@ -1108,16 +1168,20 @@ class MainWindow_precisely_align(QMainWindow): if len(self.data.correlation_align_point_match_ECG) > 0: self.selected_point0, = self.ax4.plot( - [self.data.correlation_align_point_match_ECG[0], self.data.correlation_align_point_match_ECG[0]], [plot_element["b"], plot_element["a"]], 'b--') + [self.data.correlation_align_point_match_ECG[0], self.data.correlation_align_point_match_ECG[0]], + [plot_element["b"], plot_element["a"]], 'b--') if len(self.data.correlation_align_point_match_ECG) == 2: self.selected_point1, = self.ax4.plot( - [self.data.correlation_align_point_match_ECG[1], self.data.correlation_align_point_match_ECG[1]], [plot_element["b"], plot_element["a"]], 'b--') + [self.data.correlation_align_point_match_ECG[1], + self.data.correlation_align_point_match_ECG[1]], [plot_element["b"], plot_element["a"]], 'b--') if len(self.data.correlation_align_point_match_BCG) > 0: self.selected_point2, = self.ax4.plot( - [self.data.correlation_align_point_match_BCG[0], self.data.correlation_align_point_match_BCG[0]], [plot_element["b"], plot_element["a"]], 'r--') + [self.data.correlation_align_point_match_BCG[0], self.data.correlation_align_point_match_BCG[0]], + [plot_element["b"], plot_element["a"]], 'r--') if len(self.data.correlation_align_point_match_BCG) == 2: self.selected_point3, = self.ax4.plot( - [self.data.correlation_align_point_match_BCG[1], self.data.correlation_align_point_match_BCG[1]], [plot_element["b"], plot_element["a"]], 'r--') + [self.data.correlation_align_point_match_BCG[1], + self.data.correlation_align_point_match_BCG[1]], [plot_element["b"], plot_element["a"]], 'r--') self.ax4.autoscale(False) self.ax4.set_xlim(self.ax4_xlime) @@ -1267,11 +1331,30 @@ class MainWindow_precisely_align(QMainWindow): Config["IV_Coordinate"]["BCG_front_2"] = indices[-1] Config["Coordinate"]["BCG_front_1"] = self.data.Jpeak[:-2][indices[0]] Config["Coordinate"]["BCG_front_2"] = self.data.Jpeak[:-2][indices[-1]] + PublicFunc.text_output( + self.ui, + Constants.CORRESPONDING_INTERVAL_PROMOTE_TEMPLATE.format( + Config["Coordinate"]["BCG_front_1"], + Config["Coordinate"]["BCG_front_2"], + self.data.get_corresponding_interval( + Config["Coordinate"]["BCG_front_1"]).data["new_point"], + self.data.get_corresponding_interval( + Config["Coordinate"]["BCG_front_2"]).data["new_point"], + ), Constants.TIPS_TYPE_INFO) elif self.ui.radioButton_BCG_back.isChecked(): Config["IV_Coordinate"]["BCG_back_1"] = indices[0] Config["IV_Coordinate"]["BCG_back_2"] = indices[-1] Config["Coordinate"]["BCG_back_1"] = self.data.Jpeak[:-2][indices[0]] Config["Coordinate"]["BCG_back_2"] = self.data.Jpeak[:-2][indices[-1]] + PublicFunc.text_output( + self.ui, Constants.CORRESPONDING_INTERVAL_PROMOTE_TEMPLATE.format( + Config["Coordinate"]["BCG_back_1"], + Config["Coordinate"]["BCG_back_2"], + self.data.get_corresponding_interval( + Config["Coordinate"]["BCG_back_1"]).data["new_point"], + self.data.get_corresponding_interval( + Config["Coordinate"]["BCG_back_2"]).data["new_point"], + ), Constants.TIPS_TYPE_INFO) elif self.ui.radioButton_ECG_front.isChecked() or self.ui.radioButton_ECG_back.isChecked(): if rect_left < 0: rect_left = 0 @@ -1303,11 +1386,33 @@ class MainWindow_precisely_align(QMainWindow): Config["IV_Coordinate"]["ECG_front_2"] = indices[-1] Config["Coordinate"]["ECG_front_1"] = self.data.Rpeak[:-2][indices[0]] Config["Coordinate"]["ECG_front_2"] = self.data.Rpeak[:-2][indices[-1]] + PublicFunc.text_output( + self.ui, + Constants.CORRESPONDING_INTERVAL_PROMOTE_TEMPLATE.format( + Config["Coordinate"]["ECG_front_1"], + Config["Coordinate"]["ECG_front_2"], + self.data.get_corresponding_interval( + Config["Coordinate"]["ECG_front_1"], bcg2ecg=False).data[ + "new_point"], + self.data.get_corresponding_interval( + Config["Coordinate"]["ECG_front_2"], bcg2ecg=False).data[ + "new_point"], + ), Constants.TIPS_TYPE_INFO) elif self.ui.radioButton_ECG_back.isChecked(): Config["IV_Coordinate"]["ECG_back_1"] = indices[0] Config["IV_Coordinate"]["ECG_back_2"] = indices[-1] Config["Coordinate"]["ECG_back_1"] = self.data.Rpeak[:-2][indices[0]] Config["Coordinate"]["ECG_back_2"] = self.data.Rpeak[:-2][indices[-1]] + PublicFunc.text_output( + self.ui, Constants.CORRESPONDING_INTERVAL_PROMOTE_TEMPLATE.format( + Config["Coordinate"]["ECG_back_1"], + Config["Coordinate"]["ECG_back_2"], + self.data.get_corresponding_interval( + Config["Coordinate"]["ECG_back_1"], bcg2ecg=False).data["new_point"], + self.data.get_corresponding_interval( + Config["Coordinate"]["ECG_back_2"], bcg2ecg=False).data["new_point"], + ), Constants.TIPS_TYPE_INFO + ) self.figToolbar.rect_start_x = None self.figToolbar.rect_end_x = None @@ -1388,15 +1493,21 @@ class MainWindow_precisely_align(QMainWindow): if this_line == self.point0: if nm in self.data.correlation_align_point_match_ECG: self.data.correlation_align_point_match_ECG = delete(self.data.correlation_align_point_match_ECG, - where(self.data.correlation_align_point_match_ECG == nm)[0]) + where( + self.data.correlation_align_point_match_ECG == nm)[ + 0]) elif len(self.data.correlation_align_point_match_ECG) < 2: - self.data.correlation_align_point_match_ECG = append(self.data.correlation_align_point_match_ECG, nm) + self.data.correlation_align_point_match_ECG = append(self.data.correlation_align_point_match_ECG, + nm) elif this_line == self.point1: if nm in self.data.correlation_align_point_match_BCG: self.data.correlation_align_point_match_BCG = delete(self.data.correlation_align_point_match_BCG, - where(self.data.correlation_align_point_match_BCG == nm)[0]) + where( + self.data.correlation_align_point_match_BCG == nm)[ + 0]) elif len(self.data.correlation_align_point_match_BCG) < 2: - self.data.correlation_align_point_match_BCG = append(self.data.correlation_align_point_match_BCG, nm) + self.data.correlation_align_point_match_BCG = append(self.data.correlation_align_point_match_BCG, + nm) else: raise ValueError("this_line不存在") self.__slot_btn_correlation_align__() @@ -1413,6 +1524,9 @@ class Data: self.Rpeak = None self.Rpeak_y = None self.approximately_align_pos = None + self.approximately_align_estimated_freq = None + self.approximately_align_slope = None + self.approximately_align_intercept = None self.BCG_early = None self.res_orgBcg = None @@ -1552,6 +1666,12 @@ class Data: else: self.approximately_align_pos = 0 self.BCG_early = None + + self.approximately_align_estimated_freq = df["estimate_freq"].values[-1] + self.approximately_align_slope = df["estimate_slope"].values[-1] / \ + Params.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT["Second_PerEpoch"] + self.approximately_align_intercept = df["estimate_intercept"].values[-1] * Config["InputConfig"]["UseFreq"] + except Exception: self.approximately_align_pos = 0 @@ -1565,7 +1685,8 @@ class Data: if Config["InputConfig"]["orgBcgFreq"] != Config["InputConfig"]["UseFreq"]: self.raw_orgBcg = resample(self.raw_orgBcg, int(len(self.raw_orgBcg) * - (Config["InputConfig"]["UseFreq"] / Config["InputConfig"]["orgBcgFreq"]))) + (Config["InputConfig"]["UseFreq"] / Config["InputConfig"][ + "orgBcgFreq"]))) else: return Result().success(info=Constants.RESAMPLE_NO_NEED) except Exception as e: @@ -1605,8 +1726,10 @@ class Data: try: if mode == "init": - self.JJIs0_front = self.JJIs[Config["IV_Coordinate"]["BCG_front_1"]:Config["IV_Coordinate"]["BCG_front_2"]] - self.RRIs0_front = self.RRIs[Config["IV_Coordinate"]["ECG_front_1"]:Config["IV_Coordinate"]["ECG_front_2"]] + self.JJIs0_front = self.JJIs[ + Config["IV_Coordinate"]["BCG_front_1"]:Config["IV_Coordinate"]["BCG_front_2"]] + self.RRIs0_front = self.RRIs[ + Config["IV_Coordinate"]["ECG_front_1"]:Config["IV_Coordinate"]["ECG_front_2"]] self.JJIVs_front = diff(self.JJIs0_front) self.RRIVs_front = diff(self.RRIs0_front) self.corre_front = correlate(self.RRIVs_front, self.JJIVs_front, 'valid') @@ -1656,7 +1779,8 @@ class Data: } except Exception as e: return Result().failure(info=Constants.PRECISELY_ALIGN_CALCULATE_FAILURE_FRONT + - Constants.FAILURE_REASON["Calculate_Correlation_Exception"] + "\n" + format_exc()) + Constants.FAILURE_REASON[ + "Calculate_Correlation_Exception"] + "\n" + format_exc()) return Result().success(info=Constants.PRECISELY_ALIGN_CALCULATE_FINISHED_FRONT, data=result) @@ -1724,7 +1848,8 @@ class Data: } except Exception as e: return Result().failure(info=Constants.PRECISELY_ALIGN_CALCULATE_FAILURE_BACK + - Constants.FAILURE_REASON["Calculate_Correlation_Exception"] + "\n" + format_exc()) + Constants.FAILURE_REASON[ + "Calculate_Correlation_Exception"] + "\n" + format_exc()) return Result().success(info=Constants.PRECISELY_ALIGN_CALCULATE_FINISHED_BACK, data=result) @@ -1820,7 +1945,9 @@ class Data: else: self.correlation_align_point_match_ECG.sort() self.correlation_align_point_match_BCG.sort() - off = round(((int(self.correlation_align_point_match_ECG[1]) - int(self.correlation_align_point_match_BCG[1])) + (int(self.correlation_align_point_match_ECG[0]) - int(self.correlation_align_point_match_BCG[0]))) / 2) + off = round(((int(self.correlation_align_point_match_ECG[1]) - int( + self.correlation_align_point_match_BCG[1])) + (int(self.correlation_align_point_match_ECG[0]) - int( + self.correlation_align_point_match_BCG[0]))) / 2) anchor0 = [Config["front"]["anchor_R"], Config["front"]["anchor_J"]] anchor1 = [Config["back"]["anchor_R"], Config["back"]["anchor_J"]] @@ -1854,8 +1981,10 @@ class Data: self.cut_Jpeak.append(peaks[idx]) self.cut_Jpeak = asarray(self.cut_Jpeak).astype(int) - frontcut_index_BCG = int((self.argmax_BCG - np_argmax(self.res_BCG) / Config["InputConfig"]["UseFreq"] * Config["orgfs"])) - backcut_index_BCG = int(len(self.res_BCG) / Config["InputConfig"]["UseFreq"] * Config["orgfs"] + np_argmax(self.raw_BCG) - np_argmax(self.res_BCG) / Config["InputConfig"]["UseFreq"] * Config["orgfs"]) + frontcut_index_BCG = int( + (self.argmax_BCG - np_argmax(self.res_BCG) / Config["InputConfig"]["UseFreq"] * Config["orgfs"])) + backcut_index_BCG = int(len(self.res_BCG) / Config["InputConfig"]["UseFreq"] * Config["orgfs"] + np_argmax( + self.raw_BCG) - np_argmax(self.res_BCG) / Config["InputConfig"]["UseFreq"] * Config["orgfs"]) frontcut_index_ECG = self.argmax_ECG - np_argmax(self.cut_ECG) backcut_index_ECG = len(self.cut_ECG) + self.argmax_ECG - np_argmax(self.cut_ECG) @@ -1911,7 +2040,8 @@ class Data: return Result().success(info=Constants.PRECISELY_ALIGN_SAVING_ALIGNINFO_FINISHED) def save_res_orgBcg(self, chunk): - if (not Path(Config["Path"]["Save_OrgBCG"]).parent.exists()) or (not Path(Config["Path"]["Save_OrgBCG"]).parent.is_dir()): + if (not Path(Config["Path"]["Save_OrgBCG"]).parent.exists()) or ( + not Path(Config["Path"]["Save_OrgBCG"]).parent.is_dir()): Path(Config["Path"]["Save_OrgBCG"]).parent.mkdir(parents=True, exist_ok=True) if Config["InputConfig"]["orgBcgFreq"] != Config["InputConfig"]["UseFreq"]: @@ -1932,7 +2062,8 @@ class Data: return Result().success(info=Constants.PRECISELY_ALIGN_SAVING_RES_ORGBCG_FINISHED) def save_res_BCG(self, chunk): - if (not Path(Config["Path"]["Save_BCG"]).parent.exists()) or (not Path(Config["Path"]["Save_BCG"]).parent.is_dir()): + if (not Path(Config["Path"]["Save_BCG"]).parent.exists()) or ( + not Path(Config["Path"]["Save_BCG"]).parent.is_dir()): Path(Config["Path"]["Save_BCG"]).parent.mkdir(parents=True, exist_ok=True) if self.res_BCG is None: @@ -1948,7 +2079,8 @@ class Data: return Result().success(info=Constants.PRECISELY_ALIGN_SAVING_RES_BCG_FINISHED) def save_cut_ECG(self, chunk): - if (not Path(Config["Path"]["Save_ECG"]).parent.exists()) or (not Path(Config["Path"]["Save_ECG"]).parent.is_dir()): + if (not Path(Config["Path"]["Save_ECG"]).parent.exists()) or ( + not Path(Config["Path"]["Save_ECG"]).parent.is_dir()): Path(Config["Path"]["Save_ECG"]).parent.mkdir(parents=True, exist_ok=True) if self.cut_ECG is None: @@ -1964,7 +2096,8 @@ class Data: return Result().success(info=Constants.PRECISELY_ALIGN_SAVING_CUT_ECG_FINISHED) def save_Jpeak(self, chunk): - if (not Path(Config["Path"]["Save_ECG"]).parent.exists()) or (not Path(Config["Path"]["Save_ECG"]).parent.is_dir()): + if (not Path(Config["Path"]["Save_ECG"]).parent.exists()) or ( + not Path(Config["Path"]["Save_ECG"]).parent.is_dir()): Path(Config["Path"]["Save_ECG"]).parent.mkdir(parents=True, exist_ok=True) if self.cut_Jpeak is None: @@ -1980,7 +2113,8 @@ class Data: return Result().success(info=Constants.PRECISELY_ALIGN_SAVING_CUT_JPEAK_FINISHED) def save_Rpeak(self, chunk): - if (not Path(Config["Path"]["Save_Rpeak"]).parent.exists()) or (not Path(Config["Path"]["Save_Rpeak"]).parent.is_dir()): + if (not Path(Config["Path"]["Save_Rpeak"]).parent.exists()) or ( + not Path(Config["Path"]["Save_Rpeak"]).parent.is_dir()): Path(Config["Path"]["Save_Rpeak"]).parent.mkdir(parents=True, exist_ok=True) if self.cut_Rpeak is None: @@ -1995,6 +2129,30 @@ class Data: return Result().success(info=Constants.PRECISELY_ALIGN_SAVING_CUT_RPEAK_FINISHED) + def get_corresponding_interval(self, point, bcg2ecg=True): + try: + + if self.BCG_early: + pos = -self.approximately_align_pos + else: + pos = self.approximately_align_pos + + if bcg2ecg: + new_point = point / self.approximately_align_estimated_freq + pos - self.approximately_align_intercept + else: + new_point = (point - pos + self.approximately_align_intercept) * self.approximately_align_estimated_freq + + result = { + "new_point": int(new_point) + } + + except Exception as e: + return Result().failure(info=Constants.PRECISELY_ALIGN_GET_CORRESPONDING_INTERVAL_FAILURE + + Constants.FAILURE_REASON[ + "Get_Corresponding_Interval_Exception"] + "\n" + format_exc()) + + return Result().success(info=Constants.PRECISELY_ALIGN_GET_CORRESPONDING_INTERVAL_FINISHED, data=result) + class CustomNavigationToolbar(NavigationToolbar2QT): @@ -2051,4 +2209,4 @@ class CustomNavigationToolbar(NavigationToolbar2QT): self.cid_mouse_release = None if self.cid_mouse_hold is not None: self.canvas.mpl_disconnect(self.cid_mouse_hold) - self.cid_mouse_hold = None \ No newline at end of file + self.cid_mouse_hold = None diff --git a/func/utils/Constants.py b/func/utils/Constants.py index 2b229ad..58c564f 100644 --- a/func/utils/Constants.py +++ b/func/utils/Constants.py @@ -46,6 +46,8 @@ class Constants: SAVE_FINISHED: str = "保存完成" SAVE_FAILURE: str = "保存失败" + CORRESPONDING_INTERVAL_PROMOTE_TEMPLATE: str = "经粗对齐计算BCG({},{})对应的ECG约区间为({},{})" + OPERATION_FINISHED: str = "操作完成" OPERATION_FAILURE: str = "操作失败" OPERATION_CANCELED: str = "操作取消" @@ -125,6 +127,7 @@ class Constants: "Predict_Exception": "(预测异常)", "Read_Model_Exception": "(读取模型异常)", "Calculate_Correlation_Value_Equal": "(计算相关性参数相同)", + "Get_Corresponding_Interval_Exception": "(获取对应区间异常)", "Calculate_Correlation_JJIVRange_too_Large": "(计算相关性JJIV范围大于RRIV范围)", "Calculate_Correlation_Exception": "(计算相关性异常)", "Correlation_Align_Exception": "(处理相关对齐异常)", @@ -258,6 +261,10 @@ class Constants: PRECISELY_ALIGN_CALCULATE_FINISHED_BACK: str = "计算后段相关性完成" PRECISELY_ALIGN_CALCULATE_FAILURE_BACK: str = "计算后段相关性失败" + PRECISELY_ALIGN_GET_CORRESPONDING_INTERVAL : str = "正在获取对应区间" + PRECISELY_ALIGN_GET_CORRESPONDING_INTERVAL_FAILURE : str = "获取对应区间失败" + PRECISELY_ALIGN_GET_CORRESPONDING_INTERVAL_FINISHED : str = "获取对应区间完成" + PRECISELY_ALIGN_ALIGNING_CORRELATION: str = "正在处理相关对齐" PRECISELY_ALIGN_ALIGN_CORRELATION_FINISHED: str = "处理相关对齐完成" PRECISELY_ALIGN_ALIGN_CORRELATION_FAILURE: str = "处理相关对齐失败"