Merge branch 'master' into cxh_dev

# Conflicts:
#	func/Module_approximately_align.py
This commit is contained in:
marques
2025-06-02 20:24:11 +08:00
31 changed files with 6309 additions and 1437 deletions

View File

@ -15,9 +15,10 @@ from overrides import overrides
from pandas import read_csv, DataFrame, Series, concat
from yaml import dump, load, FullLoader
from func.utils.ConfigParams import Filename, Params
from func.Filters.Preprocessing import Butterworth_for_ECG_PreProcess
from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants, ConfigParams
from func.utils.Constants import Constants
from func.utils.Result import Result
from ui.MainWindow.MainWindow_SA_label import Ui_MainWindow_SA_label
@ -98,36 +99,36 @@ class SettingWindow(QMainWindow):
self.ui.pushButton_cancel.clicked.connect(self.close)
def __read_config__(self):
if not Path(ConfigParams.SA_LABEL_CONFIG_FILE_PATH).exists():
with open(ConfigParams.SA_LABEL_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.SA_LABEL_CONFIG_NEW_CONTENT, f)
if not Path(Params.SA_LABEL_CONFIG_FILE_PATH).exists():
with open(Params.SA_LABEL_CONFIG_FILE_PATH, "w") as f:
dump(Params.SA_LABEL_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.SA_LABEL_CONFIG_FILE_PATH, "r") as f:
with open(Params.SA_LABEL_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
self.config = file_config
Config.update({
"Path": {
"Input_OrgBCG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
"Input_OrgBCG": str((Path(self.root_path) / Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)))),
"Input_Tho": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
"Input_Tho": str((Path(self.root_path) / Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)))),
"Input_Abd": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
Path(str(self.sampID)))),
"Input_FlowT": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
"Input_Abd": str((Path(self.root_path) / Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)))),
"Input_FlowP": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
"Input_FlowT": str((Path(self.root_path) / Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)))),
"Input_SpO2": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
Path(str(self.sampID)))),
"Input_Artifact": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL /
Path(str(self.sampID)))),
"Input_Label": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
"Input_FlowP": str((Path(self.root_path) / Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)))),
"Save": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL /
"Input_SpO2": str((Path(self.root_path) / Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)))),
"Input_Artifact": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID)))),
"Input_Label": str((Path(self.root_path) / Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)))),
"Save": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID)))),
"Save_2": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL /
"Save_2": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID))))
},
"PlotEventIndex": 0,
@ -182,7 +183,7 @@ class SettingWindow(QMainWindow):
self.config["InputConfig"]["FlowPFreq"] = self.ui.spinBox_input_freq_signal_FlowP.value()
self.config["InputConfig"]["SpO2Freq"] = self.ui.spinBox_input_freq_signal_SpO2.value()
with open(ConfigParams.SA_LABEL_CONFIG_FILE_PATH, "w") as f:
with open(Params.SA_LABEL_CONFIG_FILE_PATH, "w") as f:
dump(self.config, f)
self.close()
@ -193,46 +194,46 @@ class SettingWindow(QMainWindow):
def __update_ui__(self):
self.ui.plainTextEdit_file_path_input_signal_OrgBCG.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.ORGBCG_SYNC +
Path(Filename.ORGBCG_SYNC +
str(self.ui.spinBox_input_freq_signal_OrgBCG.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_signal_Tho.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.THO_SYNC +
Path(Filename.THO_SYNC +
str(self.ui.spinBox_input_freq_signal_Tho.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_signal_Abd.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.ABD_SYNC +
Path(Filename.ABD_SYNC +
str(self.ui.spinBox_input_freq_signal_Abd.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_signal_FlowT.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.FLOWT_SYNC +
Path(Filename.FLOWT_SYNC +
str(self.ui.spinBox_input_freq_signal_FlowT.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_signal_FlowP.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.FLOWP_SYNC +
Path(Filename.FLOWP_SYNC +
str(self.ui.spinBox_input_freq_signal_FlowP.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_signal_SpO2.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.SPO2_SYNC +
Path(Filename.SPO2_SYNC +
str(self.ui.spinBox_input_freq_signal_SpO2.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
class MainWindow_SA_label(QMainWindow):
@ -305,31 +306,31 @@ class MainWindow_SA_label(QMainWindow):
self.fig.subplots_adjust(top=0.98, bottom=0.05, right=0.98, left=0.1, hspace=0, wspace=0)
self.ax0 = self.fig.add_subplot(self.gs[0])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax1 = self.fig.add_subplot(self.gs[1], sharex=self.ax0)
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
self.ax1.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax2 = self.fig.add_subplot(self.gs[2], sharex=self.ax0)
self.ax2.grid(True)
self.ax2.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax2.xaxis.set_major_formatter(Params.FORMATTER)
self.ax2.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax3 = self.fig.add_subplot(self.gs[3], sharex=self.ax0)
self.ax3.grid(True)
self.ax3.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax3.xaxis.set_major_formatter(Params.FORMATTER)
self.ax3.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax4 = self.fig.add_subplot(self.gs[4], sharex=self.ax0)
self.ax4.grid(True)
self.ax4.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax4.xaxis.set_major_formatter(Params.FORMATTER)
self.ax4.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax5 = self.fig.add_subplot(self.gs[5], sharex=self.ax0)
self.ax5.grid(True)
self.ax5.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax5.xaxis.set_major_formatter(Params.FORMATTER)
self.ax5.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax6 = self.fig.add_subplot(self.gs[6], sharex=self.ax0)
self.ax6.grid(True)
self.ax6.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax6.xaxis.set_major_formatter(Params.FORMATTER)
PublicFunc.__resetAllButton__(self, ButtonState)
@ -378,17 +379,17 @@ class MainWindow_SA_label(QMainWindow):
self.ui.checkBox_examineBySecond.clicked.connect(self.__slot_checkBox_examineBySecond__)
self.ui.checkBox_examineLabeled.clicked.connect(self.__slot_checkBox_examineLabeled__)
self.ui.pushButton_prev.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_BTN_PREV_SHORTCUT_KEY))
self.ui.pushButton_confirmLabel.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_BTN_CONFIRMLABEL_SHORTCUT_KEY))
self.ui.pushButton_next.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_BTN_NEXT_SHORTCUT_KEY))
self.ui.radioButton_OSA.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_RADIOBUTTON_OSA_SHORTCUT_KEY))
self.ui.radioButton_CSA.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_RADIOBUTTON_CSA_SHORTCUT_KEY))
self.ui.radioButton_MSA.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_RADIOBUTTON_MSA_SHORTCUT_KEY))
self.ui.radioButton_HPY.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_RADIOBUTTON_HPY_SHORTCUT_KEY))
self.ui.radioButton_1_class.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_RADIOBUTTON_1_CLASS_SHORTCUT_KEY))
self.ui.radioButton_2_class.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_RADIOBUTTON_2_CLASS_SHORTCUT_KEY))
self.ui.radioButton_3_class.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_RADIOBUTTON_3_CLASS_SHORTCUT_KEY))
self.ui.pushButton_quick_remark_input_waitingForTalk.setShortcut(QCoreApplication.translate("MainWindow", ConfigParams.SA_LABEL_BTN_QUICK_REMARK_WAITINGFORTALK_SHORTCUT_KEY))
self.ui.pushButton_prev.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_BTN_PREV_SHORTCUT_KEY))
self.ui.pushButton_confirmLabel.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_BTN_CONFIRMLABEL_SHORTCUT_KEY))
self.ui.pushButton_next.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_BTN_NEXT_SHORTCUT_KEY))
self.ui.radioButton_OSA.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_RADIOBUTTON_OSA_SHORTCUT_KEY))
self.ui.radioButton_CSA.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_RADIOBUTTON_CSA_SHORTCUT_KEY))
self.ui.radioButton_MSA.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_RADIOBUTTON_MSA_SHORTCUT_KEY))
self.ui.radioButton_HPY.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_RADIOBUTTON_HPY_SHORTCUT_KEY))
self.ui.radioButton_1_class.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_RADIOBUTTON_1_CLASS_SHORTCUT_KEY))
self.ui.radioButton_2_class.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_RADIOBUTTON_2_CLASS_SHORTCUT_KEY))
self.ui.radioButton_3_class.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_RADIOBUTTON_3_CLASS_SHORTCUT_KEY))
self.ui.pushButton_quick_remark_input_waitingForTalk.setShortcut(QCoreApplication.translate("MainWindow", Params.SA_LABEL_BTN_QUICK_REMARK_WAITINGFORTALK_SHORTCUT_KEY))
@overrides
def closeEvent(self, event):
@ -609,7 +610,7 @@ class MainWindow_SA_label(QMainWindow):
item = QTableWidgetItem(str(correct_End))
self.ui.tableWidget_label_add.setItem(index, 3, item)
remark = row.get("remark", None)
if str(remark) != "" and str(remark) != "nan" and row.get("isLabeled", None) == 1:
if str(remark) != Constants.STRING_IS_EMPTY and str(remark) != Constants.STRING_IS_NAN and row.get("isLabeled", None) == 1:
for col in range(self.ui.tableWidget_label_add.columnCount()):
item = self.ui.tableWidget_label_add.item(index, col)
item.setBackground(QColor(255, 200, 200))
@ -1000,33 +1001,40 @@ class MainWindow_SA_label(QMainWindow):
self.ui.spinBox_correctEnd.setValue(Config["BCG_EP"])
def reset_axes(self):
self.ax0.clear()
self.ax1.clear()
self.ax2.clear()
self.ax3.clear()
self.ax4.clear()
self.ax5.clear()
self.ax6.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax1.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax2.grid(True)
self.ax2.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax2.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax3.grid(True)
self.ax3.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax3.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax4.grid(True)
self.ax4.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax4.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax5.grid(True)
self.ax5.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax5.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax6.grid(True)
self.ax6.xaxis.set_major_formatter(ConfigParams.FORMATTER)
if self.ax0 is not None:
self.ax0.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
if self.ax1 is not None:
self.ax1.clear()
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
self.ax1.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
if self.ax2 is not None:
self.ax2.clear()
self.ax2.grid(True)
self.ax2.xaxis.set_major_formatter(Params.FORMATTER)
self.ax2.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
if self.ax3 is not None:
self.ax3.clear()
self.ax3.grid(True)
self.ax3.xaxis.set_major_formatter(Params.FORMATTER)
self.ax3.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
if self.ax4 is not None:
self.ax4.clear()
self.ax4.grid(True)
self.ax4.xaxis.set_major_formatter(Params.FORMATTER)
self.ax4.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
if self.ax5 is not None:
self.ax5.clear()
self.ax5.grid(True)
self.ax5.xaxis.set_major_formatter(Params.FORMATTER)
self.ax5.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
if self.ax6 is not None:
self.ax6.clear()
self.ax6.grid(True)
self.ax6.xaxis.set_major_formatter(Params.FORMATTER)
def on_xlim_change(self, event_ax):
# 获取当前x轴范围
@ -1155,7 +1163,7 @@ class MainWindow_SA_label(QMainWindow):
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_Start"],
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_End"],
color='red',
alpha=ConfigParams.SA_LABEL_TRANSPARENCY)
alpha=Params.SA_LABEL_TRANSPARENCY)
elif self.data.df_corrected.at[
Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_EventsType"] == "Central apnea":
for ax in ax_:
@ -1163,7 +1171,7 @@ class MainWindow_SA_label(QMainWindow):
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_Start"],
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_End"],
color='blue',
alpha=ConfigParams.SA_LABEL_TRANSPARENCY)
alpha=Params.SA_LABEL_TRANSPARENCY)
elif self.data.df_corrected.at[
Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_EventsType"] == "Mixed apnea":
for ax in ax_:
@ -1171,7 +1179,7 @@ class MainWindow_SA_label(QMainWindow):
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_Start"],
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_End"],
color='gray',
alpha=ConfigParams.SA_LABEL_TRANSPARENCY)
alpha=Params.SA_LABEL_TRANSPARENCY)
elif self.data.df_corrected.at[
Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_EventsType"] == "Hypopnea":
for ax in ax_:
@ -1179,7 +1187,7 @@ class MainWindow_SA_label(QMainWindow):
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_Start"],
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "correct_End"],
color='pink',
alpha=ConfigParams.SA_LABEL_TRANSPARENCY)
alpha=Params.SA_LABEL_TRANSPARENCY)
else:
if self.data.df_corrected.at[
Config["EventLabelIndexList"][Config["PlotEventIndex"]], "Event type"] == "Obstructive apnea":
@ -1187,28 +1195,28 @@ class MainWindow_SA_label(QMainWindow):
ax.axvspan(self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "Start"],
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "End"],
color='red',
alpha=ConfigParams.SA_LABEL_TRANSPARENCY)
alpha=Params.SA_LABEL_TRANSPARENCY)
elif self.data.df_corrected.at[
Config["EventLabelIndexList"][Config["PlotEventIndex"]], "Event type"] == "Central apnea":
for ax in ax_:
ax.axvspan(self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "Start"],
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "End"],
color='blue',
alpha=ConfigParams.SA_LABEL_TRANSPARENCY)
alpha=Params.SA_LABEL_TRANSPARENCY)
elif self.data.df_corrected.at[
Config["EventLabelIndexList"][Config["PlotEventIndex"]], "Event type"] == "Mixed apnea":
for ax in ax_:
ax.axvspan(self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "Start"],
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "End"],
color='gray',
alpha=ConfigParams.SA_LABEL_TRANSPARENCY)
alpha=Params.SA_LABEL_TRANSPARENCY)
elif self.data.df_corrected.at[
Config["EventLabelIndexList"][Config["PlotEventIndex"]], "Event type"] == "Hypopnea":
for ax in ax_:
ax.axvspan(self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "Start"],
self.data.df_corrected.at[Config["EventLabelIndexList"][Config["PlotEventIndex"]], "End"],
color='pink',
alpha=ConfigParams.SA_LABEL_TRANSPARENCY)
alpha=Params.SA_LABEL_TRANSPARENCY)
def pd_add_new_row(self, df, score: int, remark: str, correct_Start: int, correct_End: int, correct_EventsType: str,
isLabeled: int):
@ -1259,7 +1267,7 @@ class Data:
def open_file(self):
if Path(Config["Path"]["Input_OrgBCG"]).is_file():
Config["Path"]["Input_OrgBCG"] = str(Path(Config["Path"]["Input_orgBcg"]).parent)
Config["Path"]["Input_OrgBCG"] = str(Path(Config["Path"]["Input_OrgBCG"]).parent)
if Path(Config["Path"]["Input_Tho"]).is_file():
Config["Path"]["Input_Tho"] = str(Path(Config["Path"]["Input_Tho"]).parent)
if Path(Config["Path"]["Input_Abd"]).is_file():
@ -1275,84 +1283,88 @@ class Data:
if Path(Config["Path"]["Input_Label"]).is_file():
Config["Path"]["Input_Label"] = str(Path(Config["Path"]["Input_Label"]).parent)
if ((not Path(Config["Path"]["Input_OrgBCG"]).exists())
or (not Path(Config["Path"]["Input_Tho"]).exists())
or (not Path(Config["Path"]["Input_Abd"]).exists())
or (not Path(Config["Path"]["Input_FlowT"]).exists())
or (not Path(Config["Path"]["Input_FlowP"]).exists())
or (not Path(Config["Path"]["Input_SpO2"]).exists())
or (not Path(Config["Path"]["Input_Artifact"]).exists())):
return Result().failure(info=Constants.INPUT_FAILURE +
Constants.FAILURE_REASON["Path_Not_Exist"])
result = PublicFunc.examine_file(Config["Path"]["Input_OrgBCG"], ConfigParams.ORGBCG_SYNC)
result = PublicFunc.examine_file(Config["Path"]["Input_OrgBCG"], Filename.ORGBCG_SYNC, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_OrgBCG"] = result.data["path"]
Config["InputConfig"]["OrgBCGFreq"] = result.data["freq"]
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_Tho"], ConfigParams.THO_SYNC)
result = PublicFunc.examine_file(Config["Path"]["Input_Tho"], Filename.THO_SYNC, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_Tho"] = result.data["path"]
Config["InputConfig"]["ThoFreq"] = result.data["freq"]
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_Abd"], ConfigParams.ABD_SYNC)
result = PublicFunc.examine_file(Config["Path"]["Input_Abd"], Filename.ABD_SYNC, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_Abd"] = result.data["path"]
Config["InputConfig"]["AbdFreq"] = result.data["freq"]
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_FlowT"], ConfigParams.FLOWT_SYNC)
result = PublicFunc.examine_file(Config["Path"]["Input_FlowT"], Filename.FLOWT_SYNC, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_FlowT"] = result.data["path"]
Config["InputConfig"]["FlowTFreq"] = result.data["freq"]
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_FlowP"], ConfigParams.FLOWP_SYNC)
result = PublicFunc.examine_file(Config["Path"]["Input_FlowP"], Filename.FLOWP_SYNC, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_FlowP"] = result.data["path"]
Config["InputConfig"]["FlowPFreq"] = result.data["freq"]
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_SpO2"], ConfigParams.SPO2_SYNC)
result = PublicFunc.examine_file(Config["Path"]["Input_SpO2"], Filename.SPO2_SYNC, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_SpO2"] = result.data["path"]
Config["InputConfig"]["SpO2Freq"] = result.data["freq"]
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_Artifact"], Filename.ARTIFACT_A, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_Artifact"] = result.data["path"]
else:
return result
Config["Path"]["Input_Artifact"] = str(
Path(Config["Path"]["Input_Artifact"]) / Path(ConfigParams.ARTIFACT_A + ConfigParams.ENDSWITH_TXT))
Config["Path"]["Input_Label"] = str(
Path(Config["Path"]["Input_Label"]) / Path(ConfigParams.SA_LABEL_SYNC + ConfigParams.ENDSWITH_CSV))
Path(Config["Path"]["Input_Label"]) / Path(Filename.SA_LABEL_SYNC + Params.ENDSWITH_CSV))
Config["Path"]["Save"] = str(
Path(Config["Path"]["Save"]) / Path(ConfigParams.SA_LABEL_CORRECTED + ConfigParams.ENDSWITH_CSV))
Path(Config["Path"]["Save"]) / Path(Filename.SA_LABEL_CORRECTED + Params.ENDSWITH_CSV))
Config["Path"]["Save_2"] = str(
Path(Config["Path"]["Save_2"]) / Path(ConfigParams.SA_LABEL_ADD + ConfigParams.ENDSWITH_CSV))
Path(Config["Path"]["Save_2"]) / Path(Filename.SA_LABEL_ADD + Params.ENDSWITH_CSV))
if not Path(Config["Path"]["Input_Artifact"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + "\n" +
Filename.ARTIFACT_A + "" +
Config["Path"]["Input_Artifact"] +
Constants.FAILURE_REASON["Path_Not_Exist"])
if not Path(Config["Path"]["Input_Label"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + "\n" +
Filename.SA_LABEL_SYNC + "" +
Config["Path"]["Input_Label"] +
Constants.FAILURE_REASON["Path_Not_Exist"])
try:
self.OrgBCG = read_csv(Config["Path"]["Input_OrgBCG"],
encoding=ConfigParams.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.Tho = read_csv(Config["Path"]["Input_Tho"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.Abd = read_csv(Config["Path"]["Input_Abd"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.FlowT = read_csv(Config["Path"]["Input_FlowT"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.FlowP = read_csv(Config["Path"]["Input_FlowP"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.SpO2 = read_csv(Config["Path"]["Input_SpO2"],
encoding=ConfigParams.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.Artifact = read_csv(Config["Path"]["Input_Artifact"],
encoding=ConfigParams.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.event_label = zeros(len(self.OrgBCG) + (int(Config["AddSecond"]["Front"] + int(Config["AddSecond"]["Back"])) * Config["InputConfig"]["PlotFreq"]))
except Exception as e:
return Result().failure(info=Constants.INPUT_FAILURE +
@ -1360,13 +1372,7 @@ class Data:
try:
# 检查体动标签正确性,长度
if len(self.Artifact) % 4 != 0:
return Result().failure(info=Constants.INPUT_FAILURE +
Constants.FAILURE_REASON["Artifact_Format_Not_Correct"])
for i in range(0, len(self.Artifact), 4):
unit_data = self.Artifact[i:i + 4]
if len(unit_data) < 4:
break
PublicFunc.examine_artifact(self.Artifact)
self.Artifact = self.Artifact.reshape(-1, 4)
except Exception as e:
return Result().failure(info=Constants.INPUT_FAILURE +
@ -1584,9 +1590,6 @@ class Data:
return Result().success(info=Constants.RESAMPLE_FINISHED)
def save(self):
if (not Path(Config["Path"]["Save"]).parent.exists()) or (not Path(Config["Path"]["Save"]).parent.is_dir()):
Path(Config["Path"]["Save"]).parent.mkdir(parents=True, exist_ok=True)
if self.df_corrected is None:
return Result().failure(info=Constants.SAVE_FAILURE + Constants.FAILURE_REASON["Data_Not_Exist"])
@ -1618,6 +1621,6 @@ class CustomNavigationToolbar(NavigationToolbar2QT):
def __init__(self, canvas, parent):
super().__init__(canvas, parent)
self.action_Reset_Signal_and_Time = QAction('复原视图和时间', self)
self.action_Reset_Signal_and_Time.setFont(QFont(ConfigParams.FONT, 14))
self.action_Reset_Signal_and_Time.setFont(QFont(Params.FONT, 14))
self.action_Reset_Signal_and_Time.setCheckable(True)
self.insertAction(self._actions['home'], self.action_Reset_Signal_and_Time)

View File

@ -13,8 +13,10 @@ from pandas import read_csv, DataFrame
from scipy.signal import find_peaks, resample, butter, sosfiltfilt, correlate
from yaml import dump, load, FullLoader
from sklearn.linear_model import TheilSenRegressor
from func.utils.ConfigParams import Filename, Params
from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants, ConfigParams
from func.utils.Constants import Constants
from func.utils.Result import Result
from ui.MainWindow.MainWindow_approximately_align import Ui_MainWindow_approximately_align
@ -99,11 +101,11 @@ class SettingWindow(QMainWindow):
self.ui.pushButton_cancel.clicked.connect(self.close)
def __read_config__(self):
if not Path(ConfigParams.APPROXIMATELY_ALIGN_CONFIG_FILE_PATH).exists():
with open(ConfigParams.APPROXIMATELY_ALIGN_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT, f)
if not Path(Params.APPROXIMATELY_ALIGN_CONFIG_FILE_PATH).exists():
with open(Params.APPROXIMATELY_ALIGN_CONFIG_FILE_PATH, "w") as f:
dump(Params.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.APPROXIMATELY_ALIGN_CONFIG_FILE_PATH, "r") as f:
with open(Params.APPROXIMATELY_ALIGN_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
self.config = file_config
@ -112,15 +114,15 @@ class SettingWindow(QMainWindow):
Config.update({
"Path": {
"Input_orgBcg": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
"Input_orgBcg": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Input_Tho": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Input_Tho": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Input_Abd": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Input_Abd": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Save": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
Path(str(self.sampID)) / Path(ConfigParams.APPROXIMATELY_ALIGN_INFO +
ConfigParams.ENDSWITH_CSV)))
"Save": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID)) / Path(Filename.APPROXIMATELY_ALIGN_INFO +
Params.ENDSWITH_CSV)))
},
"orgBcgConfig": {},
"PSGConfig": {}
@ -162,7 +164,7 @@ class SettingWindow(QMainWindow):
self.config["Filter"]["BandPassLow"] = self.ui.doubleSpinBox_bandpassLow.value()
self.config["Filter"]["BandPassHigh"] = self.ui.doubleSpinBox_bandpassHigh.value()
with open(ConfigParams.APPROXIMATELY_ALIGN_CONFIG_FILE_PATH, "w") as f:
with open(Params.APPROXIMATELY_ALIGN_CONFIG_FILE_PATH, "w") as f:
dump(self.config, f)
self.close()
@ -173,31 +175,25 @@ 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 /
Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.ORGBCG_RAW +
Path(Filename.ORGBCG_RAW +
str(self.ui.spinBox_input_orgBcg_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_Tho.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.THO_RAW +
Path(Filename.THO_RAW +
str(self.ui.spinBox_input_Tho_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_Abd.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.ABD_RAW +
Path(Filename.ABD_RAW +
str(self.ui.spinBox_input_Abd_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.APPROXIMATELY_ALIGN_INFO +
ConfigParams.ENDSWITH_CSV))))
Params.ENDSWITH_TXT))))
class MainWindow_approximately_align(QMainWindow):
@ -998,19 +994,19 @@ class Data:
if Path(Config["Path"]["Input_Abd"]).is_file():
Config["Path"]["Input_Abd"] = str(Path(Config["Path"]["Input_Abd"]).parent)
result = PublicFunc.examine_file(Config["Path"]["Input_orgBcg"], ConfigParams.ORGBCG_RAW)
result = PublicFunc.examine_file(Config["Path"]["Input_orgBcg"], Filename.ORGBCG_RAW, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_orgBcg"] = result.data["path"]
Config["InputConfig"]["orgBcgFreq"] = result.data["freq"]
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_Tho"], ConfigParams.THO_RAW)
result = PublicFunc.examine_file(Config["Path"]["Input_Tho"], Filename.THO_RAW, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_Tho"] = result.data["path"]
Config["InputConfig"]["ThoFreq"] = result.data["freq"]
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_Abd"], ConfigParams.ABD_RAW)
result = PublicFunc.examine_file(Config["Path"]["Input_Abd"], Filename.ABD_RAW, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_Abd"] = result.data["path"]
Config["InputConfig"]["AbdFreq"] = result.data["freq"]
@ -1019,13 +1015,13 @@ class Data:
try:
self.raw_orgBcg = read_csv(Config["Path"]["Input_orgBcg"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.raw_Tho = read_csv(Config["Path"]["Input_Tho"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.raw_Abd = read_csv(Config["Path"]["Input_Abd"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
except Exception as e:
return Result().failure(info=Constants.INPUT_FAILURE + Constants.FAILURE_REASON[
@ -1034,8 +1030,6 @@ class Data:
return Result().success(info=Constants.INPUT_FINISHED)
def save(self, epoch):
if (not Path(Config["Path"]["Save"]).parent.exists()) or (not Path(Config["Path"]["Save"]).parent.is_dir()):
Path(Config["Path"]["Save"]).parent.mkdir(parents=True, exist_ok=True)
try:
pos = Config["pos"]
ApplyFrequency = Config["ApplyFrequency"]
@ -1120,10 +1114,7 @@ class Data:
def Standardize_2(self):
# 预重采样
try:
# TODO这里的采样率处理如果THO和ABD的采样率不同可能还是会导致之后的ApplyFrequency出问题最后导致得到的粗同步坐标不正确
#
if Config["InputConfig"]["ThoFreq"] != Config["TempFrequency"]:
print(int(Config["InputConfig"]["ThoFreq"]), int(Config["TempFrequency"]))
self.processed_Tho = resample(self.processed_Tho,
int(Config["PSG_seconds"] * Config["TempFrequency"]))
@ -1198,7 +1189,7 @@ class Data:
# 计算互相关1/2
try:
# 计算因子
MULTIPLE_FACTOER = ConfigParams.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT["Multiple_Factor"]
MULTIPLE_FACTOER = Params.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT["Multiple_Factor"]
a = self.processed_downsample_Tho[
Config["PSGConfig"]["PreCut"]:len(self.processed_downsample_Tho) - Config["PSGConfig"][
"PostCut"]].copy()
@ -1293,8 +1284,8 @@ class Data:
epoch_max = response.data["epoch_max"]
epoch_second = ConfigParams.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT["Second_PerEpoch"]
temp_freq = ConfigParams.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT["TempFrequency"]
window_epoch = ConfigParams.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT["CorrByEpoch"]["window_epoch"]
temp_freq = Params.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT["TempFrequency"]
window_epoch = Params.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT["CorrByEpoch"]["window_epoch"]
tho_bias_list = []
abd_bias_list = []

View File

@ -9,15 +9,16 @@ from PySide6.QtWidgets import QMessageBox, QMainWindow, QApplication, QTableWidg
from matplotlib import gridspec, patches
from matplotlib.backends.backend_qt import NavigationToolbar2QT
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
from numpy import array, append
from numpy import array, append, sum as np_sum, nonzero
from numpy.fft import fft, fftfreq
from overrides import overrides
from pandas import read_csv, DataFrame, concat
from scipy.signal import resample
from yaml import dump, load, FullLoader
from func.utils.ConfigParams import Filename, Params
from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants, ConfigParams
from func.utils.Constants import Constants
from func.utils.Result import Result
from ui.MainWindow.MainWindow_artifact_label import Ui_MainWindow_artifact_label
@ -35,7 +36,6 @@ ButtonState = {
"pushButton_prev_move": False,
"pushButton_pause": False,
"pushButton_next_move": False,
"pushButton_save": False,
"pushButton_type_1": False,
"pushButton_type_2": False,
"pushButton_type_3": False,
@ -49,7 +49,6 @@ ButtonState = {
"pushButton_prev_move": False,
"pushButton_pause": False,
"pushButton_next_move": False,
"pushButton_save": False,
"pushButton_type_1": False,
"pushButton_type_2": False,
"pushButton_type_3": False,
@ -80,26 +79,26 @@ class SettingWindow(QMainWindow):
self.ui.pushButton_cancel.clicked.connect(self.close)
def __read_config__(self):
if not Path(ConfigParams.ARTIFACT_LABEL_CONFIG_FILE_PATH).exists():
with open(ConfigParams.ARTIFACT_LABEL_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.ARTIFACT_LABEL_CONFIG_NEW_CONTENT, f)
if not Path(Params.ARTIFACT_LABEL_CONFIG_FILE_PATH).exists():
with open(Params.ARTIFACT_LABEL_CONFIG_FILE_PATH, "w") as f:
dump(Params.ARTIFACT_LABEL_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.ARTIFACT_LABEL_CONFIG_FILE_PATH, "r") as f:
with open(Params.ARTIFACT_LABEL_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
self.config = file_config
Config.update({
"Path": {
"Input_orgBcg": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
"Input_orgBcg": str((Path(self.root_path) / Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)))),
"Input_BCG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
"Input_BCG": str((Path(self.root_path) / Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)))),
"Save_a": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL /
"Save_a": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID)))),
"Save_b": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL /
"Save_b": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID)))),
"Save_c": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL /
"Save_c": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID))))
}
})
@ -127,7 +126,7 @@ class SettingWindow(QMainWindow):
self.config["InputConfig"]["orgBcgFreq"] = self.ui.spinBox_input_freq_orgBcg.value()
self.config["InputConfig"]["BCGFreq"] = self.ui.spinBox_input_freq_BCG.value()
with open(ConfigParams.ARTIFACT_LABEL_CONFIG_FILE_PATH, "w") as f:
with open(Params.ARTIFACT_LABEL_CONFIG_FILE_PATH, "w") as f:
dump(self.config, f)
self.close()
@ -138,18 +137,18 @@ class SettingWindow(QMainWindow):
def __update_ui__(self):
self.ui.plainTextEdit_file_path_input_orgBcg.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.ORGBCG_SYNC +
Path(Filename.ORGBCG_SYNC +
str(self.ui.spinBox_input_freq_orgBcg.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_BCG.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.BCG_SYNC +
Path(Filename.BCG_SYNC +
str(self.ui.spinBox_input_freq_BCG.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
class MainWindow_artifact_label(QMainWindow):
@ -233,11 +232,11 @@ class MainWindow_artifact_label(QMainWindow):
self.fig.subplots_adjust(top=0.98, bottom=0.05, right=0.98, left=0.1, hspace=0, wspace=0)
self.ax0 = self.fig.add_subplot(self.gs[0])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax1 = self.fig.add_subplot(self.gs[1], sharex=self.ax0)
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
PublicFunc.__resetAllButton__(self, ButtonState)
@ -261,8 +260,8 @@ class MainWindow_artifact_label(QMainWindow):
self.ui.tableWidget_type_4.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.ui.tableWidget_type_5.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.ui.lineEdit_start_time.setValidator(ConfigParams.VALIDATOR_INTEGER)
self.ui.lineEdit_end_time.setValidator(ConfigParams.VALIDATOR_INTEGER)
self.ui.lineEdit_start_time.setValidator(Params.VALIDATOR_INTEGER)
self.ui.lineEdit_end_time.setValidator(Params.VALIDATOR_INTEGER)
self.ui.pushButton_input.clicked.connect(self.__slot_btn_input__)
self.ui.pushButton_type_1.clicked.connect(self.__slot_btn_label__)
@ -270,7 +269,6 @@ class MainWindow_artifact_label(QMainWindow):
self.ui.pushButton_type_3.clicked.connect(self.__slot_btn_label__)
self.ui.pushButton_type_4.clicked.connect(self.__slot_btn_label__)
self.ui.pushButton_type_5.clicked.connect(self.__slot_btn_label__)
self.ui.pushButton_save.clicked.connect(self.__slot_btn_save__)
self.ui.pushButton_delete.clicked.connect(self.__slot_btn_delete_label__)
self.ui.pushButton_prev_move.clicked.connect(self.__slot_btn_move__)
self.ui.pushButton_pause.clicked.connect(self.__slot_btn_move__)
@ -300,8 +298,10 @@ class MainWindow_artifact_label(QMainWindow):
del self.rectangles_ax0_patches
del self.rectangles_ax1_patches
del self.annotation_tableWidget
self.ax0.clear()
self.ax1.clear()
if self.ax0 is not None:
self.ax0.clear()
if self.ax1 is not None:
self.ax1.clear()
# 释放资源
del self.data
@ -370,71 +370,71 @@ class MainWindow_artifact_label(QMainWindow):
if self.data.df_Artifact_a.iloc[i][1] == 1:
# 橙色,剧烈体动
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_DEEP_YELLOW)
self.rectangles_ax0_patches.append(rectangle)
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_DEEP_YELLOW)
self.rectangles_ax1_patches.append(rectangle)
elif self.data.df_Artifact_a.iloc[i][1] == 2:
# 黄色,脉冲体动
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_YELLOW)
self.rectangles_ax0_patches.append(rectangle)
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_YELLOW)
self.rectangles_ax1_patches.append(rectangle)
elif self.data.df_Artifact_a.iloc[i][1] == 3:
# 青色,常规体动
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_AQUA)
self.rectangles_ax0_patches.append(rectangle)
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_AQUA)
self.rectangles_ax1_patches.append(rectangle)
elif self.data.df_Artifact_a.iloc[i][1] == 4:
# 紫色,疑似鼾声
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PURPLE_PINK)
self.rectangles_ax0_patches.append(rectangle)
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PURPLE_PINK)
self.rectangles_ax1_patches.append(rectangle)
elif self.data.df_Artifact_a.iloc[i][1] == 5:
# 灰色,离床
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_DEEP_GREY)
self.rectangles_ax0_patches.append(rectangle)
rectangle = patches.Rectangle((self.data.df_Artifact_a.iloc[i][2], self.rect_down),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
width=(self.data.df_Artifact_a.iloc[i][3] - self.data.df_Artifact_a.iloc[i][2]),
height=self.rect_up - self.rect_down,
fill=True, alpha=ConfigParams.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
fill=True, alpha=Params.ARTIFACT_LABEL_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_DEEP_GREY)
self.rectangles_ax1_patches.append(rectangle)
for patch in self.rectangles_ax0_patches:
@ -560,7 +560,7 @@ class MainWindow_artifact_label(QMainWindow):
except Exception as e:
return Result().failure(info=Constants.UPDATE_FAILURE + Constants.FAILURE_REASON["Update_Info_Exception"] + "\n" + format_exc())
return Result().success(info=Constants.UPDATE_FAILURE)
return Result().success(info=Constants.UPDATE_FINISHED)
def __slot_btn_input__(self):
PublicFunc.__disableAllButton__(self, ButtonState)
@ -592,9 +592,6 @@ class MainWindow_artifact_label(QMainWindow):
else:
PublicFunc.text_output(self.ui, "(2/6)" + result.info, Constants.TIPS_TYPE_INFO)
self.__reset__()
PublicFunc.finish_operation(self, ButtonState)
# 获取存档
PublicFunc.progressbar_update(self, 3, 6, Constants.LOADING_ARCHIVE, 50)
result = self.data.get_archive()
@ -648,7 +645,6 @@ class MainWindow_artifact_label(QMainWindow):
ButtonState["Current"]["pushButton_prev_move"] = True
ButtonState["Current"]["pushButton_next_move"] = True
ButtonState["Current"]["pushButton_pause"] = True
ButtonState["Current"]["pushButton_save"] = True
ButtonState["Current"]["pushButton_type_1"] = True
ButtonState["Current"]["pushButton_type_2"] = True
ButtonState["Current"]["pushButton_type_3"] = True
@ -659,7 +655,12 @@ class MainWindow_artifact_label(QMainWindow):
def __slot_btn_label__(self):
sender = self.sender()
flag = False
select_row = array([]).astype(dict)
select_row = []
select_type = array([0, 0, 0, 0, 0])
flagf = False
flagb = False
start_time = 0
end_time = 0
if sender == self.ui.pushButton_type_1:
type = 1
@ -682,65 +683,153 @@ class MainWindow_artifact_label(QMainWindow):
for index, row in self.data.df_Artifact_a.iterrows():
value_startTime = row['startTime']
value_endTime = row['endTime']
value_type = row['type']
# if ((value_endTime >= int(self.ui.lineEdit_start_time.text()) and value_startTime <= int(self.ui.lineEdit_start_time.text())) or
# (value_endTime >= int(self.ui.lineEdit_end_time.text()) and value_startTime <= int(self.ui.lineEdit_end_time.text())) or
# (value_startTime >= int(self.ui.lineEdit_start_time.text()) and value_endTime <= int(self.ui.lineEdit_end_time.text())) or
# (value_startTime <= int(self.ui.lineEdit_start_time.text()) and value_endTime >= int(self.ui.lineEdit_end_time.text()))):
# select_row = append(select_row, row)
if ((value_startTime <= int(self.ui.lineEdit_end_time.text()) <= value_endTime) or
(value_startTime <= int(self.ui.lineEdit_start_time.text()) <= value_endTime) or
(value_startTime >= int(self.ui.lineEdit_start_time.text()) and value_endTime <= int(self.ui.lineEdit_end_time.text())) or
(0 < (int(self.ui.lineEdit_start_time.text()) - value_endTime) <= (2 * Config["InputConfig"]["UseFreq"])) or
(0 < (value_startTime - int(self.ui.lineEdit_end_time.text())) <= (2 * Config["InputConfig"]["UseFreq"]))):
select_row.append(row.to_dict())
if row['type'] == 1:
select_type[0] = select_type[0] + 1
elif row['type'] == 2:
select_type[1] = select_type[1] + 1
elif row['type'] == 3:
select_type[2] = select_type[2] + 1
elif row['type'] == 4:
select_type[3] = select_type[3] + 1
elif row['type'] == 5:
select_type[4] = select_type[4] + 1
if (0 < (int(self.ui.lineEdit_start_time.text()) - value_endTime) <= (2 * Config["InputConfig"]["UseFreq"])) and (value_type == type):
flagf = True
if (0 < (value_startTime - int(self.ui.lineEdit_end_time.text())) <= (2 * Config["InputConfig"]["UseFreq"])) and (value_type == type):
flagb = True
# TODO体动选取区域的判别尚未做的很完整选中多个已有的体动的区域时可能会出现问题
if (type == 1 and row['type'] == 1) or (type == 2 and row['type'] == 2) or (type == 3 and row['type'] == 3):
if ((value_startTime > int(self.ui.lineEdit_start_time.text()) and (value_startTime - int(self.ui.lineEdit_end_time.text()) <= 2 * Config["InputConfig"]["UseFreq"])) or
(value_endTime < int(self.ui.lineEdit_end_time.text()) and (int(self.ui.lineEdit_end_time.text()) - value_endTime <= 2 * Config["InputConfig"]["UseFreq"]))):
reply = QMessageBox.question(self, '确认', '{}{},是否确认合并?'.format(Constants.ARTIFACT_LABEL_MERGE, row['number']), QMessageBox.Yes | QMessageBox.No,
QMessageBox.No)
if reply == QMessageBox.Yes:
self.data.df_Artifact_a.loc[self.data.df_Artifact_a['number'] == row['number'],
['number', 'type', 'startTime', 'endTime']] = [
int(row['number']),
int(type),
int(self.ui.lineEdit_start_time.text()) if int(self.ui.lineEdit_start_time.text()) < int(row['startTime']) else int(row['startTime']),
int(self.ui.lineEdit_end_time.text()) if int(self.ui.lineEdit_end_time.text()) > int(row['endTime']) else int(row['endTime'])
]
new_row = {'number': int(row['number']),
'type': int(type),
'startTime': int(self.ui.lineEdit_start_time.text()),
'endTime': int(self.ui.lineEdit_end_time.text())}
flag = True
break
else:
return
if value_startTime <= int(self.ui.lineEdit_end_time.text()) and int(
self.ui.lineEdit_start_time.text()) <= value_endTime:
PublicFunc.msgbox_output(self, f"{Constants.ARTIFACT_LABEL_OVERLAPPING}{row['number']}", Constants.MSGBOX_TYPE_ERROR)
return
count = np_sum(select_type >= 1)
if count >= 2 or (count == 1 and nonzero(select_type)[0][0] + 1 == type):
if count >= 2:
reply = QMessageBox.question(self, '确认',
'{}{}'.format(Constants.ARTIFACT_LABEL_MULTIPLE_ARTIFACT_COVER_OR_DELETE, [d["number"] for d in select_row]),
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No)
if reply == QMessageBox.No:
return
if not flag:
new_row = {'number': int(len(self.data.df_Artifact_a) + 1),
'type': int(type),
'startTime': int(self.ui.lineEdit_start_time.text()),
'endTime': int(self.ui.lineEdit_end_time.text())}
self.data.df_Artifact_a = concat([self.data.df_Artifact_a, DataFrame([new_row])], ignore_index=True)
sorted_part = self.data.df_Artifact_a[['type', 'startTime', 'endTime']].sort_values(by='startTime').reset_index(
if flagf == True and flagb == False:
if type == 1 or type == 2 or type == 3:
PublicFunc.msgbox_output(self, Constants.ARTIFACT_LABEL_FRONT_TWO_SECONDS_MERGE,
Constants.MSGBOX_TYPE_INFO)
start_time = select_row[0]['startTime']
end_time = int(self.ui.lineEdit_end_time.text())
elif type == 4 or type == 5:
PublicFunc.msgbox_output(self, Constants.ARTIFACT_LABEL_FRONT_TWO_SECONDS_WARNING,
Constants.MSGBOX_TYPE_INFO)
select_row = select_row[1:]
start_time = int(self.ui.lineEdit_start_time.text())
end_time = int(self.ui.lineEdit_end_time.text())
if flagf == False and flagb == True:
if type == 1 or type == 2 or type == 3:
PublicFunc.msgbox_output(self, Constants.ARTIFACT_LABEL_BACK_TWO_SECONDS_MERGE,
Constants.MSGBOX_TYPE_INFO)
start_time = int(self.ui.lineEdit_start_time.text())
end_time = select_row[-1]['endTime']
elif type == 4 or type == 5:
PublicFunc.msgbox_output(self, Constants.ARTIFACT_LABEL_BACK_TWO_SECONDS_WARNING,
Constants.MSGBOX_TYPE_INFO)
select_row = select_row[:-1]
start_time = int(self.ui.lineEdit_start_time.text())
end_time = int(self.ui.lineEdit_end_time.text())
if flagf == True and flagb == True:
if type == 1 or type == 2 or type == 3:
PublicFunc.msgbox_output(self, Constants.ARTIFACT_LABEL_FRONT_AND_BACK_TWO_SECONDS_MERGE,
Constants.MSGBOX_TYPE_INFO)
start_time = select_row[0]['startTime']
end_time = select_row[-1]['endTime']
elif type == 4 or type == 5:
PublicFunc.msgbox_output(self, Constants.ARTIFACT_LABEL_FRONT_AND_BACK_TWO_SECONDS_WARNING,
Constants.MSGBOX_TYPE_INFO)
select_row = select_row[1:-1]
start_time = int(self.ui.lineEdit_start_time.text())
end_time = int(self.ui.lineEdit_end_time.text())
if flagf == False and flagb == False:
start_time = int(self.ui.lineEdit_start_time.text())
end_time = int(self.ui.lineEdit_end_time.text())
for select_each_row in select_row:
self.data.df_Artifact_a = self.data.df_Artifact_a[self.data.df_Artifact_a['number'] != select_each_row["number"]]
else:
select_row = []
select_type = array([0, 0, 0, 0, 0])
for index, row in self.data.df_Artifact_a.iterrows():
value_startTime = row['startTime']
value_endTime = row['endTime']
value_type = row['type']
if ((value_startTime <= int(self.ui.lineEdit_end_time.text()) <= value_endTime) or
(value_startTime <= int(self.ui.lineEdit_start_time.text()) <= value_endTime) or
(value_startTime >= int(self.ui.lineEdit_start_time.text()) and value_endTime <= int(
self.ui.lineEdit_end_time.text()))):
select_row.append(row.to_dict())
if row['type'] == 1:
select_type[0] = select_type[0] + 1
elif row['type'] == 2:
select_type[1] = select_type[1] + 1
elif row['type'] == 3:
select_type[2] = select_type[2] + 1
elif row['type'] == 4:
select_type[3] = select_type[3] + 1
elif row['type'] == 5:
select_type[4] = select_type[4] + 1
count = np_sum(select_type >= 1)
if (count == 1 and nonzero(select_type)[0][0] + 1 != type):
reply = QMessageBox.question(self, '确认',
'{}{}'.format(Constants.ARTIFACT_LABEL_SINGLE_TYPE_NOT_EQUAL,
[d["number"] for d in select_row]),
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No)
if reply == QMessageBox.No:
return
start_time = int(self.ui.lineEdit_start_time.text())
end_time = int(self.ui.lineEdit_end_time.text())
for select_each_row in select_row:
self.data.df_Artifact_a = self.data.df_Artifact_a[self.data.df_Artifact_a['number'] != select_each_row["number"]]
elif count == 0:
start_time = int(self.ui.lineEdit_start_time.text())
end_time = int(self.ui.lineEdit_end_time.text())
else:
raise ValueError("count值不存在")
new_row = {
'number': 1,
'type': int(type),
'startTime': start_time,
'endTime': end_time
}
self.data.df_Artifact_a = concat([self.data.df_Artifact_a, DataFrame([new_row])], ignore_index=True)
self.data.df_Artifact_a[['type', 'startTime', 'endTime']] = self.data.df_Artifact_a[['type', 'startTime', 'endTime']].sort_values(by='startTime').reset_index(
drop=True)
self.data.df_Artifact_a[['type', 'startTime', 'endTime']] = sorted_part
self.data.df_Artifact_a['number'] = range(1, len(self.data.df_Artifact_a) + 1)
self.update_tableWidget()
self.update_Info()
self.__plot_artifact__()
target_row = self.data.df_Artifact_a[
self.data.df_Artifact_a.eq(int(self.ui.lineEdit_start_time.text())).any(axis=1)]
target_row = self.data.df_Artifact_a[self.data.df_Artifact_a.eq(start_time).any(axis=1)]
if not target_row.empty:
first_column_value = target_row.iloc[0, 0] # 获取第1列的值
else:
raise AttributeError()
PublicFunc.text_output(self.ui, f"新增体动标签{first_column_value}, 类型{new_row['type']},从{int(self.ui.lineEdit_start_time.text())}ms到{int(self.ui.lineEdit_end_time.text())}ms", Constants.TIPS_TYPE_INFO)
PublicFunc.text_output(self.ui, f"新增体动标签{first_column_value}, 类型{new_row['type']},从{int(start_time)}ms到{int(end_time)}ms", Constants.TIPS_TYPE_INFO)
self.__slot_btn_save__()
self.save()
def __slot_btn_save__(self):
def save(self):
PublicFunc.__disableAllButton__(self, ButtonState)
# 保存
@ -791,7 +880,7 @@ class MainWindow_artifact_label(QMainWindow):
self.update_tableWidget()
self.update_Info()
self.__plot_artifact__()
self.__slot_btn_save__()
self.save()
PublicFunc.text_output(self.ui, f"{self.pressed_number}{Constants.ARTIFACT_LABEL_DELETE_ARTIFACT_SUCCESSFULLY}", Constants.TIPS_TYPE_INFO)
else:
PublicFunc.text_output(self.ui, f"{self.pressed_number}{Constants.ARTIFACT_LABEL_DELETE_ARTIFACT_FAILURE}", Constants.TIPS_TYPE_ERROR)
@ -929,13 +1018,15 @@ class MainWindow_artifact_label(QMainWindow):
PublicFunc.text_output(self.ui, f"{Constants.ARTIFACT_LABEL_JUMP_ARTIFACT}{str(self.pressed_number)}", Constants.TIPS_TYPE_INFO)
def reset_axes(self):
self.ax0.clear()
self.ax1.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
if self.ax0 is not None:
self.ax0.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
if self.ax1 is not None:
self.ax1.clear()
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
def on_xlim_change(self, event_ax):
try:
@ -1208,17 +1299,14 @@ class Data:
if Path(Config["Path"]["Input_BCG"]).is_file():
Config["Path"]["Input_BCG"] = str(Path(Config["Path"]["Input_BCG"]).parent)
if (not Path(Config["Path"]["Input_orgBcg"]).exists()) or (not Path(Config["Path"]["Input_BCG"]).exists()):
return Result().failure(info=Constants.INPUT_FAILURE + Constants.FAILURE_REASON["Path_Not_Exist"])
result = PublicFunc.examine_file(Config["Path"]["Input_orgBcg"], ConfigParams.ORGBCG_SYNC)
result = PublicFunc.examine_file(Config["Path"]["Input_orgBcg"], Filename.ORGBCG_SYNC, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_orgBcg"] = result.data["path"]
Config["InputConfig"]["orgBcgFreq"] = result.data["freq"]
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_BCG"], ConfigParams.BCG_SYNC)
result = PublicFunc.examine_file(Config["Path"]["Input_BCG"], Filename.BCG_SYNC, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_BCG"] = result.data["path"]
Config["InputConfig"]["BCGFreq"] = result.data["freq"]
@ -1226,18 +1314,18 @@ class Data:
return result
Config["Path"]["Save_a"] = str(
Path(Config["Path"]["Save_a"]) / Path(ConfigParams.ARTIFACT_A + ConfigParams.ENDSWITH_TXT))
Path(Config["Path"]["Save_a"]) / Path(Filename.ARTIFACT_A + str(Config["InputConfig"]["UseFreq"]) + Params.ENDSWITH_TXT))
Config["Path"]["Save_b"] = str(
Path(Config["Path"]["Save_b"]) / Path(ConfigParams.ARTIFACT_B + ConfigParams.ENDSWITH_TXT))
Path(Config["Path"]["Save_b"]) / Path(Filename.ARTIFACT_B + str(Config["InputConfig"]["UseFreq"]) + Params.ENDSWITH_TXT))
Config["Path"]["Save_c"] = str(
Path(Config["Path"]["Save_c"]) / Path(ConfigParams.ARTIFACT_C + ConfigParams.ENDSWITH_CSV))
Path(Config["Path"]["Save_c"]) / Path(Filename.ARTIFACT_C + str(Config["InputConfig"]["UseFreq"]) + Params.ENDSWITH_CSV))
try:
self.orgBcg = read_csv(Config["Path"]["Input_orgBcg"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.BCG = read_csv(Config["Path"]["Input_BCG"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
except Exception as e:
return Result().failure(info=Constants.INPUT_FAILURE + Constants.FAILURE_REASON["Open_Data_Exception"] + "\n" + format_exc())
@ -1271,7 +1359,7 @@ class Data:
return Result().success(info=Constants.ARCHIVE_NOT_EXIST)
else:
self.Artifact_a = read_csv(Config["Path"]["Save_a"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
try:
# 检查体动标签正确性,长度
@ -1290,13 +1378,6 @@ class Data:
return Result().success(info=Constants.ARCHIVE_EXIST)
def save(self, amount, duration):
if (not Path(Config["Path"]["Save_a"]).parent.exists()) or (not Path(Config["Path"]["Save_a"]).parent.is_dir()):
Path(Config["Path"]["Save_a"]).parent.mkdir(parents=True, exist_ok=True)
if (not Path(Config["Path"]["Save_b"]).parent.exists()) or (not Path(Config["Path"]["Save_b"]).parent.is_dir()):
Path(Config["Path"]["Save_b"]).parent.mkdir(parents=True, exist_ok=True)
if (not Path(Config["Path"]["Save_c"]).parent.exists()) or (not Path(Config["Path"]["Save_c"]).parent.is_dir()):
Path(Config["Path"]["Save_c"]).parent.mkdir(parents=True, exist_ok=True)
try:
# Artifact_a.txt和Artifact_c.csv的内容遍历
output_lines = []
@ -1317,7 +1398,7 @@ class Data:
self.df_Artifact_a.to_csv(Path(Config["Path"]["Save_a"]), header=False, index=False, sep='\n')
df_Artifact_b.to_csv(Path(Config["Path"]["Save_b"]), header=False, index=False, sep='\n')
self.df_Artifact_a.to_csv(Path(Config["Path"]["Save_c"]), index=False,
encoding=ConfigParams.GBK_ENCODING)
encoding=Params.GBK_ENCODING)
except Exception as e:
return Result().failure(info=Constants.SAVE_FAILURE + Constants.FAILURE_REASON[
"Save_Exception"] + "\n" + format_exc())
@ -1331,19 +1412,19 @@ class CustomNavigationToolbar(NavigationToolbar2QT):
super().__init__(canvas, parent)
# 初始化画框工具栏
self.action_Label_Artifact = QAction(Constants.ARTIFACT_LABEL_ACTION_LABEL, self)
self.action_Label_Artifact.setFont(QFont(ConfigParams.FONT, 14))
self.action_Label_Artifact.setFont(QFont(Params.FONT, 14))
self.action_Label_Artifact.setCheckable(True)
self.action_Label_Artifact.setShortcut(QCoreApplication.translate(
"MainWindow",
ConfigParams.ARTIFACT_LABEL_ACTION_LABEL_ARTIFACT_SHORTCUT_KEY))
Params.ARTIFACT_LABEL_ACTION_LABEL_ARTIFACT_SHORTCUT_KEY))
self.insertAction(self._actions['pan'], self.action_Label_Artifact)
self._actions['pan'].setShortcut(QCoreApplication.translate(
"MainWindow",
ConfigParams.ACTION_PAN_SHORTCUT_KEY))
Params.ACTION_PAN_SHORTCUT_KEY))
self._actions['zoom'].setShortcut(QCoreApplication.translate(
"MainWindow",
ConfigParams.ACTION_ZOOM_SHORTCUT_KEY))
Params.ACTION_ZOOM_SHORTCUT_KEY))
# 用于存储事件连接ID
self.cid_mouse_press = None

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,9 @@ from overrides import overrides
from pandas import read_csv, DataFrame
from yaml import dump, load, FullLoader
from func.utils.ConfigParams import Filename, Params
from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants, ConfigParams
from func.utils.Constants import Constants
from func.utils.Result import Result
from ui.MainWindow.MainWindow_cut_PSG import Ui_MainWindow_cut_PSG
@ -62,9 +63,9 @@ class MainWindow_cut_PSG(QMainWindow):
Config.update({
"Path": {
"InputFolder": str(Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT / Path(str(self.sampID))),
"SaveFolder": str(Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED / Path(str(self.sampID))),
"InputAlignInfo": str(Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL / Path(str(self.sampID)))
"InputFolder": str(Path(self.root_path) / Filename.PATH_PSG_TEXT / Path(str(self.sampID))),
"SaveFolder": str(Path(self.root_path) / Filename.PATH_PSG_ALIGNED / Path(str(self.sampID))),
"InputAlignInfo": str(Path(self.root_path) / Filename.PATH_LABEL / Path(str(self.sampID)))
}
})
@ -94,11 +95,11 @@ class MainWindow_cut_PSG(QMainWindow):
ButtonState["Current"].update(ButtonState["Default"].copy())
def __read_config__(self):
if not Path(ConfigParams.CUT_PSG_CONFIG_FILE_PATH).exists():
with open(ConfigParams.CUT_PSG_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.CUT_PSG_CONFIG_NEW_CONTENT, f)
if not Path(Params.CUT_PSG_CONFIG_FILE_PATH).exists():
with open(Params.CUT_PSG_CONFIG_FILE_PATH, "w") as f:
dump(Params.CUT_PSG_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.CUT_PSG_CONFIG_FILE_PATH, "r") as f:
with open(Params.CUT_PSG_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
@ -231,9 +232,9 @@ class Data:
return Result().success(info=Constants.CUT_PSG_GET_FILE_AND_FREQ_FINISHED)
def open_file(self):
path = str(Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT / Path(str(self.sampID)))
path = str(Path(self.root_path) / Filename.PATH_PSG_TEXT / Path(str(self.sampID)))
for value in Config["ChannelInput"].values():
result = PublicFunc.examine_file(path, value)
result = PublicFunc.examine_file(path, value, Params.ENDSWITH_TXT)
if not result.status:
return result
@ -242,20 +243,20 @@ class Data:
Config["Path"]["InputAlignInfo"] = str(
Path(Config["Path"]["InputAlignInfo"]) / Path(
ConfigParams.PRECISELY_ALIGN_INFO + ConfigParams.ENDSWITH_TXT))
Filename.PRECISELY_ALIGN_INFO + Params.ENDSWITH_TXT))
try:
for key in Config["ChannelInput"].keys():
self.raw[key] = read_csv(Path(Config["Path"]["InputFolder"]) / Path((Config["ChannelInput"][key] + str(self.freq[key]) + Config["EndWith"][key])),
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.SALabel = read_csv(Path(Config["Path"]["InputFolder"]) / Path((Config["LabelInput"]["SA Label"] + Config["EndWith"]["SA Label"])),
encoding=ConfigParams.GBK_ENCODING)
encoding=Params.GBK_ENCODING)
self.startTime = read_csv(Path(Config["Path"]["InputFolder"]) / Path((Config["StartTime"] + Config["EndWith"]["StartTime"])),
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.alignInfo = read_csv(Path(Config["Path"]["InputAlignInfo"]),
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.alignInfo = literal_eval(self.alignInfo[0])
except Exception as e:
@ -290,7 +291,7 @@ class Data:
try:
# 读取SA标签
self.SALabel = self.SALabel.loc[:, ~self.SALabel.columns.str.contains("^Unnamed")]
self.SALabel = self.SALabel[self.SALabel["Event type"].isin(ConfigParams.CUT_PSG_SALABEL_EVENT)]
self.SALabel = self.SALabel[self.SALabel["Event type"].isin(Params.CUT_PSG_SALABEL_EVENT)]
self.SALabel["Duration"] = self.SALabel["Duration"].astype(str)
self.SALabel["Duration"] = self.SALabel["Duration"].str.replace(r' \(.*?\)', '', regex=True)
except Exception:
@ -322,9 +323,6 @@ class Data:
return Result().success(info=Constants.CUT_PSG_ALIGN_LABEL_FINISHED)
def save(self):
if (not Path(Config["Path"]["SaveFolder"]).exists()) or (not Path(Config["Path"]["SaveFolder"]).is_dir()):
Path(Config["Path"]["SaveFolder"]).mkdir(parents=True, exist_ok=True)
for raw in self.raw.values():
if len(raw) == 0:
return Result().failure(info=Constants.SAVE_FAILURE +

View File

@ -11,8 +11,9 @@ from overrides import overrides
from pandas import read_csv, DataFrame
from yaml import dump, load, FullLoader
from func.utils.ConfigParams import Filename, Params
from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants, ConfigParams
from func.utils.Constants import Constants
from func.utils.Result import Result
from func.utils.detect_Jpeak import preprocess, Jpeak_Detection
@ -59,20 +60,20 @@ class SettingWindow(QMainWindow):
self.ui.pushButton_cancel.clicked.connect(self.close)
def __read_config__(self):
if not Path(ConfigParams.DETECT_JPEAK_CONFIG_FILE_PATH).exists():
with open(ConfigParams.DETECT_JPEAK_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.DETECT_JPEAK_CONFIG_NEW_CONTENT, f)
if not Path(Params.DETECT_JPEAK_CONFIG_FILE_PATH).exists():
with open(Params.DETECT_JPEAK_CONFIG_FILE_PATH, "w") as f:
dump(Params.DETECT_JPEAK_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.DETECT_JPEAK_CONFIG_FILE_PATH, "r") as f:
with open(Params.DETECT_JPEAK_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
self.config = file_config
Config.update({
"Path": {
"Input": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
"Input": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Save": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
"Save": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID))))
}
})
@ -94,7 +95,7 @@ class SettingWindow(QMainWindow):
self.config["InputConfig"]["Freq"] = self.ui.spinBox_input_freq.value()
self.config["ModelFolderPath"] = self.ui.plainTextEdit_deepmodel_path.toPlainText()
with open(ConfigParams.DETECT_JPEAK_CONFIG_FILE_PATH, "w") as f:
with open(Params.DETECT_JPEAK_CONFIG_FILE_PATH, "w") as f:
dump(self.config, f)
self.close()
@ -105,18 +106,18 @@ class SettingWindow(QMainWindow):
def __update_ui__(self):
self.ui.plainTextEdit_file_path_input.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.BCG_FILTER +
Path(Filename.BCG_FILTER +
str(self.ui.spinBox_input_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.JPEAK_REVISE +
Path(Filename.JPEAK_REVISE +
str(self.ui.spinBox_input_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
class MainWindow_detect_Jpeak(QMainWindow):
@ -169,7 +170,7 @@ class MainWindow_detect_Jpeak(QMainWindow):
self.fig.subplots_adjust(top=0.98, bottom=0.05, right=0.98, left=0.1, hspace=0, wspace=0)
self.ax0 = self.fig.add_subplot(self.gs[0])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
PublicFunc.__resetAllButton__(self, ButtonState)
@ -204,7 +205,8 @@ class MainWindow_detect_Jpeak(QMainWindow):
QApplication.processEvents()
# 清空画框
self.ax0.clear()
if self.ax0 is not None:
self.ax0.clear()
# 释放资源
del self.data
@ -354,7 +356,7 @@ class MainWindow_detect_Jpeak(QMainWindow):
PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0)
total_rows = len(DataFrame(self.data.peak.reshape(-1)))
chunk_size = ConfigParams.DETECT_JPEAK_SAVE_CHUNK_SIZE
chunk_size = Params.DETECT_JPEAK_SAVE_CHUNK_SIZE
with open(Config["Path"]["Save"], 'w') as f:
for start in range(0, total_rows, chunk_size):
end = min(start + chunk_size, total_rows)
@ -378,7 +380,7 @@ class MainWindow_detect_Jpeak(QMainWindow):
def reset_axes(self):
self.ax0.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
def update_ui_comboBox_model(self, model_list):
self.ui.comboBox_model.clear()
@ -397,21 +399,18 @@ class Data:
if Path(Config["Path"]["Input"]).is_file():
Config["Path"]["Input"] = str(Path(Config["Path"]["Input"]).parent)
if not Path(Config["Path"]["Input"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + Constants.FAILURE_REASON["Path_Not_Exist"])
result = PublicFunc.examine_file(Config["Path"]["Input"], ConfigParams.BCG_FILTER)
result = PublicFunc.examine_file(Config["Path"]["Input"], Filename.BCG_FILTER, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input"] = result.data["path"]
Config["InputConfig"]["Freq"] = result.data["freq"]
Config["Path"]["Save"] = str(
Path(Config["Path"]["Save"]) / Path(ConfigParams.JPEAK_REVISE + str(Config["InputConfig"]["Freq"]) + ConfigParams.ENDSWITH_TXT))
Path(Config["Path"]["Save"]) / Path(Filename.JPEAK_REVISE + str(Config["InputConfig"]["Freq"]) + Params.ENDSWITH_TXT))
else:
return result
try:
self.raw_data = read_csv(Config["Path"]["Input"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
except Exception as e:
return Result().failure(info=Constants.INPUT_FAILURE +
@ -461,9 +460,6 @@ class Data:
return Result().success(info=Constants.DETECT_JPEAK_PREDICT_FINISHED)
def save(self, chunk):
if (not Path(Config["Path"]["Save"]).parent.exists()) or (not Path(Config["Path"]["Save"]).parent.is_dir()):
Path(Config["Path"]["Save"]).parent.mkdir(parents=True, exist_ok=True)
if self.peak is None:
return Result().failure(info=Constants.SAVE_FAILURE + Constants.FAILURE_REASON["Data_Not_Exist"])

View File

@ -11,8 +11,9 @@ from overrides import overrides
from pandas import read_csv, DataFrame
from yaml import dump, load, FullLoader
from func.utils.ConfigParams import Filename, Params
from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants, ConfigParams
from func.utils.Constants import Constants
from func.utils.Result import Result
from func.utils.detect_Rpeak import preprocess, Rpeak_Detection, get_method
@ -59,20 +60,20 @@ class SettingWindow(QMainWindow):
self.ui.pushButton_cancel.clicked.connect(self.close)
def __read_config__(self):
if not Path(ConfigParams.DETECT_RPEAK_CONFIG_FILE_PATH).exists():
with open(ConfigParams.DETECT_RPEAK_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.DETECT_RPEAK_CONFIG_NEW_CONTENT, f)
if not Path(Params.DETECT_RPEAK_CONFIG_FILE_PATH).exists():
with open(Params.DETECT_RPEAK_CONFIG_FILE_PATH, "w") as f:
dump(Params.DETECT_RPEAK_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.DETECT_RPEAK_CONFIG_FILE_PATH, "r") as f:
with open(Params.DETECT_RPEAK_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
self.config = file_config
Config.update({
"Path": {
"Input": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Input": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Save": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Save": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID))))
}
})
@ -91,7 +92,7 @@ class SettingWindow(QMainWindow):
# 保存配置到文件
self.config["InputConfig"]["Freq"] = self.ui.spinBox_input_freq.value()
with open(ConfigParams.DETECT_RPEAK_CONFIG_FILE_PATH, "w") as f:
with open(Params.DETECT_RPEAK_CONFIG_FILE_PATH, "w") as f:
dump(self.config, f)
self.close()
@ -102,18 +103,18 @@ class SettingWindow(QMainWindow):
def __update_ui__(self):
self.ui.plainTextEdit_file_path_input.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.ECG_FILTER +
Path(Filename.ECG_FILTER +
str(self.ui.spinBox_input_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.RPEAK_FINAL +
Path(Filename.RPEAK_FINAL +
str(self.ui.spinBox_input_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
class MainWindow_detect_Rpeak(QMainWindow):
@ -166,11 +167,11 @@ class MainWindow_detect_Rpeak(QMainWindow):
self.fig.subplots_adjust(top=0.98, bottom=0.05, right=0.98, left=0.1, hspace=0, wspace=0)
self.ax0 = self.fig.add_subplot(self.gs[0])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax1 = self.fig.add_subplot(self.gs[1], sharex=self.ax0)
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
PublicFunc.__resetAllButton__(self, ButtonState)
@ -197,8 +198,10 @@ class MainWindow_detect_Rpeak(QMainWindow):
QApplication.processEvents()
# 清空画框
self.ax0.clear()
self.ax1.clear()
if self.ax0 is not None:
self.ax0.clear()
if self.ax1 is not None:
self.ax1.clear()
# 释放资源
del self.data
@ -349,7 +352,7 @@ class MainWindow_detect_Rpeak(QMainWindow):
PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0)
total_rows = len(DataFrame(self.data.peak.reshape(-1)))
chunk_size = ConfigParams.DETECT_RPEAK_SAVE_CHUNK_SIZE
chunk_size = Params.DETECT_RPEAK_SAVE_CHUNK_SIZE
with open(Config["Path"]["Save"], 'w') as f:
for start in range(0, total_rows, chunk_size):
end = min(start + chunk_size, total_rows)
@ -374,10 +377,10 @@ class MainWindow_detect_Rpeak(QMainWindow):
self.ax0.clear()
self.ax1.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
def update_ui_comboBox_method(self, method_list):
self.ui.comboBox_method.clear()
@ -397,21 +400,18 @@ class Data:
if Path(Config["Path"]["Input"]).is_file():
Config["Path"]["Input"] = str(Path(Config["Path"]["Input"]).parent)
if not Path(Config["Path"]["Input"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + Constants.FAILURE_REASON["Path_Not_Exist"])
result = PublicFunc.examine_file(Config["Path"]["Input"], ConfigParams.ECG_FILTER)
result = PublicFunc.examine_file(Config["Path"]["Input"], Filename.ECG_FILTER, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input"] = result.data["path"]
Config["InputConfig"]["Freq"] = result.data["freq"]
Config["Path"]["Save"] = str(
Path(Config["Path"]["Save"]) / Path(ConfigParams.RPEAK_FINAL + str(Config["InputConfig"]["Freq"]) + ConfigParams.ENDSWITH_TXT))
Path(Config["Path"]["Save"]) / Path(Filename.RPEAK_FINAL + str(Config["InputConfig"]["Freq"]) + Params.ENDSWITH_TXT))
else:
return result
try:
self.raw_data = read_csv(Config["Path"]["Input"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
except Exception as e:
return Result().failure(info=Constants.INPUT_FAILURE +
@ -452,9 +452,6 @@ class Data:
return Result().success(info=Constants.DETECT_RPEAK_PREDICT_FINISHED)
def save(self, chunk):
if (not Path(Config["Path"]["Save"]).parent.exists()) or (not Path(Config["Path"]["Save"]).parent.is_dir()):
Path(Config["Path"]["Save"]).parent.mkdir(parents=True, exist_ok=True)
if self.peak is None:
return Result().failure(info=Constants.SAVE_FAILURE + Constants.FAILURE_REASON["Data_Not_Exist"])

View File

@ -9,14 +9,15 @@ from PySide6.QtWidgets import QMessageBox, QMainWindow, QApplication, QTableWidg
from matplotlib import gridspec, patches
from matplotlib.backends.backend_qt import NavigationToolbar2QT
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
from numpy import append, delete, arange
from numpy import append, delete, arange, setdiff1d
from overrides import overrides
from pandas import read_csv, DataFrame
from scipy.signal import find_peaks
from yaml import dump, load, FullLoader
from func.utils.ConfigParams import Filename, Params
from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants, ConfigParams
from func.utils.Constants import Constants
from func.Filters.Preprocessing import data_preprocess_for_label_check
from func.utils.Result import Result
@ -34,16 +35,14 @@ ButtonState = {
"pushButton_input": True,
"pushButton_prev_move": False,
"pushButton_pause": False,
"pushButton_next_move": False,
"pushButton_save": False
"pushButton_next_move": False
},
"Current": {
"pushButton_input_setting": True,
"pushButton_input": True,
"pushButton_prev_move": False,
"pushButton_pause": False,
"pushButton_next_move": False,
"pushButton_save": False
"pushButton_next_move": False
}
}
@ -71,11 +70,11 @@ class SettingWindow(QMainWindow):
self.ui.pushButton_cancel.clicked.connect(self.close)
def __read_config__(self):
if not Path(ConfigParams.LABEL_CHECK_CONFIG_FILE_PATH).exists():
with open(ConfigParams.LABEL_CHECK_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.LABEL_CHECK_CONFIG_NEW_CONTENT, f)
if not Path(Params.LABEL_CHECK_CONFIG_FILE_PATH).exists():
with open(Params.LABEL_CHECK_CONFIG_FILE_PATH, "w") as f:
dump(Params.LABEL_CHECK_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.LABEL_CHECK_CONFIG_FILE_PATH, "r") as f:
with open(Params.LABEL_CHECK_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
self.config = file_config
@ -83,13 +82,13 @@ class SettingWindow(QMainWindow):
if self.mode == "BCG":
Config.update({
"Path": {
"Input_Signal": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Input_Peak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Input_Approximately_Align": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL /
"Input_Signal": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Input_Peak": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Input_Approximately_Align": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID)))),
"Save": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
"Save": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID))))
},
"Mode": self.mode
@ -97,13 +96,13 @@ class SettingWindow(QMainWindow):
elif self.mode == "ECG":
Config.update({
"Path": {
"Input_Signal": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Input_Peak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Input_Approximately_Align": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL /
"Input_Signal": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Input_Peak": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Input_Approximately_Align": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID)))),
"Save": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Save": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID))))
},
"Mode": self.mode
@ -149,7 +148,7 @@ class SettingWindow(QMainWindow):
# 保存配置到文件
self.config["InputConfig"]["Freq"] = self.ui.spinBox_input_freq_signal.value()
with open(ConfigParams.LABEL_CHECK_CONFIG_FILE_PATH, "w") as f:
with open(Params.LABEL_CHECK_CONFIG_FILE_PATH, "w") as f:
dump(self.config, f)
self.close()
@ -161,47 +160,47 @@ class SettingWindow(QMainWindow):
if self.mode == "BCG":
self.ui.plainTextEdit_file_path_input_signal.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.BCG_FILTER +
Path(Filename.BCG_FILTER +
str(self.ui.spinBox_input_freq_signal.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_peak.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.JPEAK_REVISE +
Path(Filename.JPEAK_REVISE +
str(self.ui.spinBox_input_freq_signal.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.JPEAK_REVISE_CORRECTED +
Path(Filename.JPEAK_REVISE_CORRECTED +
str(self.ui.spinBox_input_freq_signal.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
elif self.mode == "ECG":
self.ui.plainTextEdit_file_path_input_signal.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.ECG_FILTER +
Path(Filename.ECG_FILTER +
str(self.ui.spinBox_input_freq_signal.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_peak.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.RPEAK_FINAL +
Path(Filename.RPEAK_FINAL +
str(self.ui.spinBox_input_freq_signal.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.RPEAK_FINAL_CORRECTED +
Path(Filename.RPEAK_FINAL_CORRECTED +
str(self.ui.spinBox_input_freq_signal.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
else:
raise ValueError("模式不存在")
@ -283,11 +282,11 @@ class MainWindow_label_check(QMainWindow):
self.fig.subplots_adjust(top=0.98, bottom=0.05, right=0.98, left=0.1, hspace=0, wspace=0)
self.ax0 = self.fig.add_subplot(self.gs[0])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax1 = self.fig.add_subplot(self.gs[1], sharex=self.ax0, sharey=self.ax0)
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
PublicFunc.__resetAllButton__(self, ButtonState)
@ -307,7 +306,6 @@ class MainWindow_label_check(QMainWindow):
self.ui.pushButton_input.clicked.connect(self.__slot_btn_input__)
self.ui.pushButton_input_setting.clicked.connect(self.setting.show)
self.ui.pushButton_save.clicked.connect(self.__slot_btn_save__)
self.ui.pushButton_prev_move.clicked.connect(self.__slot_btn_move__)
self.ui.pushButton_pause.clicked.connect(self.__slot_btn_move__)
self.ui.pushButton_next_move.clicked.connect(self.__slot_btn_move__)
@ -340,8 +338,10 @@ class MainWindow_label_check(QMainWindow):
del self.point_peak_original
del self.point_peak_corrected
del self.annotation_tableWidget
self.ax0.clear()
self.ax1.clear()
if self.ax0 is not None:
self.ax0.clear()
if self.ax1 is not None:
self.ax1.clear()
# 释放资源
del self.data
@ -464,70 +464,81 @@ class MainWindow_label_check(QMainWindow):
self.data = Data()
# 导入数据
PublicFunc.progressbar_update(self, 1, 6, Constants.INPUTTING_DATA, 0)
PublicFunc.progressbar_update(self, 1, 7, Constants.INPUTTING_DATA, 0)
result = self.data.open_file()
if not result.status:
PublicFunc.text_output(self.ui, "(1/6)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.text_output(self.ui, "(1/7)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.msgbox_output(self, result.info, Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
else:
PublicFunc.text_output(self.ui, "(1/6)" + result.info, Constants.TIPS_TYPE_INFO)
PublicFunc.text_output(self.ui, "(1/7)" + result.info, Constants.TIPS_TYPE_INFO)
# 获取存档
PublicFunc.progressbar_update(self, 2, 6, Constants.LOADING_ARCHIVE, 20)
PublicFunc.progressbar_update(self, 2, 7, Constants.LOADING_ARCHIVE, 20)
result = self.data.get_archive()
if not result.status:
PublicFunc.text_output(self.ui, "(2/6)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.text_output(self.ui, "(2/7)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.msgbox_output(self, result.info, Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
else:
PublicFunc.text_output(self.ui, "(2/6)" + result.info, Constants.TIPS_TYPE_INFO)
PublicFunc.text_output(self.ui, "(2/7)" + result.info, Constants.TIPS_TYPE_INFO)
# 保存
PublicFunc.progressbar_update(self, 3, 7, Constants.SAVING_DATA, 25)
result = self.data.save()
if not result.status:
PublicFunc.text_output(self.ui, "(3/7)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.msgbox_output(self, result.info, Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
else:
PublicFunc.text_output(self.ui, "(3/7)" + result.info, Constants.TIPS_TYPE_INFO)
# 数据预处理
PublicFunc.progressbar_update(self, 3, 6, Constants.PREPROCESSING_DATA, 30)
PublicFunc.progressbar_update(self, 4, 7, Constants.PREPROCESSING_DATA, 30)
result = self.data.preprocess()
if not result.status:
PublicFunc.text_output(self.ui, "(3/6)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.text_output(self.ui, "(4/7)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.msgbox_output(self, result.info, Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
else:
PublicFunc.text_output(self.ui, "(3/6)" + result.info, Constants.TIPS_TYPE_INFO)
PublicFunc.text_output(self.ui, "(4/7)" + result.info, Constants.TIPS_TYPE_INFO)
# 更新表格
PublicFunc.progressbar_update(self, 4, 6, Constants.UPDATING_TABLEWIDGET_AND_INFO, 50)
PublicFunc.progressbar_update(self, 5, 7, Constants.UPDATING_TABLEWIDGET_AND_INFO, 50)
result = self.__update_tableWidget_and_info__()
if not result.status:
PublicFunc.text_output(self.ui, "(4/6)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.text_output(self.ui, "(5/7)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.msgbox_output(self, result.info, Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
else:
PublicFunc.text_output(self.ui, "(4/6)" + result.info, Constants.TIPS_TYPE_INFO)
PublicFunc.text_output(self.ui, "(5/7)" + result.info, Constants.TIPS_TYPE_INFO)
# 绘图
PublicFunc.progressbar_update(self, 5, 6, Constants.DRAWING_DATA, 60)
PublicFunc.progressbar_update(self, 6, 7, Constants.DRAWING_DATA, 60)
result = self.__plot__()
if not result.status:
PublicFunc.text_output(self.ui, "(5/6)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.text_output(self.ui, "(6/7)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.msgbox_output(self, result.info, Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
else:
PublicFunc.text_output(self.ui, "(5/6)" + result.info, Constants.TIPS_TYPE_INFO)
PublicFunc.text_output(self.ui, "(6/7)" + result.info, Constants.TIPS_TYPE_INFO)
# 绘点
PublicFunc.progressbar_update(self, 6, 6, Constants.DRAWING_DATA, 80)
PublicFunc.progressbar_update(self, 7, 7, Constants.DRAWING_DATA, 80)
result = self.__plot_peaks__()
if not result.status:
PublicFunc.text_output(self.ui, "(6/6)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.text_output(self.ui, "(7/7)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.msgbox_output(self, result.info, Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
else:
PublicFunc.text_output(self.ui, "(6/6)" + result.info, Constants.TIPS_TYPE_INFO)
PublicFunc.text_output(self.ui, "(7/7)" + result.info, Constants.TIPS_TYPE_INFO)
self.__reset__()
self.canvas.mpl_connect("motion_notify_event", self.on_motion)
@ -539,42 +550,8 @@ class MainWindow_label_check(QMainWindow):
ButtonState["Current"]["pushButton_prev_move"] = True
ButtonState["Current"]["pushButton_next_move"] = True
ButtonState["Current"]["pushButton_pause"] = True
ButtonState["Current"]["pushButton_save"] = True
PublicFunc.finish_operation(self, ButtonState)
def __slot_btn_save__(self):
reply = QMessageBox.question(self, Constants.QUESTION_TITLE,
Constants.QUESTION_CONTENT + Config["Path"]["Save"],
QMessageBox.Yes | QMessageBox.No,
QMessageBox.Yes)
if reply == QMessageBox.Yes:
PublicFunc.__disableAllButton__(self, ButtonState)
# 保存
PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0)
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:
for start in range(0, total_rows, chunk_size):
end = min(start + chunk_size, total_rows)
chunk = DataFrame(self.data.corrected_peak.reshape(-1)).iloc[start:end]
result = self.data.save(chunk)
progress = int((end / total_rows) * 100)
self.progressbar.setValue(progress)
QApplication.processEvents()
if not result.status:
PublicFunc.text_output(self.ui, "(1/1)" + result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.msgbox_output(self, result.info, Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
else:
PublicFunc.text_output(self.ui, "(1/1)" + result.info, Constants.TIPS_TYPE_INFO)
PublicFunc.msgbox_output(self, result.info, Constants.TIPS_TYPE_INFO)
PublicFunc.finish_operation(self, ButtonState)
def __slot_btn_move__(self):
if self.data is None:
return
@ -670,13 +647,15 @@ class MainWindow_label_check(QMainWindow):
PublicFunc.text_output(self.ui, f"{Constants.LABEL_CHECK_JUMP_X_INDEX}{str(int(x))}", Constants.TIPS_TYPE_INFO)
def reset_axes(self):
self.ax0.clear()
self.ax1.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
if self.ax0 is not None:
self.ax0.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
if self.ax1 is not None:
self.ax1.clear()
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
def on_xlim_change(self, event_ax):
try:
@ -814,6 +793,7 @@ class MainWindow_label_check(QMainWindow):
height=Config["FindPeaks"]["MinHeight"],
distance=Config["FindPeaks"]["MinInterval"])
peaks_idx = peaks_idx + int(rect_left)
peaks_idx = setdiff1d(peaks_idx, self.data.corrected_peak)
if len(peaks_idx) != 0:
PublicFunc.text_output(self.ui, f"{Constants.LABEL_CHECK_ADD_POINTS_SUCCESSFULLY}{peaks_idx}",
Constants.TIPS_TYPE_INFO)
@ -843,7 +823,14 @@ class MainWindow_label_check(QMainWindow):
self.data.corrected_peak.sort()
self.data.corrected_peak_y = [self.data.processed_data[x] for x in self.data.corrected_peak]
self.__update_tableWidget_and_info__()
DataFrame(self.data.corrected_peak).to_csv(Config["Path"]["Save"], index=False, header=False)
result = self.data.save()
if not result.status:
PublicFunc.text_output(self.ui, result.info, Constants.TIPS_TYPE_ERROR)
PublicFunc.msgbox_output(self, result.info, Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
else:
PublicFunc.text_output(self.ui, result.info, Constants.TIPS_TYPE_INFO)
# 移除矩形patch
if self.figToolbar.rect_patch_ax0 is not None and self.figToolbar.rect_patch_ax1 is not None:
self.figToolbar.rect_patch_ax0.remove()
@ -860,24 +847,24 @@ class MainWindow_label_check(QMainWindow):
if self.figToolbar.rect_patch_ax0 is None:
if self.is_left_button_pressed:
self.figToolbar.rect_patch_ax0 = patches.Rectangle((0, 0), 1, 1, fill=True,
alpha=ConfigParams.LABEL_CHECK_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
alpha=Params.LABEL_CHECK_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
elif self.is_right_button_pressed:
self.figToolbar.rect_patch_ax0 = patches.Rectangle((0, 0), 1, 1, fill=True,
alpha=ConfigParams.LABEL_CHECK_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_RED)
alpha=Params.LABEL_CHECK_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_RED)
self.ax0.add_patch(self.figToolbar.rect_patch_ax0)
# 如果矩形patch不存在则创建一个新的
if self.figToolbar.rect_patch_ax1 is None:
if self.is_left_button_pressed:
self.figToolbar.rect_patch_ax1 = patches.Rectangle((0, 0), 1, 1, fill=True,
alpha=ConfigParams.LABEL_CHECK_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
alpha=Params.LABEL_CHECK_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
elif self.is_right_button_pressed:
self.figToolbar.rect_patch_ax1 = patches.Rectangle((0, 0), 1, 1, fill=True,
alpha=ConfigParams.LABEL_CHECK_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_RED)
alpha=Params.LABEL_CHECK_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_RED)
self.ax1.add_patch(self.figToolbar.rect_patch_ax1)
# 更新矩形patch的位置和大小
@ -908,13 +895,13 @@ class Data:
def open_file(self):
if Config["Mode"] == "BCG":
signal = ConfigParams.BCG_FILTER
peak = ConfigParams.JPEAK_REVISE
save = ConfigParams.JPEAK_REVISE_CORRECTED
signal = Filename.BCG_FILTER
peak = Filename.JPEAK_REVISE
save = Filename.JPEAK_REVISE_CORRECTED
elif Config["Mode"] == "ECG":
signal = ConfigParams.ECG_FILTER
peak = ConfigParams.RPEAK_FINAL
save = ConfigParams.RPEAK_FINAL_CORRECTED
signal = Filename.ECG_FILTER
peak = Filename.RPEAK_FINAL
save = Filename.RPEAK_FINAL_CORRECTED
else:
raise ValueError("模式不存在")
if Path(Config["Path"]["Input_Signal"]).is_file():
@ -926,28 +913,38 @@ class Data:
if Path(Config["Path"]["Save"]).is_file():
Config["Path"]["Save"] = str(Path(Config["Path"]["Save"]).parent)
result = PublicFunc.examine_file(Config["Path"]["Input_Signal"], signal)
result = PublicFunc.examine_file(Config["Path"]["Input_Signal"], signal, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_Signal"] = result.data["path"]
Config["Path"]["Input_Peak"] = str(
Path(Config["Path"]["Input_Peak"]) / Path(peak + str(Config["InputConfig"]["Freq"]) + ConfigParams.ENDSWITH_TXT))
Config["InputConfig"]["Freq"] = result.data["freq"]
Config["Path"]["Input_Approximately_Align"] = str(
Path(Config["Path"]["Input_Approximately_Align"]) / Path(ConfigParams.APPROXIMATELY_ALIGN_INFO + ConfigParams.ENDSWITH_CSV))
Config["Path"]["Save"] = str(
Path(Config["Path"]["Save"]) / Path(save + str(Config["InputConfig"]["Freq"]) + ConfigParams.ENDSWITH_TXT))
else:
return result
if (not Path(Config["Path"]["Input_Signal"]).exists()) or (not Path(Config["Path"]["Input_Peak"]).exists()):
return Result().failure(info=Constants.INPUT_FAILURE + Constants.FAILURE_REASON["Path_Not_Exist"])
Config["Path"]["Input_Peak"] = str(
Path(Config["Path"]["Input_Peak"]) / Path(peak + str(Config["InputConfig"]["Freq"]) + Params.ENDSWITH_TXT))
Config["Path"]["Input_Approximately_Align"] = str(
Path(Config["Path"]["Input_Approximately_Align"]) / Path(
Filename.APPROXIMATELY_ALIGN_INFO + Params.ENDSWITH_CSV))
Config["Path"]["Save"] = str(
Path(Config["Path"]["Save"]) / Path(save + str(Config["InputConfig"]["Freq"]) + Params.ENDSWITH_TXT))
if not Path(Config["Path"]["Input_Peak"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + "\n" +
peak + "" +
Config["Path"]["Input_Peak"] +
Constants.FAILURE_REASON["Path_Not_Exist"])
if not Path(Config["Path"]["Input_Approximately_Align"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + "\n" +
Filename.APPROXIMATELY_ALIGN_INFO + "" +
Config["Path"]["Input_Approximately_Align"] +
Constants.FAILURE_REASON["Path_Not_Exist"])
try:
self.raw_data = read_csv(Config["Path"]["Input_Signal"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.original_peak = read_csv(Config["Path"]["Input_Peak"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
except Exception as e:
return Result().failure(info=Constants.INPUT_FAILURE +
@ -979,7 +976,7 @@ class Data:
return Result().success(info=Constants.ARCHIVE_NOT_EXIST)
else:
self.corrected_peak = read_csv(Config["Path"]["Save"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
return Result().success(info=Constants.ARCHIVE_EXIST)
@ -1010,15 +1007,12 @@ class Data:
return Result().success(info=Constants.PREPROCESS_FINISHED)
def save(self, chunk):
if (not Path(Config["Path"]["Save"]).parent.exists()) or (not Path(Config["Path"]["Save"]).parent.is_dir()):
Path(Config["Path"]["Save"]).parent.mkdir(parents=True, exist_ok=True)
def save(self):
if self.corrected_peak is None:
return Result().failure(info=Constants.SAVE_FAILURE + Constants.FAILURE_REASON["Data_Not_Exist"])
try:
chunk.to_csv(Config["Path"]["Save"], mode='a', index=False, header=False)
DataFrame(self.corrected_peak).to_csv(Config["Path"]["Save"], index=False, header=False)
except Exception as e:
return Result().failure(info=Constants.SAVE_FAILURE +
Constants.FAILURE_REASON["Save_Exception"] + "\n" + format_exc())
@ -1032,19 +1026,19 @@ class CustomNavigationToolbar(NavigationToolbar2QT):
super().__init__(canvas, parent)
# 初始化画框工具栏
self.action_Label_Multiple = QAction(Constants.LABEL_CHECK_ACTION_LABEL_MULTIPLE_NAME, self)
self.action_Label_Multiple.setFont(QFont(ConfigParams.FONT, 14))
self.action_Label_Multiple.setFont(QFont(Params.FONT, 14))
self.action_Label_Multiple.setCheckable(True)
self.action_Label_Multiple.setShortcut(QCoreApplication.translate(
"MainWindow",
ConfigParams.LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY))
Params.LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY))
self.insertAction(self._actions['pan'], self.action_Label_Multiple)
self._actions['pan'].setShortcut(QCoreApplication.translate(
"MainWindow",
ConfigParams.ACTION_PAN_SHORTCUT_KEY))
Params.ACTION_PAN_SHORTCUT_KEY))
self._actions['zoom'].setShortcut(QCoreApplication.translate(
"MainWindow",
ConfigParams.ACTION_ZOOM_SHORTCUT_KEY))
Params.ACTION_ZOOM_SHORTCUT_KEY))
# 用于存储事件连接ID
self.cid_mouse_press = None

View File

@ -16,9 +16,12 @@ from func.Module_label_check import MainWindow_label_check
from func.Module_precisely_align import MainWindow_precisely_align
from func.Module_cut_PSG import MainWindow_cut_PSG
from func.Module_artifact_label import MainWindow_artifact_label
from func.Module_bcg_quality_label import MainWindow_bcg_quality_label
from func.Module_resp_quality_label import MainWindow_resp_quality_label
from func.Module_SA_label import MainWindow_SA_label
from func.utils.Constants import Constants, ConfigParams
from func.utils.ConfigParams import Filename, Params
from func.utils.Constants import Constants
use("QtAgg")
@ -52,7 +55,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.__read_config__()
self.ui.plainTextEdit_root_path.setPlainText(Config["Path"]["Root"])
self.seek_sampID(Path(Config["Path"]["Root"]) / Path(ConfigParams.PUBLIC_PATH_ORGBCG_TEXT))
self.seek_sampID(Path(Config["Path"]["Root"]) / Path(Filename.PATH_ORGBCG_TEXT))
self.approximately_align = None
self.preprocess = None
@ -62,7 +65,8 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.precisely_align = None
self.cut_PSG = None
self.artifact_label = None
self.bcg_quality_label = None
self.resp_quality_label = None
self.SA_label = None
# 绑定槽函数
@ -77,22 +81,24 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.ui.pushButton_precisely_align.clicked.connect(self.__slot_btn_precisely_align__)
self.ui.pushButton_cut_PSG.clicked.connect(self.__slot_btn_cut_PSG__)
self.ui.pushButton_artifact_label.clicked.connect(self.__slot_btn_artifact_label__)
self.ui.pushButton_bcg_quality_label.clicked.connect(self.__slot_btn_bcg_quality_label__)
self.ui.pushButton_resp_quality_label.clicked.connect(self.__slot_btn_resp_quality_label__)
self.ui.pushButton_SA_label.clicked.connect(self.__slot_btn_SA_label__)
@staticmethod
def __read_config__():
if not Path(ConfigParams.PUBLIC_CONFIG_FILE_PATH).exists():
Path(ConfigParams.PUBLIC_CONFIG_FILE_PATH).parent.mkdir(parents=True, exist_ok=True)
with open(ConfigParams.PUBLIC_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.PUBLIC_CONFIG_NEW_CONTENT, f)
if not Path(Params.PUBLIC_CONFIG_FILE_PATH).exists():
Path(Params.PUBLIC_CONFIG_FILE_PATH).parent.mkdir(parents=True, exist_ok=True)
with open(Params.PUBLIC_CONFIG_FILE_PATH, "w") as f:
dump(Params.PUBLIC_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.PUBLIC_CONFIG_FILE_PATH, "r") as f:
with open(Params.PUBLIC_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
@staticmethod
def __write_config__():
with open(Path(ConfigParams.PUBLIC_CONFIG_FILE_PATH), "w") as f:
with open(Path(Params.PUBLIC_CONFIG_FILE_PATH), "w") as f:
dump(Config, f)
def __slot_btn_open__(self):
@ -100,7 +106,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
file_dialog.setFileMode(QFileDialog.Directory)
file_dialog.setOption(QFileDialog.ShowDirsOnly, True)
if file_dialog.exec_() == QFileDialog.Accepted:
self.seek_sampID(Path(file_dialog.selectedFiles()[0]) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT)
self.seek_sampID(Path(file_dialog.selectedFiles()[0]) / Filename.PATH_ORGBCG_TEXT)
self.ui.plainTextEdit_root_path.setPlainText(file_dialog.selectedFiles()[0])
# 修改配置
@ -120,6 +126,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.approximately_align.show(root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.approximately_align.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_preprocess__(self):
self.preprocess = MainWindow_preprocess()
@ -140,6 +147,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.preprocess.show(mode, root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.preprocess.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_detect_Jpeak__(self):
self.detect_Jpeak = MainWindow_detect_Jpeak()
@ -152,6 +160,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.detect_Jpeak.show(root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.detect_Jpeak.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_detect_Rpeak__(self):
self.detect_Rpeak = MainWindow_detect_Rpeak()
@ -164,6 +173,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.detect_Rpeak.show(root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.detect_Rpeak.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_label_check__(self):
self.label_check = MainWindow_label_check()
@ -186,7 +196,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.label_check.show(mode, root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.label_check.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_precisely_align__(self):
self.precisely_align = MainWindow_precisely_align()
@ -199,6 +209,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.precisely_align.show(root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.precisely_align.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_cut_PSG__(self):
self.cut_PSG = MainWindow_cut_PSG()
@ -209,6 +220,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
if not self.check_sampID():
return
self.cut_PSG.show(root_path, int(sampID))
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_artifact_label__(self):
self.artifact_label = MainWindow_artifact_label()
@ -221,6 +233,33 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.artifact_label.show(root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.artifact_label.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_bcg_quality_label__(self):
self.bcg_quality_label = MainWindow_bcg_quality_label()
root_path = self.ui.plainTextEdit_root_path.toPlainText()
sampID = self.ui.comboBox_sampID.currentText()
if not self.check_root_path():
return
if not self.check_sampID():
return
self.bcg_quality_label.show(root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.bcg_quality_label.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_resp_quality_label__(self):
self.resp_quality_label = MainWindow_resp_quality_label()
root_path = self.ui.plainTextEdit_root_path.toPlainText()
sampID = self.ui.comboBox_sampID.currentText()
if not self.check_root_path():
return
if not self.check_sampID():
return
self.resp_quality_label.show(root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.resp_quality_label.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_SA_label__(self):
self.SA_label = MainWindow_SA_label()
@ -233,6 +272,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.SA_label.show(root_path, int(sampID))
# 默认最大化显示而非固定分辨率
self.SA_label.showMaximized()
self.check_save_path_and_mkdir(root_path, sampID)
def seek_sampID(self, path):
if not Path(path).exists():
@ -242,7 +282,6 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
sub_folders = [item.name for item in Path(path).iterdir() if item.is_dir()]
self.ui.comboBox_sampID.addItems(sub_folders)
def check_root_path(self):
if self.ui.plainTextEdit_root_path.toPlainText() == Constants.STRING_IS_EMPTY:
PublicFunc.msgbox_output(self, Constants.MAINWINDOW_ROOT_PATH_NOT_EXIST, Constants.MSGBOX_TYPE_ERROR)
@ -254,3 +293,16 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
PublicFunc.msgbox_output(self, Constants.MAINWINDOW_SAMPID_EMPTY, Constants.MSGBOX_TYPE_ERROR)
return False
return True
def check_save_path_and_mkdir(self, root_path, sampID):
path_Label = Path(root_path) / Path(Filename.PATH_LABEL) / Path(str(sampID))
path_OrgBCG_Aligned = Path(root_path) / Path(Filename.PATH_ORGBCG_ALIGNED) / Path(str(sampID))
path_PSG_Aligned = Path(root_path) / Path(Filename.PATH_PSG_ALIGNED) / Path(str(sampID))
path_OrgBCG_Text = Path(root_path) / Path(Filename.PATH_ORGBCG_TEXT) / Path(str(sampID))
path_PSG_Text = Path(root_path) / Path(Filename.PATH_PSG_TEXT) / Path(str(sampID))
path_list = [path_Label, path_OrgBCG_Aligned, path_PSG_Aligned, path_OrgBCG_Text, path_PSG_Text]
for path in path_list:
if not path.exists():
path.mkdir(parents=True, exist_ok=True)

View File

@ -17,8 +17,9 @@ from resampy import resample
from scipy.signal import find_peaks
from yaml import dump, load, FullLoader
from func.utils.ConfigParams import Filename, Params
from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants, ConfigParams
from func.utils.Constants import Constants
from func.utils.Result import Result
from ui.MainWindow.MainWindow_precisely_align import Ui_MainWindow_precisely_align
@ -102,40 +103,40 @@ class SettingWindow(QMainWindow):
self.ui.pushButton_cancel.clicked.connect(self.close)
def __read_config__(self):
if not Path(ConfigParams.PRECISELY_ALIGN_CONFIG_FILE_PATH).exists():
with open(ConfigParams.PRECISELY_ALIGN_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.PRECISELY_ALIGN_CONFIG_NEW_CONTENT, f)
if not Path(Params.PRECISELY_ALIGN_CONFIG_FILE_PATH).exists():
with open(Params.PRECISELY_ALIGN_CONFIG_FILE_PATH, "w") as f:
dump(Params.PRECISELY_ALIGN_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.PRECISELY_ALIGN_CONFIG_FILE_PATH, "r") as f:
with open(Params.PRECISELY_ALIGN_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
self.config = file_config
Config.update({
"Path": {
"Input_OrgBCG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
"Input_OrgBCG": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Input_BCG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
"Input_BCG": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Input_Jpeak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
"Input_Jpeak": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Input_ECG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Input_ECG": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Input_Rpeak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Input_Rpeak": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Input_Approximately_Align": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Input_Approximately_Align": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID)))),
"Save_AlignInfo": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_LABEL /
Path(str(self.sampID)))),
"Save_OrgBCG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
"Save_AlignInfo": str((Path(self.root_path) / Filename.PATH_LABEL /
Path(str(self.sampID)))),
"Save_OrgBCG": str((Path(self.root_path) / Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)))),
"Save_BCG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
"Save_BCG": str((Path(self.root_path) / Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)))),
"Save_ECG": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
"Save_ECG": str((Path(self.root_path) / Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)))),
"Save_Jpeak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)))),
"Save_Rpeak": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
"Save_Jpeak": str((Path(self.root_path) / Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)))),
"Save_Rpeak": str((Path(self.root_path) / Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID))))
},
"Coordinate": {
@ -221,7 +222,7 @@ class SettingWindow(QMainWindow):
self.config["InputConfig"]["BCGFreq"] = self.ui.spinBox_input_freq_BCG.value()
self.config["InputConfig"]["ECGFreq"] = self.ui.spinBox_input_freq_ECG.value()
with open(ConfigParams.PRECISELY_ALIGN_CONFIG_FILE_PATH, "w") as f:
with open(Params.PRECISELY_ALIGN_CONFIG_FILE_PATH, "w") as f:
dump(self.config, f)
self.close()
@ -232,60 +233,60 @@ 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 /
Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.ORGBCG_RAW +
Path(Filename.ORGBCG_RAW +
str(self.ui.spinBox_input_freq_orgBcg.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_BCG.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.BCG_FILTER +
Path(Filename.BCG_FILTER +
str(self.ui.spinBox_input_freq_BCG.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_input_ECG.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.ECG_FILTER +
Path(Filename.ECG_FILTER +
str(self.ui.spinBox_input_freq_ECG.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save_orgBcg.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.ORGBCG_SYNC +
Path(Filename.ORGBCG_SYNC +
str(self.ui.spinBox_input_freq_orgBcg.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save_BCG.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.BCG_SYNC +
Path(Filename.BCG_SYNC +
str(self.ui.spinBox_input_freq_BCG.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save_ECG.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.ECG_SYNC +
Path(Filename.ECG_SYNC +
str(self.ui.spinBox_input_freq_ECG.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save_Jpeak.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_ALIGNED /
Filename.PATH_ORGBCG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.JPEAK_SYNC +
Path(Filename.JPEAK_SYNC +
str(self.ui.spinBox_input_freq_BCG.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save_Rpeak.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_ALIGNED /
Filename.PATH_PSG_ALIGNED /
Path(str(self.sampID)) /
Path(ConfigParams.RPEAK_SYNC +
Path(Filename.RPEAK_SYNC +
str(self.ui.spinBox_input_freq_ECG.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
class MainWindow_precisely_align(QMainWindow):
@ -463,10 +464,10 @@ class MainWindow_precisely_align(QMainWindow):
self.fig.subplots_adjust(top=0.95, bottom=0.05, right=0.98, left=0.05, hspace=0.15, wspace=0)
self.ax0 = self.fig.add_subplot(self.gs[0])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax1 = self.fig.add_subplot(self.gs[1], sharex=self.ax0, sharey=self.ax0)
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
Jpeak = self.data.Jpeak[:-2]
Rpeak = self.data.Rpeak[:-2]
@ -500,16 +501,16 @@ class MainWindow_precisely_align(QMainWindow):
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])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
self.ax1 = self.fig.add_subplot(self.gs[2])
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
self.ax2 = self.fig.add_subplot(self.gs[1])
self.ax2.grid(True)
self.ax2.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax2.xaxis.set_major_formatter(Params.FORMATTER)
self.ax3 = self.fig.add_subplot(self.gs[3])
self.ax3.grid(True)
self.ax3.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax3.xaxis.set_major_formatter(Params.FORMATTER)
self.ax0.set_title(
"front\ncorre_IIV: {}, corre_II: {}\nsame_sign_rate:{}, total_time_ratio: {}\nshift: {}, alignment offset: {} seconds\noffset_interval: {}, anchor_J: {}, anchor_R: {}".format(
@ -566,7 +567,7 @@ class MainWindow_precisely_align(QMainWindow):
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])
self.ax4.grid(True)
self.ax4.xaxis.set_major_formatter(ConfigParams.FORMATTER)
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)
@ -587,7 +588,7 @@ class MainWindow_precisely_align(QMainWindow):
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])
self.ax4.grid(True)
self.ax4.xaxis.set_major_formatter(ConfigParams.FORMATTER)
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)
@ -687,7 +688,7 @@ class MainWindow_precisely_align(QMainWindow):
PublicFunc.finish_operation(self, ButtonState)
def __slot_btn_calculate_correlation__(self, test1=None, shift_front=None, shift_back=None):
# TODO这里有个未知的BUG虽然不影响功能但会影响代码整洁性第一个形参赋值为None时之后使用变量时将会变成False不知道为什么
# TODO这里有个未知的BUG虽然不影响功能但会影响代码整洁性第一个形参赋值为None时之后使用变量时将会变成False不知道为什么
PublicFunc.__disableAllButton__(self, ButtonState)
sender = self.sender()
@ -839,7 +840,7 @@ class MainWindow_precisely_align(QMainWindow):
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
chunk_size = Params.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)
@ -861,7 +862,7 @@ class MainWindow_precisely_align(QMainWindow):
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
chunk_size = Params.PRECISELY_ALIGN_SAVE_CHUNK_SIZE
with open(Config["Path"]["Save_BCG"], 'w') as f:
for start in range(0, total_rows, chunk_size):
end = min(start + chunk_size, total_rows)
@ -883,7 +884,7 @@ class MainWindow_precisely_align(QMainWindow):
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
chunk_size = Params.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)
@ -905,7 +906,7 @@ class MainWindow_precisely_align(QMainWindow):
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
chunk_size = Params.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)
@ -927,7 +928,7 @@ class MainWindow_precisely_align(QMainWindow):
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
chunk_size = Params.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)
@ -1014,23 +1015,23 @@ class MainWindow_precisely_align(QMainWindow):
if self.ax0 is not None:
self.ax0.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
if self.ax1 is not None:
self.ax1.clear()
self.ax1.grid(True)
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax1.xaxis.set_major_formatter(Params.FORMATTER)
if self.ax2 is not None:
self.ax2.clear()
self.ax2.grid(True)
self.ax2.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax2.xaxis.set_major_formatter(Params.FORMATTER)
if self.ax3 is not None:
self.ax3.clear()
self.ax3.grid(True)
self.ax3.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax3.xaxis.set_major_formatter(Params.FORMATTER)
if self.ax4 is not None:
self.ax4.clear()
self.ax4.grid(True)
self.ax4.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax4.xaxis.set_major_formatter(Params.FORMATTER)
def redraw_calculate_coordination(self, plot_element=None):
if plot_element is not None and plot_element["mode"] == "select":
@ -1327,26 +1328,26 @@ class MainWindow_precisely_align(QMainWindow):
if self.figToolbar.ax0_BCG_rectangle_front is None and self.is_left_button_pressed:
self.figToolbar.ax0_BCG_rectangle_front = patches.Rectangle((0, 0), 1, 1,
fill=True,
alpha=ConfigParams.PRECISELY_ALIGN_LABEL_TRANSPARENCY,
alpha=Params.PRECISELY_ALIGN_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
self.ax0.add_patch(self.figToolbar.ax0_BCG_rectangle_front)
if self.figToolbar.ax0_BCG_rectangle_back is None and self.is_left_button_pressed:
self.figToolbar.ax0_BCG_rectangle_back = patches.Rectangle((0, 0), 1, 1,
fill=True,
alpha=ConfigParams.PRECISELY_ALIGN_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
fill=True,
alpha=Params.PRECISELY_ALIGN_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
self.ax0.add_patch(self.figToolbar.ax0_BCG_rectangle_back)
if self.figToolbar.ax1_ECG_rectangle_front is None and self.is_left_button_pressed:
self.figToolbar.ax1_ECG_rectangle_front = patches.Rectangle((0, 0), 1, 1,
fill=True,
alpha=ConfigParams.PRECISELY_ALIGN_LABEL_TRANSPARENCY,
alpha=Params.PRECISELY_ALIGN_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
self.ax1.add_patch(self.figToolbar.ax1_ECG_rectangle_front)
if self.figToolbar.ax1_ECG_rectangle_back is None and self.is_left_button_pressed:
self.figToolbar.ax1_ECG_rectangle_back = patches.Rectangle((0, 0), 1, 1,
fill=True,
alpha=ConfigParams.PRECISELY_ALIGN_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
fill=True,
alpha=Params.PRECISELY_ALIGN_LABEL_TRANSPARENCY,
color=Constants.PLOT_COLOR_PINK)
self.ax1.add_patch(self.figToolbar.ax1_ECG_rectangle_back)
if self.ui.radioButton_BCG_front.isChecked():
@ -1454,72 +1455,83 @@ class Data:
if Path(Config["Path"]["Input_Approximately_Align"]).is_file():
Config["Path"]["Input_Approximately_Align"] = str(Path(Config["Path"]["Input_Approximately_Align"]).parent)
result = PublicFunc.examine_file(Config["Path"]["Input_OrgBCG"], ConfigParams.ORGBCG_RAW)
result = PublicFunc.examine_file(Config["Path"]["Input_OrgBCG"], Filename.ORGBCG_RAW, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_OrgBCG"] = result.data["path"]
Config["InputConfig"]["orgBcgFreq"] = result.data["freq"]
Config["Path"]["Input_Approximately_Align"] = str(
Path(Config["Path"]["Input_Approximately_Align"]) / Path(
ConfigParams.APPROXIMATELY_ALIGN_INFO + ConfigParams.ENDSWITH_CSV))
Config["Path"]["Save_AlignInfo"] = str(
Path(Config["Path"]["Save_AlignInfo"]) / Path(
ConfigParams.PRECISELY_ALIGN_INFO + ConfigParams.ENDSWITH_TXT))
Config["Path"]["Save_OrgBCG"] = str(
Path(Config["Path"]["Save_OrgBCG"]) / Path(
ConfigParams.ORGBCG_SYNC + str(Config["InputConfig"]["orgBcgFreq"]) + ConfigParams.ENDSWITH_TXT))
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_BCG"], ConfigParams.BCG_FILTER)
Config["Path"]["Input_Approximately_Align"] = str(
Path(Config["Path"]["Input_Approximately_Align"]) / Path(
Filename.APPROXIMATELY_ALIGN_INFO + Params.ENDSWITH_CSV))
Config["Path"]["Save_AlignInfo"] = str(
Path(Config["Path"]["Save_AlignInfo"]) / Path(
Filename.PRECISELY_ALIGN_INFO + Params.ENDSWITH_TXT))
Config["Path"]["Save_OrgBCG"] = str(
Path(Config["Path"]["Save_OrgBCG"]) / Path(
Filename.ORGBCG_SYNC + str(Config["InputConfig"]["orgBcgFreq"]) + Params.ENDSWITH_TXT))
result = PublicFunc.examine_file(Config["Path"]["Input_BCG"], Filename.BCG_FILTER, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_BCG"] = result.data["path"]
Config["InputConfig"]["BCGFreq"] = result.data["freq"]
Config["Path"]["Input_Jpeak"] = str(
Path(Config["Path"]["Input_Jpeak"]) / Path(ConfigParams.JPEAK_REVISE_CORRECTED + str(Config["InputConfig"]["BCGFreq"]) + ConfigParams.ENDSWITH_TXT))
Config["Path"]["Save_BCG"] = str(
Path(Config["Path"]["Save_BCG"]) / Path(
ConfigParams.BCG_SYNC + str(Config["InputConfig"]["BCGFreq"]) + ConfigParams.ENDSWITH_TXT))
Config["Path"]["Save_Jpeak"] = str(
Path(Config["Path"]["Save_Jpeak"]) / Path(
ConfigParams.JPEAK_SYNC + str(Config["InputConfig"]["BCGFreq"]) + ConfigParams.ENDSWITH_TXT))
else:
return result
result = PublicFunc.examine_file(Config["Path"]["Input_ECG"], ConfigParams.ECG_FILTER)
Config["Path"]["Input_Jpeak"] = str(
Path(Config["Path"]["Input_Jpeak"]) / Path(Filename.JPEAK_REVISE_CORRECTED + str(
Config["InputConfig"]["BCGFreq"]) + Params.ENDSWITH_TXT))
Config["Path"]["Save_BCG"] = str(
Path(Config["Path"]["Save_BCG"]) / Path(
Filename.BCG_SYNC + str(Config["InputConfig"]["BCGFreq"]) + Params.ENDSWITH_TXT))
Config["Path"]["Save_Jpeak"] = str(
Path(Config["Path"]["Save_Jpeak"]) / Path(
Filename.JPEAK_SYNC + str(Config["InputConfig"]["BCGFreq"]) + Params.ENDSWITH_TXT))
result = PublicFunc.examine_file(Config["Path"]["Input_ECG"], Filename.ECG_FILTER, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input_ECG"] = result.data["path"]
Config["InputConfig"]["ECGFreq"] = result.data["freq"]
Config["Path"]["Input_Rpeak"] = str(
Path(Config["Path"]["Input_Rpeak"]) / Path(ConfigParams.RPEAK_FINAL_CORRECTED + str(Config["InputConfig"]["ECGFreq"]) + ConfigParams.ENDSWITH_TXT))
Config["Path"]["Save_ECG"] = str(
Path(Config["Path"]["Save_ECG"]) / Path(
ConfigParams.ECG_SYNC + str(Config["InputConfig"]["ECGFreq"]) + ConfigParams.ENDSWITH_TXT))
Config["Path"]["Save_Rpeak"] = str(
Path(Config["Path"]["Save_Rpeak"]) / Path(
ConfigParams.RPEAK_SYNC + str(Config["InputConfig"]["ECGFreq"]) + ConfigParams.ENDSWITH_TXT))
else:
return result
Config["Path"]["Input_Rpeak"] = str(
Path(Config["Path"]["Input_Rpeak"]) / Path(
Filename.RPEAK_FINAL_CORRECTED + str(Config["InputConfig"]["ECGFreq"]) + Params.ENDSWITH_TXT))
Config["Path"]["Save_ECG"] = str(
Path(Config["Path"]["Save_ECG"]) / Path(
Filename.ECG_SYNC + str(Config["InputConfig"]["ECGFreq"]) + Params.ENDSWITH_TXT))
Config["Path"]["Save_Rpeak"] = str(
Path(Config["Path"]["Save_Rpeak"]) / Path(
Filename.RPEAK_SYNC + str(Config["InputConfig"]["ECGFreq"]) + Params.ENDSWITH_TXT))
if ((not Path(Config["Path"]["Input_OrgBCG"]).exists())
or (not Path(Config["Path"]["Input_BCG"]).exists())
or (not Path(Config["Path"]["Input_Jpeak"]).exists())
or (not Path(Config["Path"]["Input_ECG"]).exists())
or (not Path(Config["Path"]["Input_Rpeak"]).exists())):
return Result().failure(info=Constants.INPUT_FAILURE + Constants.FAILURE_REASON["Data_Not_Exist"])
if not Path(Config["Path"]["Input_Jpeak"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + "\n" +
Filename.JPEAK_REVISE_CORRECTED + "" +
Config["Path"]["Input_Jpeak"] +
Constants.FAILURE_REASON["Path_Not_Exist"])
if not Path(Config["Path"]["Input_Rpeak"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + "\n" +
Filename.RPEAK_FINAL_CORRECTED + "" +
Config["Path"]["Input_Rpeak"] +
Constants.FAILURE_REASON["Path_Not_Exist"])
if not Path(Config["Path"]["Input_Approximately_Align"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + "\n" +
Filename.APPROXIMATELY_ALIGN_INFO + "" +
Config["Path"]["Input_Approximately_Align"] +
Constants.FAILURE_REASON["Path_Not_Exist"])
try:
self.raw_orgBcg = read_csv(Config["Path"]["Input_OrgBCG"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.raw_BCG = read_csv(Config["Path"]["Input_BCG"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.Jpeak = read_csv(Config["Path"]["Input_Jpeak"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.raw_ECG = read_csv(Config["Path"]["Input_ECG"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.Rpeak = read_csv(Config["Path"]["Input_Rpeak"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
self.argmax_BCG = np_argmax(self.raw_BCG)
self.argmax_ECG = np_argmax(self.raw_ECG)
@ -1536,6 +1548,7 @@ class Data:
self.BCG_early = False
elif self.approximately_align_pos < 0:
self.BCG_early = True
self.approximately_align_pos = - self.approximately_align_pos
else:
self.approximately_align_pos = 0
self.BCG_early = None
@ -1858,9 +1871,6 @@ class Data:
return Result().success(info=info)
def save_alignInfo(self):
if (not Path(Config["Path"]["Save_AlignInfo"]).parent.exists()) or (not Path(Config["Path"]["Save_AlignInfo"]).parent.is_dir()):
Path(Config["Path"]["Save_AlignInfo"]).parent.mkdir(parents=True, exist_ok=True)
try:
save_data = {
"front": {
@ -1992,19 +2002,19 @@ class CustomNavigationToolbar(NavigationToolbar2QT):
super().__init__(canvas, parent)
# 初始化画框工具栏
self.action_Get_Range = QAction(Constants.PRECISELY_ALIGN_ACTION_GET_RANGE_NAME, self)
self.action_Get_Range.setFont(QFont(ConfigParams.FONT, 14))
self.action_Get_Range.setFont(QFont(Params.FONT, 14))
self.action_Get_Range.setCheckable(True)
self.action_Get_Range.setShortcut(QCoreApplication.translate(
"MainWindow",
ConfigParams.PRECISELY_ALIGN_ACTION_GET_RANGE_SHORTCUT_KEY))
Params.PRECISELY_ALIGN_ACTION_GET_RANGE_SHORTCUT_KEY))
self.insertAction(self._actions['pan'], self.action_Get_Range)
self._actions['pan'].setShortcut(QCoreApplication.translate(
"MainWindow",
ConfigParams.ACTION_PAN_SHORTCUT_KEY))
Params.ACTION_PAN_SHORTCUT_KEY))
self._actions['zoom'].setShortcut(QCoreApplication.translate(
"MainWindow",
ConfigParams.ACTION_ZOOM_SHORTCUT_KEY))
Params.ACTION_ZOOM_SHORTCUT_KEY))
# 用于存储事件连接ID
self.cid_mouse_press = None

View File

@ -12,8 +12,9 @@ from pandas import read_csv, DataFrame
from scipy.signal import resample
from yaml import dump, load, FullLoader
from func.utils.ConfigParams import Filename, Params
from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants, ConfigParams
from func.utils.Constants import Constants
from func.Filters.Preprocessing import Butterworth_for_BCG_PreProcess, Butterworth_for_ECG_PreProcess
from func.utils.Result import Result
@ -62,11 +63,11 @@ class SettingWindow(QMainWindow):
self.ui.pushButton_cancel.clicked.connect(self.close)
def __read_config__(self):
if not Path(ConfigParams.PREPROCESS_CONFIG_FILE_PATH).exists():
with open(ConfigParams.PREPROCESS_CONFIG_FILE_PATH, "w") as f:
dump(ConfigParams.PREPROCESS_CONFIG_NEW_CONTENT, f)
if not Path(Params.PREPROCESS_CONFIG_FILE_PATH).exists():
with open(Params.PREPROCESS_CONFIG_FILE_PATH, "w") as f:
dump(Params.PREPROCESS_CONFIG_NEW_CONTENT, f)
with open(ConfigParams.PREPROCESS_CONFIG_FILE_PATH, "r") as f:
with open(Params.PREPROCESS_CONFIG_FILE_PATH, "r") as f:
file_config = load(f.read(), Loader=FullLoader)
Config.update(file_config)
self.config = file_config
@ -74,9 +75,9 @@ class SettingWindow(QMainWindow):
if self.mode == "BCG":
Config.update({
"Path": {
"Input": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
"Input": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)))),
"Save": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
"Save": str((Path(self.root_path) / Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID))))
},
"Mode": self.mode
@ -84,9 +85,9 @@ class SettingWindow(QMainWindow):
elif self.mode == "ECG":
Config.update({
"Path": {
"Input": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Input": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID)))),
"Save": str((Path(self.root_path) / ConfigParams.PUBLIC_PATH_PSG_TEXT /
"Save": str((Path(self.root_path) / Filename.PATH_PSG_TEXT /
Path(str(self.sampID))))
},
"Mode": self.mode
@ -111,7 +112,7 @@ class SettingWindow(QMainWindow):
self.config["InputConfig"]["Freq"] = self.ui.spinBox_input_freq.value()
self.config["OutputConfig"]["Freq"] = self.ui.spinBox_output_freq.value()
with open(ConfigParams.PREPROCESS_CONFIG_FILE_PATH, "w") as f:
with open(Params.PREPROCESS_CONFIG_FILE_PATH, "w") as f:
dump(self.config, f)
self.close()
@ -123,33 +124,33 @@ class SettingWindow(QMainWindow):
if self.mode == "BCG":
self.ui.plainTextEdit_file_path_input.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.ORGBCG_RAW +
Path(Filename.ORGBCG_RAW +
str(self.ui.spinBox_input_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_ORGBCG_TEXT /
Filename.PATH_ORGBCG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.BCG_FILTER +
Path(Filename.BCG_FILTER +
str(self.ui.spinBox_output_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
elif self.mode == "ECG":
self.ui.plainTextEdit_file_path_input.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.ECG_RAW +
Path(Filename.ECG_RAW +
str(self.ui.spinBox_input_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
self.ui.plainTextEdit_file_path_save.setPlainText(
str((Path(self.root_path) /
ConfigParams.PUBLIC_PATH_PSG_TEXT /
Filename.PATH_PSG_TEXT /
Path(str(self.sampID)) /
Path(ConfigParams.ECG_FILTER +
Path(Filename.ECG_FILTER +
str(self.ui.spinBox_output_freq.value()) +
ConfigParams.ENDSWITH_TXT))))
Params.ENDSWITH_TXT))))
else:
raise ValueError("模式不存在")
@ -205,7 +206,7 @@ class MainWindow_preprocess(QMainWindow):
self.fig.subplots_adjust(top=0.98, bottom=0.05, right=0.98, left=0.1, hspace=0, wspace=0)
self.ax0 = self.fig.add_subplot(self.gs[0])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
PublicFunc.__resetAllButton__(self, ButtonState)
@ -239,7 +240,8 @@ class MainWindow_preprocess(QMainWindow):
QApplication.processEvents()
# 清空画框
self.ax0.clear()
if self.ax0 is not None:
self.ax0.clear()
# 释放资源
del self.data
@ -363,7 +365,7 @@ class MainWindow_preprocess(QMainWindow):
PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0)
total_rows = len(DataFrame(self.data.processed_data.reshape(-1)))
chunk_size = ConfigParams.PREPROCESS_SAVE_CHUNK_SIZE
chunk_size = Params.PREPROCESS_SAVE_CHUNK_SIZE
with open(Config["Path"]["Save"], 'w') as f:
for start in range(0, total_rows, chunk_size):
end = min(start + chunk_size, total_rows)
@ -385,9 +387,10 @@ class MainWindow_preprocess(QMainWindow):
PublicFunc.finish_operation(self, ButtonState)
def reset_axes(self):
self.ax0.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
if self.ax0 is not None:
self.ax0.clear()
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
class Data:
@ -398,31 +401,28 @@ class Data:
def open_file(self):
if Config["Mode"] == "BCG":
signal = ConfigParams.ORGBCG_RAW
save = ConfigParams.BCG_FILTER
signal = Filename.ORGBCG_RAW
save = Filename.BCG_FILTER
elif Config["Mode"] == "ECG":
signal = ConfigParams.ECG_RAW
save = ConfigParams.ECG_FILTER
signal = Filename.ECG_RAW
save = Filename.ECG_FILTER
else:
raise ValueError("模式不存在")
if Path(Config["Path"]["Input"]).is_file():
Config["Path"]["Input"] = str(Path(Config["Path"]["Input"]).parent)
if not Path(Config["Path"]["Input"]).exists():
return Result().failure(info=Constants.INPUT_FAILURE + Constants.FAILURE_REASON["Path_Not_Exist"])
result = PublicFunc.examine_file(Config["Path"]["Input"], signal)
result = PublicFunc.examine_file(Config["Path"]["Input"], signal, Params.ENDSWITH_TXT)
if result.status:
Config["Path"]["Input"] = result.data["path"]
Config["InputConfig"]["Freq"] = result.data["freq"]
Config["Path"]["Save"] = str(
Path(Config["Path"]["Save"]) / Path(save + str(Config["OutputConfig"]["Freq"]) + ConfigParams.ENDSWITH_TXT))
Path(Config["Path"]["Save"]) / Path(save + str(Config["OutputConfig"]["Freq"]) + Params.ENDSWITH_TXT))
else:
return result
try:
self.raw_data = read_csv(Config["Path"]["Input"],
encoding=ConfigParams.UTF8_ENCODING,
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
except Exception as e:
return Result().failure(info=Constants.INPUT_FAILURE +
@ -474,9 +474,6 @@ class Data:
return Result().success(info=Constants.PREPROCESS_FINISHED)
def save(self, chunk):
if (not Path(Config["Path"]["Save"]).parent.exists()) or (not Path(Config["Path"]["Save"]).parent.is_dir()):
Path(Config["Path"]["Save"]).parent.mkdir(parents=True, exist_ok=True)
if self.processed_data is None:
return Result().failure(info=Constants.SAVE_FAILURE + Constants.FAILURE_REASON["Data_Not_Exist"])

File diff suppressed because it is too large Load Diff

View File

@ -2,23 +2,82 @@ from PySide6.QtGui import QIntValidator, QDoubleValidator
from matplotlib.ticker import FuncFormatter
class ConfigParams:
class Filename:
# 文件命名
PATH_ORGBCG_TEXT: str = "OrgBCG_Text"
PATH_PSG_TEXT: str = "PSG_Text"
PATH_ORGBCG_ALIGNED: str = "OrgBCG_Aligned"
PATH_PSG_ALIGNED: str = "PSG_Aligned"
PATH_ORGBCG_ORIGIN: str = "OrgBCG_Origin"
PATH_PSG_ORIGIN: str = "PSG_Origin"
PATH_LABEL: str = "Label"
PATH_REVEIVE_ORIGIN: str = "Receive_Origin"
PATH_REPORT: str = "Report"
PATH_SAMPID: str = "<sampID>"
SUFFIX_FREQ: str = "采样率"
# Folder: OrgBCG_Text
ORGBCG_RAW: str = "OrgBCG_Raw_"
BCG_FILTER: str = "BCG_Filter_"
JPEAK_REVISE: str = "Jpeak_revise_"
JPEAK_REVISE_CORRECTED: str = "Jpeak_revise_corrected_"
# Folder: PSG_Text
ECG_RAW: str = "ECG II_Raw_"
THO_RAW: str = "Effort Tho_Raw_"
ABD_RAW: str = "Effort Abd_Raw_"
FLOWT_RAW: str = "Flow T_Raw_"
FLOWP_RAW: str = "Flow P_Raw_"
SNORE_RAW: str = "Snore_Raw_"
SPO2_RAW: str = "SpO2_Raw_"
FIVE_CLASS_RAW: str = "5_class_Raw_"
STARTTIME_RAW: str = "StartTime_Raw"
SA_LABEL_RAW: str = "SA Label_Raw"
ECG_FILTER: str = "ECG_Filter_"
RPEAK_FINAL: str = "Rpeak_final_"
RPEAK_FINAL_CORRECTED: str = "Rpeak_final_corrected_"
# Folder: OrgBCG_Aligned
ORGBCG_SYNC: str = "OrgBCG_Sync_"
BCG_SYNC: str = "BCG_Sync_"
# Folder: PSG_Aligned
ECG_SYNC: str = "ECG_Sync_"
THO_SYNC: str = "Effort Tho_Sync_"
ABD_SYNC: str = "Effort Abd_Sync_"
FLOWT_SYNC: str = "Flow T_Sync_"
FLOWP_SYNC: str = "Flow P_Sync_"
SNORE_SYNC: str = "Snore_Sync_"
SPO2_SYNC: str = "SpO2_Sync_"
FIVE_CLASS_SYNC: str = "5_class_Sync_"
SA_LABEL_SYNC: str = "SA Label_Sync"
JPEAK_SYNC: str = "Jpeak_Sync_"
RPEAK_SYNC: str = "Rpeak_Sync_"
# Folder: Label
APPROXIMATELY_ALIGN_INFO: str = "Approximately_Align_Info"
PRECISELY_ALIGN_INFO: str = "Precisely_Align_Info"
ARTIFACT_A: str = "Artifact_a_"
ARTIFACT_B: str = "Artifact_b_"
ARTIFACT_C: str = "Artifact_c_"
SA_LABEL_CORRECTED: str = "SA Label_corrected"
SA_LABEL_ADD: str = "SA Label_add"
RESP_QUALITY_LABEL: str = "Resp_quality_label"
THO_PEAK: str = "Tho_peak_"
SQ_LABEL_10S: str = "SQ_label_10s"
SQ_LABEL_30S: str = "SQ_label_30s"
class Params:
# 公共
PUBLIC_CONFIG_FILE_PATH: str = "./config/Config_public.yaml"
PUBLIC_PATH_ORGBCG_TEXT: str = "OrgBCG_Text"
PUBLIC_PATH_PSG_TEXT: str = "PSG_Text"
PUBLIC_PATH_ORGBCG_ALIGNED: str = "OrgBCG_Aligned"
PUBLIC_PATH_PSG_ALIGNED: str = "PSG_Aligned"
PUBLIC_PATH_LABEL: str = "Label"
PUBLIC_CONFIG_NEW_CONTENT = {
"Path": {
"Root": ""
}
}
UTF8_ENCODING: str = "utf-8"
# 目前用到这个编码的地方:
# <BCG的质量评估打标>里的保存和读取csv文件的地方注意的是读取原始数据时依然使用UTF-8
GBK_ENCODING: str = "gbk"
ENDSWITH_TXT: str = ".txt"
ENDSWITH_CSV: str = ".csv"
@ -30,45 +89,6 @@ class ConfigParams:
VALIDATOR_INTEGER = QIntValidator(-2**31, 2**31 - 1)
VALIDATOR_DOUBLE = QDoubleValidator(-1e100, 1e100, 10)
# 文件命名
ORGBCG_RAW: str = "OrgBCG_Raw_"
ECG_RAW: str = "ECG II_Raw_"
THO_RAW: str = "Effort Tho_Raw_"
ABD_RAW: str = "Effort Abd_Raw_"
FLOWT_RAW: str = "Flow T_Raw_"
FLOWP_RAW: str = "Flow P_Raw_"
SNORE_RAW: str = "Snore_Raw_"
SPO2_RAW: str = "SpO2_Raw_"
FIVE_CLASS_RAW: str = "5_class_Raw_"
STARTTIME_RAW: str = "StartTime_Raw_"
SA_LABEL_RAW: str = "SA Label_Raw_"
BCG_FILTER: str = "BCG_Filter_"
ECG_FILTER: str = "ECG_Filter_"
JPEAK_REVISE: str = "Jpeak_revise_"
RPEAK_FINAL: str = "Rpeak_final_"
JPEAK_REVISE_CORRECTED: str = "Jpeak_revise_corrected_"
RPEAK_FINAL_CORRECTED: str = "Rpeak_final_corrected_"
APPROXIMATELY_ALIGN_INFO: str = "Approximately_Align_Info"
PRECISELY_ALIGN_INFO: str = "Precisely_Align_Info"
ARTIFACT_A: str = "Artifact_a"
ARTIFACT_B: str = "Artifact_b"
ARTIFACT_C: str = "Artifact_c"
BCG_SYNC: str = "BCG_Sync_"
ECG_SYNC: str = "ECG_Sync_"
JPEAK_SYNC: str = "Jpeak_Sync_"
RPEAK_SYNC: str = "Rpeak_Sync_"
ORGBCG_SYNC: str = "OrgBCG_Sync_"
THO_SYNC: str = "Effort Tho_Sync_"
ABD_SYNC: str = "Effort Abd_Sync_"
FLOWT_SYNC: str = "Flow T_Sync_"
FLOWP_SYNC: str = "Flow P_Sync_"
SNORE_SYNC: str = "Snore_Sync_"
SPO2_SYNC: str = "SpO2_Sync_"
FIVE_CLASS_SYNC: str = "5_class_Sync_"
SA_LABEL_SYNC: str = "SA Label_Sync"
SA_LABEL_CORRECTED: str = "SA Label_corrected"
SA_LABEL_ADD: str = "SA Label_add"
# 数据粗同步
APPROXIMATELY_ALIGN_CONFIG_FILE_PATH: str = "./config/Config_approximately_align.yaml"
APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT: dict = {
@ -195,29 +215,29 @@ class ConfigParams:
CUT_PSG_CONFIG_NEW_CONTENT: dict = {
"ECGFreq": 1000,
"ChannelInput": {
"Effort Tho": THO_RAW,
"Effort Abd": ABD_RAW,
"Flow T": FLOWT_RAW,
"Flow P": FLOWP_RAW,
"Snore": SNORE_RAW,
"SpO2": SPO2_RAW,
"5_class": FIVE_CLASS_RAW
"Effort Tho": Filename.THO_RAW,
"Effort Abd": Filename.ABD_RAW,
"Flow T": Filename.FLOWT_RAW,
"Flow P": Filename.FLOWP_RAW,
"Snore": Filename.SNORE_RAW,
"SpO2": Filename.SPO2_RAW,
"5_class": Filename.FIVE_CLASS_RAW
},
"LabelInput": {
"SA Label": SA_LABEL_RAW
"SA Label": Filename.SA_LABEL_RAW
},
"StartTime": STARTTIME_RAW,
"StartTime": Filename.STARTTIME_RAW,
"ChannelSave": {
"Effort Tho": THO_SYNC,
"Effort Abd": ABD_SYNC,
"Flow T": FLOWT_SYNC,
"Flow P": FLOWP_SYNC,
"Snore": SNORE_SYNC,
"SpO2": SPO2_SYNC,
"5_class": FIVE_CLASS_SYNC
"Effort Tho": Filename.THO_SYNC,
"Effort Abd": Filename.ABD_SYNC,
"Flow T": Filename.FLOWT_SYNC,
"Flow P": Filename.FLOWP_SYNC,
"Snore": Filename.SNORE_SYNC,
"SpO2": Filename.SPO2_SYNC,
"5_class": Filename.FIVE_CLASS_SYNC
},
"LabelSave": {
"SA Label": SA_LABEL_SYNC
"SA Label": Filename.SA_LABEL_SYNC
},
"EndWith": {
"Effort Tho": ENDSWITH_TXT,
@ -251,6 +271,44 @@ class ConfigParams:
ARTIFACT_LABEL_LABEL_TRANSPARENCY: float = 0.3
ARTIFACT_LABEL_ACTION_LABEL_ARTIFACT_SHORTCUT_KEY: str = "Z"
# BCG的质量标注
BCG_QUALITY_LABEL_CONFIG_FILE_PATH: str = "./config/Config_bcg_quality_label.yaml"
BCG_QUALITY_LABEL_CONFIG_NEW_CONTENT: dict = {
"InputConfig": {
"BCGFreq": 1000,
"UseFreq": 1000
}
}
BCG_QUALITY_LABEL_BTN_PREV_SHORTCUT_KEY: str = "A"
BCG_QUALITY_LABEL_BTN_NEXT_SHORTCUT_KEY: str = "D"
# 呼吸可用性及间期标注
RESP_QUALITY_LABEL_CONFIG_FILE_PATH: str = "./config/Config_resp_quality_label.yaml"
RESP_QUALITY_LABEL_CONFIG_NEW_CONTENT: dict = {
"InputConfig": {
"OrgBCGFreq": 1000,
"ThoFreq": 100,
"OrgBCGUseFreq": 1000,
"ThoUseFreq": 100
},
"Threshold": {
"Low": 0.65,
"High": 0.8
},
"FindPeaks" : {
"MinInterval": 300,
"MinHeight": 0.1
},
"Filter": {
"BandPassLow": 0.1,
"BandPassHigh": 1
}
}
RESP_QUALITY_LABEL_PREPROCESS_FC: int = 1
RESP_QUALITY_LABEL_PARTS_TIME_SEC: int = 30
RESP_QUALITY_LABEL_LABEL_TRANSPARENCY: float = 0.2
RESP_QUALITY_LABEL_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY: str = "Z"
# 睡眠呼吸暂停事件标注
SA_LABEL_CONFIG_FILE_PATH: str = "./config/Config_SA_label.yaml"
SA_LABEL_CONFIG_NEW_CONTENT: dict = {
@ -281,62 +339,10 @@ class ConfigParams:
SA_LABEL_RADIOBUTTON_2_CLASS_SHORTCUT_KEY: str = "I"
SA_LABEL_RADIOBUTTON_3_CLASS_SHORTCUT_KEY: str = "O"
# 质量打标
BCG_QUALITY_LABEL_INPUT_BCG_FILENAME: str = "BCG_sync_"
BCG_QUALITY_LABEL_INPUT_ARTIFACT_FILENAME: str = "Artifact_a"
BCG_QUALITY_LABEL_SAVE_FILENAME: str = "SQ_label_"
BCG_QUALITY_LABEL_INPUT_DEFAULT_FS: int = 1000
BCG_QUALITY_LABEL_SAVE_MODE_10S: str = "10s"
BCG_QUALITY_LABEL_SAVE_MODE_30S: str = "30s"
BCG_QUALITY_LABEL_MODE_10S_LENGTH = 10 * BCG_QUALITY_LABEL_INPUT_DEFAULT_FS
BCG_QUALITY_LABEL_MODE_30S_LENGTH = 30 * BCG_QUALITY_LABEL_INPUT_DEFAULT_FS
# 呼吸可用性及间期标注
RESP_QUALITY_LABEL_INPUT_XINXIAO_FILENAME: str = "orgBcg_sync_"
RESP_QUALITY_LABEL_INPUT_THO_FILENAME: str = "Effort_Tho_sync_"
RESP_QUALITY_LABEL_INPUT_ARTIFACT_FILENAME: str = "Artifact_a"
RESP_QUALITY_LABEL_SAVE_RESP_QUALITY_LABNEL_FILENAME: str = "Resp_quality_label"
RESP_QUALITY_LABEL_SAVE_THO_PEAK_FILENAME: str = "Tho_peak"
RESP_QUALITY_LABEL_INPUT_XINXIAO_DEFAULT_FS: int = 1000
RESP_QUALITY_LABEL_INPUT_THO_DEFAULT_FS: int = 200
RESP_QUALITY_LABEL_PARTS_TIME_SEC: int = 30
RESP_QUALITY_LABEL_PREPROCESS_FC: int = 1
RESP_QUALITY_LABEL_THRESHOLD1_DEFAULT: float = 0.65
RESP_QUALITY_LABEL_THRESHOLD2_DEFAULT: float = 0.8
RESP_QUALITY_LABEL_FINDPEAKS_MIN_INTERVAL_DEFAULT: int = 300
RESP_QUALITY_LABEL_FINDPEAKS_MIN_HEIGHT_DEFAULT: float = 0.1
RESP_QUALITY_LABEL_CUSTOM_LOW_DEFAULT: float = 0.1
RESP_QUALITY_LABEL_CUSTOM_HIGH_DEFAULT: float = 1
RESP_QUALITY_LABEL_LABEL_TRANSPARENCY: float = 0.2
RESP_QUALITY_LABEL_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY: str = "Z"
# 睡眠呼吸暂停事件打标
# 禁止实例化
def __new__(cls):
raise TypeError("Constants class cannot be instantiated")
# 禁止修改常量
@classmethod
def __setattr__(cls, key, value):

View File

@ -1,4 +1,4 @@
from func.utils.ConfigParams import ConfigParams
from func.utils.ConfigParams import Params
class Constants:
@ -94,16 +94,18 @@ class Constants:
"Path_Not_Exist": "(路径不存在)",
"File_Not_Exist": "(数据文件不存在)",
"File_More_Than_One": "(数据文件超过一个)",
"Data_Frequency_Not_In_Filename": "(无法找到文件名中的数据频率信息)",
"Suffix_Not_Correct": "(文件扩展名不正确)",
"Frequency_Not_In_Filename": "(数据频率不在文件名中)",
"Data_Not_Exist": "(数据不存在)",
"Model_File_Not_Exist": "(模型文件不存在)",
"Model_Path_Not_Exist": "(模型文件不存在)",
"Cut_Data_Length_not_Correct": "(切割数据时长度不正确)",
"Align_Label_SALabel_Format_not_Correct": "映射标签时SA Label中的文件格式不正确",
"Filename_Format_not_Correct": "(文件名格式不正确)",
"Method_Not_Exist": "(检测方法不存在)",
"Data_Length_not_Correct": "orgBcg和BCG长度不匹配",
"Artifact_Format_Not_Correct": "(体动长度或格式不正确)",
"Get_Artifact_Format_Exception": "获取体动长度或格式异常",
"Data_Length_Not_Correct": "信号长度不正确",
"Open_Data_Exception": "(打开数据异常)",
"Process_Exception": "(处理异常)",
@ -132,7 +134,9 @@ class Constants:
"Get_File_and_Freq_Excepetion": "(检查文件是否存在并获取其数据采样率异常)",
"Update_tableWidget_Exception": "(更新表格异常)",
"Update_Info_Exception": "(更新信息异常)",
"Get_Artifact_Format_Exception": "(获取体动长度或格式异常)",
"Label_Format_Exception": "(获取标签格式异常)",
"Calculate_Peak_Exception": "(计算峰值异常)",
"res_orgBcg_Not_Exist": "切割后orgBcg不存在",
"res_BCG_Not_Exist": "切割后BCG不存在",
@ -240,7 +244,7 @@ class Constants:
LABEL_CHECK_ADD_POINTS_SUCCESSFULLY: str = "成功新增点,横坐标:"
LABEL_CHECK_REMOVE_POINTS_SUCCESSFULLY: str = "成功删除点,横坐标:"
LABEL_CHECK_NO_POINT_IN_THE_INTERVAL: str = "所选区间内无新增或删除点"
LABEL_CHECK_ACTION_LABEL_MULTIPLE_NAME: str = f"批量更改标签({ConfigParams.LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY})"
LABEL_CHECK_ACTION_LABEL_MULTIPLE_NAME: str = f"批量更改标签({Params.LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY})"
# 数据精同步
PRECISELY_ALIGN_PROCESSING_DATA: str = "正在处理数据"
@ -296,7 +300,7 @@ class Constants:
PRECISELY_ALIGN_PLOT_LABEL_SELECTED_POINT: str = "Selected Point"
PRECISELY_ALIGN_NO_POINT_IN_THE_INTERVAL: str = "所选区间内无有效点"
PRECISELY_ALIGN_RECOVER_SCALE: str = "尺度恢复"
PRECISELY_ALIGN_ACTION_GET_RANGE_NAME: str = f"设置范围({ConfigParams.PRECISELY_ALIGN_ACTION_GET_RANGE_SHORTCUT_KEY})"
PRECISELY_ALIGN_ACTION_GET_RANGE_NAME: str = f"设置范围({Params.PRECISELY_ALIGN_ACTION_GET_RANGE_SHORTCUT_KEY})"
# 冗余数据切割和标签映射
CUT_PSG_GETTING_FILE_AND_FREQ: str = "正在获取文件及其采样率"
@ -324,11 +328,17 @@ class Constants:
ARTIFACT_LABEL_JUMP_ARTIFACT: str = "跳转到体动"
ARTIFACT_LABEL_RECOVER_SCALE: str = "尺度恢复"
ARTIFACT_LABEL_MISS_ARGS: str = "打标参数未填写"
ARTIFACT_LABEL_OVERLAPPING: str = "当前所打标的片段存在重合,重合片段序号:"
ARTIFACT_LABEL_MERGE: str = "当前所打标的片段距离附近片段不到2秒片段序号"
ARTIFACT_LABEL_MULTIPLE_ARTIFACT_COVER_OR_DELETE: str = "所选区域包含多种类型的体动,是否需要删除它们并使用新标注进行覆盖?所选区域中含有的体动序号:"
ARTIFACT_LABEL_FRONT_TWO_SECONDS_MERGE: str = "所选区域前2秒内有与当前标注相同类型的体动将执行合并"
ARTIFACT_LABEL_BACK_TWO_SECONDS_MERGE: str = "所选区域后2秒内有与当前标注相同类型的体动将执行合并"
ARTIFACT_LABEL_FRONT_AND_BACK_TWO_SECONDS_MERGE: str = "所选区域前后2秒内都有与当前标注相同类型的体动将执行合并"
ARTIFACT_LABEL_FRONT_TWO_SECONDS_WARNING: str = "所选区域前2秒内有与当前标注相同类型的体动仅进行提示"
ARTIFACT_LABEL_BACK_TWO_SECONDS_WARNING: str = "所选区域后2秒内有与当前标注相同类型的体动仅进行提示"
ARTIFACT_LABEL_FRONT_AND_BACK_TWO_SECONDS_WARNING: str = "所选区域前后2秒内都有与当前标注相同类型的体动仅进行提示"
ARTIFACT_LABEL_SINGLE_TYPE_NOT_EQUAL: str = "所选区域仅包含一种类型的体动,但其类型与当前标注的类型不匹配,是否需要删除它们并使用新标注覆盖?所选区域中含有的体动序号:"
ARTIFACT_LABEL_DELETE_ARTIFACT_SUCCESSFULLY: str = "体动被删除"
ARTIFACT_LABEL_DELETE_ARTIFACT_FAILURE: str = "需要被删除的体动不存在"
ARTIFACT_LABEL_ACTION_LABEL: str = f"标注体动({ConfigParams.ARTIFACT_LABEL_ACTION_LABEL_ARTIFACT_SHORTCUT_KEY})"
ARTIFACT_LABEL_ACTION_LABEL: str = f"标注体动({Params.ARTIFACT_LABEL_ACTION_LABEL_ARTIFACT_SHORTCUT_KEY})"
ARTIFACT_LABEL_LABELBTN_STYLE_1: str = """
QPushButton {
@ -381,6 +391,93 @@ class Constants:
background-color: #00ff00; /* 鼠标悬停时的背景颜色 */
}"""
# BCG的质量标注
BCG_QUALITY_LABEL_COLUMN_LABEL: str = "label"
BCG_QUALITY_LABEL_COLUMN_REMARK: str = "remark"
BCG_QUALITY_LABEL_PLOT_LABEL_SIGNAL: str = "BCG"
BCG_QUALITY_LABEL_PLOT_LABEL_ARTIFACT: str = "Artifact"
BCG_QUALITY_LABEL_PLOT_LABEL_LONGEST_CONTINUOUS: str = "Longest_Continuous"
BCG_QUALITY_LABEL_10S_A: str = "a1"
BCG_QUALITY_LABEL_10S_B: str = "b1"
BCG_QUALITY_LABEL_10S_C: str = "c1"
BCG_QUALITY_LABEL_30S_A1: str = "a1"
BCG_QUALITY_LABEL_30S_A2: str = "a2"
BCG_QUALITY_LABEL_30S_B1: str = "b1"
BCG_QUALITY_LABEL_30S_B2: str = "b2"
BCG_QUALITY_LABEL_30S_C: str = "c1"
BCG_QUALITY_LABEL_TOBELABELED: str = "f1"
BCG_QUALITY_LABEL_VIEWING_THE_FIRST_PART: str = "你正在查看第1段信号"
BCG_QUALITY_LABEL_VIEWING_THE_LAST_PART: str = "你正在查看最后1段信号"
BCG_QUALITY_LABEL_VIEWING_THE_FIRST_PART_UNLABELED: str = "前面的片段都被打标将跳转至第1段信号"
BCG_QUALITY_LABEL_VIEWING_THE_LAST_PART_UNLABELED: str = "后面的片段都被打标将跳转至最后1段信号"
BCG_QUALITY_LABEL_LABELED_FINISHED: str = "该份数据打标已全部完成"
BCG_QUALITY_LABEL_VIEWING_PART: str = "正在查看信号段"
BCG_QUALITY_LABEL_JUMP_PART: str = "跳转到片段"
BCG_QUALITY_LABEL_LABEL_ALL_TO_TYPE_C_QUESTION_CONTENT: str = "你确定要将所有片段标记为类型C"
BCG_QUALITY_LABEL_LABEL_ARTIFACT_TO_TYPE_C_QUESTION_CONTENT: str = "你确定要将所有带有体动的片段标记为类型C"
BCG_QUALITY_LABEL_LABELBTN_STYLE: str = """
QPushButton {
background-color: orange; /* 设置背景颜色 */
padding: 10px; /* 设置内边距 */
border: 2px solid darkblue; /* 设置边框 */
border-radius: 10px; /* 设置圆角 */
}
QPushButton:hover {
background-color: yellow; /* 鼠标悬停时的背景颜色 */
}"""
# 呼吸可用性及间期标注
RESP_QUALITY_LABEL_CALCULATING_PEAK: str = "正在计算峰值"
RESP_QUALITY_LABEL_CALCULATE_FINISHED: str = "计算完成"
RESP_QUALITY_LABEL_CALCULATE_FAILURE: str = "计算失败"
RESP_QUALITY_LABEL_PLOT_LABEL_ORGBCG: str = "BDR_Sync by filter OrgBCG_Sync"
RESP_QUALITY_LABEL_PLOT_LABEL_THO: str = "THO_Sync after preprocess"
RESP_QUALITY_LABEL_PLOT_LABEL_THO_PEAKS: str = "Tho_peak"
RESP_QUALITY_LABEL_PLOT_LABEL_ARTIFACT: str = "Artifact"
RESP_QUALITY_LABEL_SPECTRUM_BDR_TITLE: str = "Spectrum of BDR_sync by filter OrgBCG_Sync"
RESP_QUALITY_LABEL_SPECTRUM_THO_TITLE: str = "Spectrum of THO_sync after preprocess"
RESP_QUALITY_LABEL_SPECTRUM_ORGBCG_LABEL: str = "OrgBCG"
RESP_QUALITY_LABEL_SPECTRUM_BDR_LABEL: str = "BDR"
RESP_QUALITY_LABEL_SPECTRUM_THO_LABEL: str = "Tho"
RESP_QUALITY_LABEL_VIEWING_THE_FIRST_PART: str = "你正在查看第1段信号"
RESP_QUALITY_LABEL_VIEWING_THE_LAST_PART: str = "你正在查看最后1段信号"
RESP_QUALITY_LABEL_PREV_PART: str = "上一个片段index "
RESP_QUALITY_LABEL_NEXT_PART: str = "下一个片段index "
RESP_QUALITY_LABEL_JUMP: str = "跳转到片段index "
RESP_QUALITY_LABEL_LABEL_SUCCESSFULLY: str = "片段标注成功"
RESP_QUALITY_LABEL_LABEL_TYPE: str = "标注类型为:"
RESP_QUALITY_LABEL_ADD_POINTS_SUCCESSFULLY: str = "成功新增点,横坐标:"
RESP_QUALITY_LABEL_REMOVE_POINTS_SUCCESSFULLY: str = "成功删除点,横坐标:"
RESP_QUALITY_LABEL_NO_POINT_IN_THE_INTERVAL: str = "所选区间内无新增或删除点"
RESP_QUALITY_LABEL_CUSTOM_FILTER_ARGS_ERROR: str = "OrgBCG带通滤波频率设置范围应为数字范围是0~1"
RESP_QUALITY_LABEL_AUTOLABEL_ARGS_ERROR: str = "人工标注阈值设置范围应为数字范围是0~1"
RESP_QUALITY_LABEL_CHECK_ARGS_QUESTION_CONTENT: str = "你确定要执行此操作吗,请确保参数输入正确"
RESP_QUALITY_LABEL_ACTION_LABEL_MULTIPLE_NAME: str = f"批量更改标签({Params.RESP_QUALITY_LABEL_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY})"
RESP_QUALITY_LABEL_A_QUALITY: int = 1
RESP_QUALITY_LABEL_B_QUALITY: int = 0
RESP_QUALITY_LABEL_C_QUALITY: int = -1
RESP_QUALITY_LABEL_KEY_VALUE = {
1: "Good",
0: "Bad",
-1: "None"
}
RESP_QUALITY_LABEL_FIGTOOLBAR_SPECTRUM_STYLESHEET: str = """
QToolBar {
border: 1px;
spacing: 2px; /* 设置工具栏按钮之间的间距 */
}
QToolButton {
height: 20px; /* 设置工具栏按钮的高度 */
width: 20px; /* 设置工具栏按钮的宽度 */
font-size: 8px; /* 设置按钮文字大小 */
}
QToolButton::menu-button {
width: 0px; /* 隐藏下拉菜单按钮 */
}
"""
# 睡眠呼吸暂停事件标注
SA_LABEL_JUMP: str = "跳转到事件"
SA_LABEL_VIEWING_FIRST: str = "你正在查看第1个事件"
@ -398,133 +495,6 @@ class Constants:
SA_LABEL_LENGTH_LESS_THEN_10S: str = "当前标注的事件的持续时间小于10秒"
SA_LABEL_WRONG_ARGS: str = "起始时间和终止时间输入错误"
# 质量打标
BCG_QUALITY_LABEL_FILES_NOT_FOUND: str = f"无法找到{ConfigParams.BCG_QUALITY_LABEL_INPUT_BCG_FILENAME}{ConfigParams.ENDSWITH_TXT}{ConfigParams.BCG_QUALITY_LABEL_INPUT_ARTIFACT_FILENAME}{ConfigParams.ENDSWITH_TXT},无法执行<BCG的质量标注>"
BCG_QUALITY_LABEL_FILES_FOUND: str = f"找到{ConfigParams.BCG_QUALITY_LABEL_INPUT_BCG_FILENAME}{ConfigParams.ENDSWITH_TXT}{ConfigParams.BCG_QUALITY_LABEL_INPUT_ARTIFACT_FILENAME}{ConfigParams.ENDSWITH_TXT}"
BCG_QUALITY_LABEL_HISTORICAL_SAVE_FOUND: str = f"找到历史存档文件{ConfigParams.BCG_QUALITY_LABEL_SAVE_FILENAME}{ConfigParams.BCG_QUALITY_LABEL_SAVE_MODE_10S}{ConfigParams.ENDSWITH_CSV}{ConfigParams.BCG_QUALITY_LABEL_SAVE_FILENAME}{ConfigParams.BCG_QUALITY_LABEL_SAVE_MODE_30S}{ConfigParams.ENDSWITH_CSV},已成功读取"
BCG_QUALITY_LABEL_MODE_UNSELECTED: str = "显示模式未选择"
BCG_QUALITY_LABEL_INPUT_SIGNAL_FAILURE: str = "导入信号失败,请检查信号长度"
BCG_QUALITY_LABEL_INPUT_ARTIFACT_FAILURE_FORMAT: str = "导入体动失败,请检查体动标签格式"
BCG_QUALITY_LABEL_INPUT_ARTIFACT_FAILURE_LENGTH: str = "导入体动失败请检查体动长度是否为4的倍数"
BCG_QUALITY_LABEL_RUNNING: str = "开始执行任务<BCG的质量评估标注>"
BCG_QUALITY_LABEL_10S_MODE: str = f"{ConfigParams.BCG_QUALITY_LABEL_SAVE_MODE_10S}_MODE"
BCG_QUALITY_LABEL_30S_MODE: str = f"{ConfigParams.BCG_QUALITY_LABEL_SAVE_MODE_30S}_MODE"
BCG_QUALITY_LABEL_COLUMN_LABEL: str = "label"
BCG_QUALITY_LABEL_COLUMN_REMARK: str = "remark"
BCG_QUALITY_LABEL_VIEWING_THE_FIRST_PART: str = "你正在查看第1段信号"
BCG_QUALITY_LABEL_VIEWING_THE_LAST_PART: str = "你正在查看最后1段信号"
BCG_QUALITY_LABEL_VIEWING_THE_FIRST_PART_UNLABELED: str = "前面的片段都被打标将跳转至第1段信号"
BCG_QUALITY_LABEL_VIEWING_THE_LAST_PART_UNLABELED: str = "后面的片段都被打标将跳转至最后1段信号"
BCG_QUALITY_LABEL_LABELED_FINISHED: str = "该份数据打标已全部完成"
BCG_QUALITY_LABEL_VIEWING_PART: str = "正在查看信号段"
BCG_QUALITY_LABEL_JUMP_PART: str = "跳转到片段"
BCG_QUALITY_LABEL_CLICKED_CHECKBOX_HIGHLIGHT_LONGEST_CONTINUOUS: str = "点击了<高亮最长连续>"
BCG_QUALITY_LABEL_CLICKED_CHECKBOX_DISPLAY_AFTERFILTER: str = "点击了<去除工频噪声>"
BCG_QUALITY_LABEL_CLICKED_CHECKBOX_EXAMINE_TOBOLABELED: str = "点击了<仅查未标片段>"
BCG_QUALITY_LABEL_LABEL_ALL_TO_TYPE_C_QUESTION_CONTENT: str = "你确定要将所有片段标记为类型C"
BCG_QUALITY_LABEL_LABEL_ALL_TO_TYPE_C: str = "已将所有片段标记为类型C"
BCG_QUALITY_LABEL_LABEL_ARTIFACT_TO_TYPE_C_QUESTION_CONTENT: str = "你确定要将所有带有体动的片段标记为类型C"
BCG_QUALITY_LABEL_LABEL_ARTIFACT_TO_TYPE_C: str = "已将所有带有体动的片段标记为类型C"
BCG_QUALITY_LABEL_PLOT_LABEL_SIGNAL: str = "BCG"
BCG_QUALITY_LABEL_PLOT_LABEL_ARTIFACT: str = "Artifact"
BCG_QUALITY_LABEL_PLOT_LABEL_LONGEST_CONTINUOUS: str = "Longest_Continuous"
BCG_QUALITY_LABEL_10S_A: str = "a"
BCG_QUALITY_LABEL_10S_B: str = "b"
BCG_QUALITY_LABEL_10S_C: str = "c"
BCG_QUALITY_LABEL_10S_A_LIST: str = "label_a"
BCG_QUALITY_LABEL_10S_B_LIST: str = "label_b"
BCG_QUALITY_LABEL_10S_C_LIST: str = "label_c"
BCG_QUALITY_LABEL_30S_A1: str = "a"
BCG_QUALITY_LABEL_30S_A2: str = "b"
BCG_QUALITY_LABEL_30S_B1: str = "c"
BCG_QUALITY_LABEL_30S_B2: str = "d"
BCG_QUALITY_LABEL_30S_C: str = "e"
BCG_QUALITY_LABEL_30S_A1_LIST: str = "label_a1"
BCG_QUALITY_LABEL_30S_A2_LIST: str = "label_a2"
BCG_QUALITY_LABEL_30S_B1_LIST: str = "label_b1"
BCG_QUALITY_LABEL_30S_B2_LIST: str = "label_b2"
BCG_QUALITY_LABEL_30S_C_LIST: str = "label_c"
BCG_QUALITY_LABEL_tobeLabeled: str = "f"
BCG_QUALITY_LABEL_tobeLabeled_LIST: str = "label_tobeLabeled"
BCG_QUALITY_LABEL_LABELBTN_STYLE: str = """
QPushButton {
background-color: orange; /* 设置背景颜色 */
padding: 10px; /* 设置内边距 */
border: 2px solid darkblue; /* 设置边框 */
border-radius: 10px; /* 设置圆角 */
}
QPushButton:hover {
background-color: yellow; /* 鼠标悬停时的背景颜色 */
}"""
# 呼吸可用性及间期标注
RESP_QUALITY_LABEL_FILES_NOT_FOUND: str = f"无法找到{ConfigParams.RESP_QUALITY_LABEL_INPUT_XINXIAO_FILENAME}{ConfigParams.ENDSWITH_TXT}{ConfigParams.RESP_QUALITY_LABEL_INPUT_THO_FILENAME}{ConfigParams.ENDSWITH_TXT}{ConfigParams.RESP_QUALITY_LABEL_INPUT_ARTIFACT_FILENAME}{ConfigParams.ENDSWITH_TXT},无法执行<呼吸可用性及间期标注>"
RESP_QUALITY_LABEL_FILES_FOUND: str = f"找到{ConfigParams.RESP_QUALITY_LABEL_INPUT_XINXIAO_FILENAME}{ConfigParams.ENDSWITH_TXT}{ConfigParams.RESP_QUALITY_LABEL_INPUT_THO_FILENAME}{ConfigParams.ENDSWITH_TXT}{ConfigParams.RESP_QUALITY_LABEL_INPUT_ARTIFACT_FILENAME}{ConfigParams.ENDSWITH_TXT}"
RESP_QUALITY_LABEL_HISTORICAL_SAVE1_FOUND: str = f"找到历史存档文件{ConfigParams.RESP_QUALITY_LABEL_SAVE_RESP_QUALITY_LABNEL_FILENAME}{ConfigParams.ENDSWITH_TXT},已成功读取"
RESP_QUALITY_LABEL_HISTORICAL_SAVE2_FOUND: str = f"找到历史存档文件{ConfigParams.RESP_QUALITY_LABEL_SAVE_THO_PEAK_FILENAME}{ConfigParams.ENDSWITH_TXT},已成功读取"
RESP_QUALITY_LABEL_INPUT_SIGNAL_FAILURE: str = "导入信号失败,请检查信号长度"
RESP_QUALITY_LABEL_INPUT_SUCCESSFULLY: str = "导入数据成功"
RESP_QUALITY_LABEL_PREPROCESS_SUCCESSFULLY: str = "导入数据成功"
RESP_QUALITY_LABEL_INPUT_ARTIFACT_FAILURE_FORMAT: str = "导入体动失败,请检查体动标签格式"
RESP_QUALITY_LABEL_INPUT_ARTIFACT_FAILURE_LENGTH: str = "导入体动失败请检查体动长度是否为4的倍数"
RESP_QUALITY_LABEL_RUNNING: str = "开始执行任务<呼吸可用性及间期标注>"
RESP_QUALITY_LABEL_PLOT_LABEL_ORGBCG: str = "BDR_sync by filter orgBcg_sync"
RESP_QUALITY_LABEL_PLOT_LABEL_THO: str = "THO_sync after preprocess"
RESP_QUALITY_LABEL_PLOT_LABEL_THO_PEAKS: str = "THO_peak"
RESP_QUALITY_LABEL_PLOT_LABEL_ARTIFACT: str = "Artifact"
RESP_QUALITY_LABEL_VIEWING_THE_FIRST_PART: str = "你正在查看第1段信号"
RESP_QUALITY_LABEL_VIEWING_THE_LAST_PART: str = "你正在查看最后1段信号"
RESP_QUALITY_LABEL_ACTION_LABEL_MULTIPLE_NAME: str = f"批量更改标签({ConfigParams.RESP_QUALITY_LABEL_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY})"
RESP_QUALITY_LABEL_CUSTOM_NAVIGATIONTOOLBAR_WIDGET_NAME: str = "MainWindow"
RESP_QUALITY_LABEL_BUTTON_PRESS_EVENT: str = "button_press_event"
RESP_QUALITY_LABEL_BUTTON_RELEASE_EVENT: str = "button_release_event"
RESP_QUALITY_LABEL_MOTION_NOTIFY_EVENT: str = "motion_notify_event"
RESP_QUALITY_LABEL_ADD_POINTS_SUCCESSFULLY: str = "成功新增点,横坐标:"
RESP_QUALITY_LABEL_REMOVE_POINTS_SUCCESSFULLY: str = "成功删除点,横坐标:"
RESP_QUALITY_LABEL_NO_POINT_IN_THE_INTERVAL: str = "所选区间内无新增或删除点"
RESP_QUALITY_LABEL_SAVE_PEAKS_SUCCESSFULLY: str = "保存峰值成功"
RESP_QUALITY_LABEL_DATA_NOT_FOUND: str = "数据未导入"
RESP_QUALITY_LABEL_LABEL_SUCCESSFULLY: str = "片段标注并保存成功"
RESP_QUALITY_LABEL_RESET_SUCCESSFULLY: str = "片段重置并保存成功"
RESP_QUALITY_LABEL_PLOT_LABEL_VLINE: str = "vline"
RESP_QUALITY_LABEL_PLOT_LABEL_HLINE: str = "hline"
RESP_QUALITY_LABEL_A_QUALITY: int = 1
RESP_QUALITY_LABEL_B_QUALITY: int = 0
RESP_QUALITY_LABEL_C_QUALITY: int = -1
RESP_QUALITY_LABEL_LABELED: str = "已标注"
RESP_QUALITY_LABEL_TOBELABELED: str = "未标注"
RESP_QUALITY_LABEL_SPECTRUM_BDR_TITLE: str = "Spectrum of BDR_sync by filter orgBcg_sync"
RESP_QUALITY_LABEL_SPECTRUM_THO_TITLE: str = "Spectrum of THO_sync after preprocess"
RESP_QUALITY_LABEL_SPECTRUM_ORGBCG_LABEL: str = "orgBcg"
RESP_QUALITY_LABEL_SPECTRUM_BDR_LABEL: str = "BDR"
RESP_QUALITY_LABEL_SPECTRUM_THO_LABEL: str = "THO"
RESP_QUALITY_LABEL_CUSTOM_FILTER_ARGS_ERROR: str = "orgBcg带通滤波频率设置范围应为数字范围是0~1"
RESP_QUALITY_LABEL_AUTOLABEL_ARGS_ERROR: str = "人工标注阈值设置范围应为数字范围是0~1"
RESP_QUALITY_LABEL_CHECK_ARGS_QUESTION_CONTENT: str = "你确定要执行此操作吗,请确保参数输入正确"
RESP_QUALITY_LABEL_KEY_VALUE = {
1: "Good",
0: "Bad",
-1: "None"
}
# 禁止实例化
def __new__(cls):
raise TypeError("Constants class cannot be instantiated")

View File

@ -177,7 +177,7 @@ class PublicFunc:
QApplication.processEvents()
@staticmethod
def examine_file(path_str, filename):
def examine_file(path_str, filename, suffix):
temp_path = list(
Path(path_str).glob(f"{filename}*"))
if len(temp_path) == 0:
@ -201,8 +201,24 @@ class PublicFunc:
info=Constants.INPUT_FAILURE + "\n" +
filename + "" +
Constants.FAILURE_REASON["Data_Frequency_Not_In_Filename"])
if Path(path).suffix != suffix:
return Result().failure(
info=Constants.INPUT_FAILURE + "\n" +
filename + "" +
Constants.FAILURE_REASON["Suffix_Not_Correct"])
data = {
"path": str(path),
"freq": int(freq)
}
return Result().success(data=data)
return Result().success(data=data)
@staticmethod
def examine_artifact(artifact):
# 检查体动标签正确性,长度
if len(artifact) % 4 != 0:
return Result().failure(info=Constants.INPUT_FAILURE +
Constants.FAILURE_REASON["Artifact_Format_Not_Correct"])
for i in range(0, len(artifact), 4):
unit_data = artifact[i:i + 4]
if len(unit_data) < 4:
break