#!/usr/bin/python # -*- coding: UTF-8 -*- """ @author:andrew @file:RespCoarseAlign.py @email:admin@marques22.com @email:2021022362@m.scnu.edu.cn @time:2023/09/20 """ import sys from pathlib import Path import pyedflib import numpy as np import pandas as pd from PySide6.QtGui import QPixmap, QImage from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox, QWidget, QPushButton from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas from matplotlib.figure import Figure from scipy import signal from ui.Mian import Ui_mainWindow as Ui_respCoarseAlign from ui.setings import Ui_MainWindow as Ui_Setting import yaml Conf = { "PSGConfig": { "Path": "./Data/PSG/", "Frequency": 100, "THOChannel": { "auto": True, "Channel": 3, }, "ABDChannel": { "auto": True, "Channel": 4, }, }, "XXConfig": { "Path": "./Data/XX/", "Frequency": 100, }, "RespFilterConfig": { "LowPass": 0.01, "HighPass": 0.7, "order": 4 }, "ApplyFrequency": 5 } ButtonState = { "Default": { "pushButton_Refresh": True, "pushButton_OpenFile": True, "pushButton_Standardize": False, "pushButton_CutOff": False, "pushButton_GetPos": False, "pushButton_Align": False, "pushButton_JUMP": False, "pushButton_EM1": False, "pushButton_EM10": False, "pushButton_EM100": False, "pushButton_EP1": False, "pushButton_EP10": False, "pushButton_EP100": False, "pushButton_SaveInfo": False, "pushButton_Exit": True}, "Current": { "pushButton_Refresh": True, "pushButton_OpenFile": True, "pushButton_Standardize": False, "pushButton_CutOff": False, "pushButton_GetPos": False, "pushButton_Align": False, "pushButton_JUMP": False, "pushButton_EM1": False, "pushButton_EM10": False, "pushButton_EM100": False, "pushButton_EP1": False, "pushButton_EP10": False, "pushButton_EP100": False, "pushButton_SaveInfo": False, "pushButton_Exit": True} } class SettingWindow(QMainWindow): def __init__(self): super(SettingWindow, self).__init__() self.ui = Ui_Setting() self.ui.setupUi(self) self.__read_settings__() def __read_settings__(self): with open("./config.yaml", "r") as f: fileConfig = yaml.load(f.read(), Loader=yaml.FullLoader) Conf.update(fileConfig) # print(Conf) self.ui.lineEdit_PSGFilePath.setText(Conf["PSGConfig"]["Path"]) self.ui.lineEdit_XXFilePath.setText(Conf["XXConfig"]["Path"]) self.ui.spinBox_PSGDefaultFreq.setValue(Conf["PSGConfig"]["Frequency"]) self.ui.spinBox_XXDefaultFreq.setValue(Conf["XXConfig"]["Frequency"]) self.ui.QSpinBox_ApplyFre.setValue(Conf["ApplyFrequency"]) autoTHO = Conf["PSGConfig"]["THOChannel"]["auto"] self.ui.checkBox_THOautoChannel.setChecked(2 if autoTHO else 0) autoABD = Conf["PSGConfig"]["ABDChannel"]["auto"] self.ui.checkBox_ABDautoChannel.setChecked(2 if autoABD else 0) self.ui.spinBox_THOcustomChannel.setValue(Conf["PSGConfig"]["THOChannel"]["Channel"]) self.ui.spinBox_ABDcustomChannel.setValue(Conf["PSGConfig"]["ABDChannel"]["Channel"]) self.ui.doubleSpinBox_ButterLowPassFreq.setValue(Conf["RespFilterConfig"]["LowCut"]) self.ui.doubleSpinBox_ButterHighPassFreq.setValue(Conf["RespFilterConfig"]["HighCut"]) self.ui.spinBox_ButterOrder.setValue(Conf["RespFilterConfig"]["Order"]) self.ui.spinBox_THOcustomChannel.setEnabled(not autoTHO) self.ui.spinBox_ABDcustomChannel.setEnabled(not autoABD) # 绑定事件 self.ui.toolButton_PSGFilePath.clicked.connect(self.__select_file__) self.ui.toolButton_XXFilePath.clicked.connect(self.__select_file__) self.ui.pushButton_SaveConfig.clicked.connect(self.__write_settings__) self.ui.pushButton_Cancel.clicked.connect(self.close) # ABD auto checkbox和SpinBox 互斥 self.ui.checkBox_ABDautoChannel.stateChanged.connect(self.__ABDAutoChannel__) self.ui.checkBox_THOautoChannel.stateChanged.connect(self.__THOAutoChannel__) def __ABDAutoChannel__(self, state): if state == 2: self.ui.spinBox_ABDcustomChannel.setEnabled(False) else: self.ui.spinBox_ABDcustomChannel.setEnabled(True) def __THOAutoChannel__(self, state): if state == 2: self.ui.spinBox_THOcustomChannel.setEnabled(False) else: self.ui.spinBox_THOcustomChannel.setEnabled(True) def __select_file__(self, event): sender = self.sender() if sender.objectName() == "toolButton_PSGFilePath": path = QFileDialog.getExistingDirectory(self, "选择PSG数据文件夹", "./Data/PSG/") self.ui.lineEdit_PSGFilePath.setText(path) elif sender.objectName() == "toolButton_XXFilePath": path = QFileDialog.getExistingDirectory(self, "选择XX数据文件夹", "./Data/XX/") self.ui.lineEdit_XXFilePath.setText(path) def __write_settings__(self): # 从界面读取配置 Conf["PSGConfig"]["Path"] = self.ui.lineEdit_PSGFilePath.text() Conf["XXConfig"]["Path"] = self.ui.lineEdit_XXFilePath.text() Conf["PSGConfig"]["Frequency"] = self.ui.spinBox_PSGDefaultFreq.value() Conf["XXConfig"]["Frequency"] = self.ui.spinBox_XXDefaultFreq.value() Conf["ApplyFrequency"] = self.ui.QSpinBox_ApplyFre.value() Conf["PSGConfig"]["THOChannel"]["auto"] = self.ui.checkBox_THOautoChannel.isChecked() Conf["PSGConfig"]["ABDChannel"]["auto"] = self.ui.checkBox_ABDautoChannel.isChecked() Conf["PSGConfig"]["THOChannel"]["Channel"] = self.ui.spinBox_THOcustomChannel.value() Conf["PSGConfig"]["ABDChannel"]["Channel"] = self.ui.spinBox_ABDcustomChannel.value() Conf["RespFilterConfig"]["LowCut"] = self.ui.doubleSpinBox_ButterLowPassFreq.value() Conf["RespFilterConfig"]["HighCut"] = self.ui.doubleSpinBox_ButterHighPassFreq.value() Conf["RespFilterConfig"]["Order"] = self.ui.spinBox_ButterOrder.value() with open("./config.yaml", "w") as f: yaml.dump(Conf, f) self.close() class Data: def __init__(self, PSGDataPath, XXDataPath, sampNo, Config): self.PSGDataPath = PSGDataPath / f"{sampNo}.edf" if (XXDataPath / f"{sampNo}.npy").exists(): self.XXDataPath = XXDataPath / f"{sampNo}.npy" elif (XXDataPath / f"{sampNo}.txt").exists(): self.XXDataPath = XXDataPath / f"{sampNo}.txt" else: self.XXDataPath = None self.Config = Config self.raw_THO = None self.raw_ABD = None self.raw_XX = None self.processed_THO = None self.processed_ABD = None self.processed_XX = None self.PSG_minutes = None self.XX_minutes = None def OpenFile(self): # 判断是edf还是npy或txt if self.PSGDataPath.suffix == ".edf": PSG = pyedflib.EdfReader(self.PSGDataPath.__str__()) if self.Config["PSGConfig"]["THOChannel"]["auto"]: self.raw_THO = PSG.readSignal(PSG.getSignalLabels().index('Effort THO')) else: self.raw_THO = PSG.readSignal(self.Config["PSGConfig"]["THOChannel"]["Channel"]) if self.Config["PSGConfig"]["ABDChannel"]["auto"]: self.raw_ABD = PSG.readSignal(PSG.getSignalLabels().index('Effort ABD')) else: self.raw_ABD = PSG.readSignal(self.Config["PSGConfig"]["ABDChannel"]["Channel"]) PSG.close() else: return False, "PSG文件格式错误" if self.XXDataPath.suffix == ".npy": self.raw_XX = np.load(self.XXDataPath) elif self.XXDataPath.suffix == ".txt": self.raw_XX = pd.read_csv(self.XXDataPath, sep="\t", header=None).values else: return False, "XX文件格式错误" # 获取时长 # print(self.raw_THO.shape, self.raw_XX.shape) # print(self.Config["PSGConfig"]["Frequency"], self.Config["XXConfig"]["Frequency"]) self.PSG_minutes = round(self.raw_THO.shape[0] / self.Config["PSGConfig"]["Frequency"] / 60) self.XX_minutes = round(self.raw_XX.shape[0] / self.Config["XXConfig"]["Frequency"] / 60) return True, "读取成功" def __Filter__(self): def butter_bandpass_filter(data, lowCut, highCut, fs, order): low = lowCut / (fs * 0.5) high = highCut / (fs * 0.5) sos = signal.butter(order, [low, high], btype="bandpass", output='sos') return signal.sosfilt(sos, data) # 滤波 self.processed_THO = butter_bandpass_filter(self.raw_THO, self.Config["RespFilterConfig"]["LowCut"], self.Config["RespFilterConfig"]["HighCut"], self.Config["PSGConfig"]["Frequency"], self.Config["RespFilterConfig"]["Order"]) self.processed_ABD = butter_bandpass_filter(self.raw_ABD, self.Config["RespFilterConfig"]["LowCut"], self.Config["RespFilterConfig"]["HighCut"], self.Config["PSGConfig"]["Frequency"], self.Config["RespFilterConfig"]["Order"]) self.processed_XX = butter_bandpass_filter(self.raw_XX, self.Config["RespFilterConfig"]["LowCut"], self.Config["RespFilterConfig"]["HighCut"], self.Config["XXConfig"]["Frequency"], self.Config["RespFilterConfig"]["Order"]) return def Standardize_0(self): # 重采样 self.processed_THO = signal.resample(self.raw_THO, int(self.PSG_minutes * 60 * self.Config["ApplyFrequency"])) self.processed_ABD = signal.resample(self.raw_ABD, int(self.PSG_minutes * 60 * self.Config["ApplyFrequency"])) self.processed_XX = signal.resample(self.raw_XX, int(self.XX_minutes * 60 * self.Config["ApplyFrequency"])) return True, "原始信号仅重采样" def Standardize_1(self): self.__Filter__() return True, "呼吸提取完成 " def Standardize_2(self): # 如果XX采样率大于PSG采样率,那么XX重采样到PSG采样率 if self.Config["XXConfig"]["Frequency"] > self.Config["PSGConfig"]["Frequency"]: # 用[::]完成 self.processed_XX = self.processed_XX[ ::int(self.Config["XXConfig"]["Frequency"] / self.Config["PSGConfig"]["Frequency"])] # 如果XX采样率小于PSG采样率,那么XX重采样到PSG采样率 elif self.Config["XXConfig"]["Frequency"] < self.Config["PSGConfig"]["Frequency"] < 100: # 用repeat完成 self.processed_XX = np.repeat(self.processed_XX, int(self.Config["PSGConfig"]["Frequency"] / self.Config["XXConfig"][ "Frequency"]), axis=0) # 修改Config self.Config.update({"temp_frequency": self.Config["PSGConfig"]["Frequency"]}) return True, "预重采样完成" def Standardize_3(self): temp_frequency = self.Config["temp_frequency"] # 判断是否去基线 if self.Config["PSGConfig"]["PSGDelBase"]: # 减去四秒钟平均滤波 self.processed_THO = self.processed_THO - np.convolve(self.processed_THO, np.ones(int(4 * temp_frequency)) / int( 4 * temp_frequency), mode='same') self.processed_ABD = self.processed_ABD - np.convolve(self.processed_ABD, np.ones(int(4 * temp_frequency)) / int( 4 * temp_frequency), mode='same') if self.Config["XXConfig"]["XXDelBase"]: self.processed_XX = self.processed_XX - np.convolve(self.processed_XX, np.ones(int(4 * temp_frequency)) / int( 4 * temp_frequency), mode='same') return True, "去基线完成" def Standardize_4(self): # 判断是否标准化 if self.Config["PSGConfig"]["PSGZScore"]: self.processed_THO = (self.processed_THO - np.mean(self.processed_THO)) / np.std(self.processed_THO) self.processed_ABD = (self.processed_ABD - np.mean(self.processed_ABD)) / np.std(self.processed_ABD) if self.Config["XXConfig"]["XXZScore"]: self.processed_XX = (self.processed_XX - np.mean(self.processed_XX)) / np.std(self.processed_XX) return True, "标准化完成" def Standardize_5(self): # 重采样 self.processed_THO = signal.resample(self.processed_THO, int(self.PSG_minutes * 60 * self.Config["ApplyFrequency"])) self.processed_ABD = signal.resample(self.processed_ABD, int(self.PSG_minutes * 60 * self.Config["ApplyFrequency"])) self.processed_XX = signal.resample(self.processed_XX, int(self.XX_minutes * 60 * self.Config["ApplyFrequency"])) return True, "最终重采样完成" def DrawPicRawOverview(self): fig = Figure(figsize=(8, 7), dpi=100) canvas = FigureCanvas(fig) max_x = max(self.processed_THO.shape[0], self.processed_ABD.shape[0], self.processed_XX.shape[0]) ax1 = fig.add_subplot(311) ax1.plot(self.processed_THO, color='blue') ax1.set_xlim(0, max_x) ax1.set_title("THO") ax2 = fig.add_subplot(312) ax2.plot(self.processed_XX, color='blue') ax2.set_xlim(0, max_x) ax2.set_title("xinxiao") ax3 = fig.add_subplot(313) ax3.plot(self.processed_ABD, color='blue') ax3.set_xlim(0, max_x) ax3.set_title("ABD") width, height = fig.figbbox.width, fig.figbbox.height fig.canvas.draw() # 返回图片以便存到QPixIamge return canvas.buffer_rgba(), width, height def DrawPicOverviewWithCutOff(self): fig = Figure(figsize=(8, 7), dpi=100) canvas = FigureCanvas(fig) max_x = max(self.processed_THO.shape[0] + self.Config["PSGConfig"]["PreA"], self.processed_XX.shape[0] + self.Config["XXConfig"]["PreA"]) min_x = min(self.Config["PSGConfig"]["PreA"], self.Config["XXConfig"]["PreA"], 0) ax1 = fig.add_subplot(311) ax1.plot( np.linspace(self.Config["PSGConfig"]["PreA"], len(self.processed_THO) + self.Config["PSGConfig"]["PreA"], len(self.processed_THO)), self.processed_THO, color='blue') # 绘制x = PreCut的线 和 x = PostCut的虚线 ax1.axvline(x=self.Config["PSGConfig"]["PreCut"] + self.Config["PSGConfig"]["PreA"], color='red', linestyle='--') ax1.axvline(x=len(self.processed_THO) - self.Config["PSGConfig"]["PostCut"] + self.Config["PSGConfig"]["PreA"], color='red', linestyle='--') ax1.set_xlim(min_x, max_x) ax1.set_title("THO") ax2 = fig.add_subplot(312) ax2.plot(np.linspace(self.Config["XXConfig"]["PreA"], len(self.processed_XX) + self.Config["XXConfig"]["PreA"], len(self.processed_XX)), self.processed_XX, color='blue') ax2.axvline(x=self.Config["XXConfig"]["PreCut"] + self.Config["XXConfig"]["PreA"], color='red', linestyle='--') ax2.axvline(x=len(self.processed_XX) - self.Config["XXConfig"]["PostCut"] + self.Config["XXConfig"]["PreA"], color='red', linestyle='--') ax2.set_xlim(min_x, max_x) ax2.set_title("xinxiao") ax3 = fig.add_subplot(313) ax3.plot( np.linspace(self.Config["PSGConfig"]["PreA"], len(self.processed_ABD) + self.Config["PSGConfig"]["PreA"], len(self.processed_ABD)), self.processed_ABD, color='blue') ax3.axvline(x=self.Config["PSGConfig"]["PreCut"] + self.Config["PSGConfig"]["PreA"], color='red', linestyle='--') ax3.axvline(x=len(self.processed_THO) - self.Config["PSGConfig"]["PostCut"] + self.Config["PSGConfig"]["PreA"], color='red', linestyle='--') ax3.set_xlim(min_x, max_x) ax3.set_title("ABD") width, height = fig.figbbox.width, fig.figbbox.height fig.canvas.draw() # 返回图片以便存到QPixIamge return canvas.buffer_rgba(), width, height class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.ui = Ui_respCoarseAlign() self.setting = SettingWindow() self.ui.setupUi(self) self.ui.actionDefault_Configuration.triggered.connect(self.setting.show) # checkbox custom 和SpinBox 互斥 self.ui.checkBox_custom.stateChanged.connect(self.__customChannel__) self.__disableAllButton__() # 绑定事件 # 刷新键分别获取PSG和XX文件夹里面的数据,获取所有编号显示在下拉框,比对编号同时存在的可选,仅存在一个文件夹的编号不可选 self.ui.pushButton_Refresh.clicked.connect(self.__refresh__) self.ui.pushButton_OpenFile.clicked.connect(self.__openFile__) self.ui.pushButton_Standardize.clicked.connect(self.__standardize__) self.ui.pushButton_CutOff.clicked.connect(self.__cutOff__) self.ui.pushButton_GetPos.clicked.connect(self.__getPosition__) # self.ui.pushButton_Align.clicked.connect(self.__align__) # self.ui.pushButton_JUMP.clicked.connect(self.__jump__) # self.ui.pushButton_EM1.clicked.connect(self.__EM1__) # self.ui.pushButton_EM10.clicked.connect(self.__EM10__) # self.ui.pushButton_EM100.clicked.connect(self.__EM100__) # self.ui.pushButton_EP1.clicked.connect(self.__EP1__) # self.ui.pushButton_EP10.clicked.connect(self.__EP10__) # self.ui.pushButton_EP100.clicked.connect(self.__EP100__) # self.ui.pushButton_SaveInfo.clicked.connect(self.__saveInfo__) self.ui.pushButton_Exit.clicked.connect(self.__exit__) def __resset__(self): ButtonState["Current"].update(ButtonState["Default"].copy()) ButtonState["Current"]["pushButton_Standardize"] = True self.ui.spinBox_PSGPreA.setValue(0) self.ui.spinBox_PSGPreCut.setValue(0) self.ui.spinBox_PSGPostCut.setValue(0) self.ui.spinBox_XXPreA.setValue(0) self.ui.spinBox_XXPreCut.setValue(0) self.ui.spinBox_XXPostCut.setValue(0) self.ui.checkBox_NABD.setChecked(False) self.ui.checkBox_NTHO.setChecked(False) self.ui.checkBox_PABD.setChecked(False) self.ui.checkBox_PTHO.setChecked(False) self.ui.checkBox_custom.setChecked(False) self.ui.spinBox_SelectEpoch.setValue(0) self.ui.spinBox_custom.setValue(0) def __cutOff__(self): Conf2 = self.data.Config.copy() Conf2["PSGConfig"].update({"PreA": self.ui.spinBox_PSGPreA.value(), "PreCut": self.ui.spinBox_PSGPreCut.value(), "PostCut": self.ui.spinBox_PSGPostCut.value()}) Conf2["XXConfig"].update({"PreA": self.ui.spinBox_XXPreA.value(), "PreCut": self.ui.spinBox_XXPreCut.value(), "PostCut": self.ui.spinBox_XXPostCut.value()}) self.data.Config = Conf2 self.__plot__() # matplotlib 绘制图像 def __plot__(self): # 判读是哪个按钮点击调用的本程序 if self.sender() == self.ui.pushButton_Standardize: buffer, width, height = self.data.DrawPicRawOverview() elif self.sender() == self.ui.pushButton_CutOff: buffer, width, height = self.data.DrawPicOverviewWithCutOff() else: return # 显示到labelPic上 img = QImage(buffer, width, height, QImage.Format_RGBA8888) self.ui.label_Pic.setPixmap(QPixmap(img)) # noinspection PyUnresolvedReferences def __exit__(self): # 选择是否确认退出 reply = QMessageBox.question(self, '确认', '确认退出吗?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: self.close() def __customChannel__(self, state): if state == 2: self.ui.spinBox_custom.setEnabled(True) else: self.ui.spinBox_custom.setEnabled(False) # 刷新键分别获取PSG和XX文件夹里面的数据,获取所有编号显示在下拉框,比对编号同时存在的可选,仅存在一个文件夹的编号不可选 def __refresh__(self): # 检查两文件夹是否存在 PSGPath = Path(self.setting.ui.lineEdit_PSGFilePath.text()) XXPath = Path(self.setting.ui.lineEdit_XXFilePath.text()) if not PSGPath.exists(): QMessageBox.warning(self, "警告", "PSG文件夹不存在") return if not XXPath.exists(): QMessageBox.warning(self, "警告", "XX文件夹不存在") return # 获取两文件夹下所有的txt和npy文件编号 PSGFiles = [file.stem for file in PSGPath.glob("*.edf")] XXFiles = [file.stem for file in XXPath.glob("*.txt")] + [file.stem for file in XXPath.glob("*.npy")] sorted(PSGFiles) sorted(XXFiles) # 获取两文件夹下同时存在的编号 print(PSGFiles, XXFiles) Files = list(set(PSGFiles).intersection(set(XXFiles))) # 获取两文件夹下仅存在一个的编号 FilesOnlyInPSG = list(set(PSGFiles).difference(set(XXFiles))) FilesOnlyInXX = list(set(XXFiles).difference(set(PSGFiles))) print(Files, FilesOnlyInPSG, FilesOnlyInXX) # 均显示到下拉框 self.ui.comboBox_SelectFile.clear() self.ui.comboBox_SelectFile.addItems([file for file in Files]) self.ui.comboBox_SelectFile.addItems([file + " (仅PSG)" for file in FilesOnlyInPSG]) self.ui.comboBox_SelectFile.addItems([file + " (仅XX)" for file in FilesOnlyInXX]) self.ui.comboBox_SelectFile.setCurrentIndex(0) # # 仅存在一个文件夹的编号不可选 for file in FilesOnlyInPSG: self.ui.comboBox_SelectFile.model().item(FilesOnlyInPSG.index(file) + len(Files)).setEnabled(False) for file in FilesOnlyInXX: self.ui.comboBox_SelectFile.model().item( FilesOnlyInXX.index(file) + len(Files) + len(FilesOnlyInPSG)).setEnabled(False) def __disableAllButton__(self): # 禁用所有按钮 all_widgets = self.centralWidget().findChildren(QWidget) # 迭代所有部件,查找按钮并禁用它们 for widget in all_widgets: if isinstance(widget, QPushButton): if widget.objectName() in ButtonState["Current"].keys(): widget.setEnabled(ButtonState["Current"][widget.objectName()]) def __enableAllButton__(self): # 启用按钮 all_widgets = self.centralWidget().findChildren(QWidget) # 迭代所有部件,查找按钮并启用它们 for widget in all_widgets: if isinstance(widget, QPushButton): if widget.objectName() in ButtonState["Current"].keys(): widget.setEnabled(ButtonState["Current"][widget.objectName()]) def __openFile__(self): self.ui.label_Info.setText("正在打开文件...") self.__disableAllButton__() # 长时间操作,刷新界面防止卡顿 QApplication.processEvents() # 获取checkbox状态 self.data = Data(Path(self.setting.ui.lineEdit_PSGFilePath.text()), Path(self.setting.ui.lineEdit_XXFilePath.text()), self.ui.comboBox_SelectFile.currentText().split(" ")[0], Conf) opened, info = self.data.OpenFile() if not opened: QMessageBox.warning(self, "警告", info) self.ui.label_Info.setText(info) else: self.ui.label_PSGmins.setText(str(self.data.PSG_minutes)) self.ui.label_XXmins.setText(str(self.data.XX_minutes)) self.ui.progressBar.setValue(100) self.ui.label_Info.setText(info) self.__resset__() self.__enableAllButton__() def __standardize__(self): self.ui.progressBar.setValue(0) self.ui.label_Info.setText("正在标准化...") self.__disableAllButton__() QApplication.processEvents() Conf2 = self.data.Config.copy() Conf2["RawSignal"] = self.ui.checkBox_RawSignal.isChecked() Conf2["PSGConfig"].update({ "PSGDelBase": self.ui.checkBox_PSGDelBase.isChecked(), "PSGZScore": self.ui.checkBox_PSGZScore.isChecked(), "Frequency": self.ui.spinBox_PSGFreq.value(), }) Conf2["XXConfig"].update({ "XXDelBase": self.ui.checkBox_XXDelBase.isChecked(), "XXZScore": self.ui.checkBox_XXZScore.isChecked(), "Frequency": self.ui.spinBox_XXFreq.value(), }) self.data.Config = Conf2 if self.data.Config["RawSignal"]: opened, info = self.data.Standardize_0() if not opened: QMessageBox.warning(self, "警告", info) self.ui.label_Info.setText(info) else: self.ui.progressBar.setValue(100) self.ui.label_Info.setText(info) else: self.ui.label_Info.setText('正在进行呼吸提取...') QApplication.processEvents() opened, info = self.data.Standardize_1() self.ui.label_Info.setText(info) self.ui.progressBar.setValue(10) QApplication.processEvents() opened, info = self.data.Standardize_2() self.ui.progressBar.setValue(30) self.ui.label_Info.setText(info) QApplication.processEvents() opened, info = self.data.Standardize_3() self.ui.label_Info.setText(info) self.ui.progressBar.setValue(50) QApplication.processEvents() opened, info = self.data.Standardize_4() self.ui.label_Info.setText(info) self.ui.progressBar.setValue(70) QApplication.processEvents() opened, info = self.data.Standardize_5() self.ui.label_Info.setText(info) self.ui.progressBar.setValue(90) QApplication.processEvents() self.__plot__() self.ui.progressBar.setValue(100) ButtonState["Current"]["pushButton_CutOff"] = True ButtonState["Current"]["pushButton_GetPos"] = True self.__enableAllButton__() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec())