ecg_label_check/ecg_label_check.py

1030 lines
54 KiB
Python
Raw Normal View History

2025-02-10 19:14:14 +08:00
"""
@author:Yosa
@file:ecg_label_check.py
@email:2023025086@m.scnu.edu.cn
@time:2025/2/5
"""
import sys
from logging import NOTSET, getLogger, FileHandler, Formatter, StreamHandler, info, error, debug
from time import time, strftime, localtime
import pandas as pd
2025-02-10 19:14:14 +08:00
import numpy as np
from PyQt5 import QtGui
2025-02-10 19:14:14 +08:00
from PyQt5.QtGui import QFont, QDoubleValidator, QIntValidator
from matplotlib.ticker import FuncFormatter
2025-02-21 20:41:11 +08:00
from numpy import append
2025-02-10 19:14:14 +08:00
from matplotlib import use
from matplotlib import pyplot as plt, gridspec
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT
from datetime import datetime
from pathlib import Path
from PyQt5.QtCore import QCoreApplication, QTimer
from PyQt5.QtWidgets import QFileDialog, QMainWindow, QMessageBox, QButtonGroup, QApplication, QTableWidgetItem, \
2025-02-21 20:41:11 +08:00
QLineEdit, QAction, QTableWidget, QDialog, QVBoxLayout, QLabel, QDialogButtonBox
2025-02-10 19:14:14 +08:00
from scipy.signal import butter, filtfilt, find_peaks
import append
2025-02-10 19:14:14 +08:00
from MainWindow import Ui_MainWindow
use("Qt5Agg") # 声明使用QT5
# 设置日志
logger = getLogger()
logger.setLevel(NOTSET)
realtime = strftime('%Y%m%d', localtime(time()))
if not Path("logs").exists():
Path("logs").mkdir(exist_ok=True)
fh = FileHandler(Path("logs") / (realtime + ".log"), mode='a')
fh.setLevel(NOTSET)
fh.setFormatter(Formatter("%(asctime)s: %(message)s"))
logger.addHandler(fh)
ch = StreamHandler()
ch.setLevel(NOTSET)
ch.setFormatter(Formatter("%(asctime)s: %(message)s"))
logger.addHandler(ch)
getLogger('matplotlib.font_manager').disabled = True
info("------------------------------------")
info("---------ecg_label_check.py---------")
class MainWindow(QMainWindow, Ui_MainWindow):
# 全局变量初始化
data1 = np.array([])
data1 = data1.astype(np.float64)
data2 = np.array([])
data2 = data2.astype(np.float64)
label1 = np.array([])
label1 = label1.astype(np.int64)
label2 = np.array([])
label2 = label2.astype(np.int64)
# 程序初始化操作
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
# 设置画框
self.figure = plt.figure(figsize=(12, 6), dpi=150)
self.canvas = FigureCanvasQTAgg(self.figure)
self.figToolbar = CustomNavigationToolbar(self.canvas, self)
self.verticalLayout_canvas.addWidget(self.canvas)
self.verticalLayout_canvas.addWidget(self.figToolbar)
self.figToolbar._actions['home'].triggered.connect(self.toggle_home)
self.figToolbar.action_Label_Single.triggered.connect(self.toggle_changeLabel_Single_mode)
self.figToolbar.action_Label_Multiple.triggered.connect(self.toggle_changeLabel_Multiple_mode)
# 画框子图初始化
self.gs = gridspec.GridSpec(2, 1, height_ratios=[1, 1])
self.figure.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)
plt.margins(0, 0)
plt.tight_layout()
plt.xticks([])
plt.yticks([])
# 单选框组件分组
self.buttonGroup_inputMode = QButtonGroup()
self.buttonGroup_inputMode.addButton(self.radioButton_inputMode_auto)
self.buttonGroup_inputMode.addButton(self.radioButton_inputMode_manual)
self.buttonGroup_data1_preprocess = QButtonGroup()
self.buttonGroup_data1_preprocess.addButton(self.radioButton_data1_fillterMode)
self.buttonGroup_data2_preprocess = QButtonGroup()
self.buttonGroup_data2_preprocess.addButton(self.radioButton_data2_fillterMode)
self.buttonGroup_move_preset = QButtonGroup()
self.buttonGroup_move_preset.addButton(self.radioButton_move_preset_1)
self.buttonGroup_move_preset.addButton(self.radioButton_move_preset_2)
self.buttonGroup_move_preset.addButton(self.radioButton_move_preset_3)
self.buttonGroup_move_preset.addButton(self.radioButton_move_custom)
# 设置表格属性
self.tableWidget_label1.setHorizontalHeaderLabels(['label1'])
self.tableWidget_label2.setHorizontalHeaderLabels(['label2'])
self.tableWidget_label1.setEditTriggers(QTableWidget.NoEditTriggers)
self.tableWidget_label2.setEditTriggers(QTableWidget.NoEditTriggers)
2025-02-19 19:13:48 +08:00
self.tableWidget_label1.horizontalHeader().setStretchLastSection(True)
self.tableWidget_label1.horizontalHeader().setSectionResizeMode(1)
self.tableWidget_label2.horizontalHeader().setStretchLastSection(True)
self.tableWidget_label2.horizontalHeader().setSectionResizeMode(1)
2025-02-10 19:14:14 +08:00
# 槽函数连接控件初始化
self.pushButton_savepath_open.clicked.connect(self.slot_btn_selectPath)
self.pushButton_rootpath_open.clicked.connect(self.slot_btn_selectPath)
self.pushButton_data1path_open.clicked.connect(self.slot_btn_selectPath)
self.pushButton_data2path_open.clicked.connect(self.slot_btn_selectPath)
self.pushButton_label1path_open.clicked.connect(self.slot_btn_selectPath)
self.pushButton_label2path_open.clicked.connect(self.slot_btn_selectPath)
self.pushButton_dataInput.clicked.connect(self.slot_btn_dataInput)
self.pushButton_append.clicked.connect(self.slot_btn_append)
2025-02-10 19:14:14 +08:00
self.pushButton_outputLabel.clicked.connect(self.slot_btn_outputLabel)
self.comboBox_choose.currentTextChanged.connect(self.slot_comboBox_textChanged)
self.radioButton_inputMode_auto.clicked.connect(self.slot_radioBtn_inputMode_auto)
self.radioButton_inputMode_manual.clicked.connect(self.slot_radioBtn_inputMode_manual)
self.pushButton_left_move.clicked.connect(self.slot_btn_left_move)
self.pushButton_pause.clicked.connect(self.slot_btn_pause)
self.pushButton_right_move.clicked.connect(self.slot_btn_right_move)
self.radioButton_move_preset_1.clicked.connect(self.slot_radioBtn_move_preset_1)
self.radioButton_move_preset_2.clicked.connect(self.slot_radioBtn_move_preset_2)
self.radioButton_move_preset_3.clicked.connect(self.slot_radioBtn_move_preset_3)
self.radioButton_move_custom.clicked.connect(self.slot_radioBtn_move_custom)
self.tableWidget_label1.cellDoubleClicked.connect(self.slot_tableWidget_1_on_cell_double_clicked)
self.tableWidget_label2.cellDoubleClicked.connect(self.slot_tableWidget_2_on_cell_double_clicked)
# 初始化按钮快捷键
self.pushButton_left_move.setShortcut(QCoreApplication.translate("MainWindow", "A"))
self.pushButton_pause.setShortcut(QCoreApplication.translate("MainWindow", "S"))
self.pushButton_right_move.setShortcut(QCoreApplication.translate("MainWindow", "D"))
# 界面控件状态初始化
self.lineEdit_rootpath.setEnabled(False)
self.lineEdit_savepath.setEnabled(False)
self.lineEdit_data1path.setEnabled(False)
self.lineEdit_data2path.setEnabled(False)
self.lineEdit_label1path.setEnabled(False)
self.lineEdit_label2path.setEnabled(False)
self.label_choose.setEnabled(False)
self.comboBox_choose.setEnabled(False)
self.groupBox_save.setEnabled(False)
self.groupBox_data1.setEnabled(False)
self.groupBox_data2.setEnabled(False)
self.groupBox_label1.setEnabled(False)
self.groupBox_label2.setEnabled(False)
self.groupBox_autoplay.setEnabled(False)
self.groupBox_labelDisplay.setEnabled(False)
self.radioButton_inputMode_auto.setChecked(True)
self.radioButton_data1_fillterMode.setChecked(True)
self.radioButton_data2_fillterMode.setChecked(True)
self.radioButton_move_preset_1.setChecked(True)
self.pushButton_outputLabel.setEnabled(False)
self.figToolbar.action_Label_Single.setEnabled(False)
self.figToolbar.action_Label_Multiple.setEnabled(False)
for action in self.figToolbar._actions.values():
action.setEnabled(False)
# 消息弹窗初始化
self.msgBox = QMessageBox()
self.msgBox.setWindowTitle("消息")
# 自动播放参数初始化
self.autoplay_mode = "pause"
self.autoplay_moveLength = int(self.label_moveLength_preset_1.text())
self.autoplay_maxRange = int(self.label_maxRange_preset_1.text())
self.autoplay_moveSpeed = int(self.label_moveSpeed_preset_1.text())
# 初始化自动播放定时器
self.timer_autoplay = QTimer()
self.timer_autoplay.timeout.connect(self.autoplay_move_xlim)
# 绘图工具初始化
self.points_y = np.array([])
self.temp_point = None
self.is_left_button_pressed = False
self.is_right_button_pressed = False
# 定义验证器用于规范lineEdit的输入内容
validator_double = QDoubleValidator(-1e100, 1e100, 10)
validator_integer = QIntValidator(-2**31, 2**31 - 1)
self.lineEdit_data1_fillterNum.setValidator(validator_integer)
self.lineEdit_data2_fillterNum.setValidator(validator_integer)
self.lineEdit_data1_fillterFrequency_min.setValidator(validator_double)
self.lineEdit_data1_fillterFrequency_max.setValidator(validator_double)
self.lineEdit_data2_fillterFrequency_min.setValidator(validator_double)
self.lineEdit_data2_fillterFrequency_max.setValidator(validator_double)
self.lineEdit_frequency.setValidator(validator_double)
self.lineEdit_moveLength.setValidator(validator_integer)
self.lineEdit_maxRange.setValidator(validator_double)
self.lineEdit_moveSpeed.setValidator(validator_integer)
self.lineEdit_findpeaks_min_interval.setValidator(validator_integer)
self.lineEdit_findpeaks_min_height.setValidator(validator_double)
self.textBrowser_update("程序启动成功,导入数据以开始任务")
info("Program Started.")
def slot_btn_selectPath(self):
fileDialog = QFileDialog()
if self.sender() == self.pushButton_rootpath_open:
fileDialog.setFileMode(QFileDialog.Directory)
fileDialog.setOption(QFileDialog.ShowDirsOnly, True)
if fileDialog.exec_() == QFileDialog.Accepted:
file_path = fileDialog.selectedFiles()[0]
if not file_path:
error("Root Path not Exist...")
self.textBrowser_update("操作:根目录路径输入错误")
self.msgBox.setText("根目录路径输入错误")
self.msgBox.setIcon(QMessageBox.Critical)
self.msgBox.exec()
return
self.lineEdit_rootpath.setText(file_path)
file_path = Path(file_path)
info("Loading Root Path...")
self.data_and_label_Path = file_path / "label"
if self.data_and_label_Path.exists():
# 检查路径下的hecg.txt和hRpeak.txt文件是否一一对应
data_files = sorted(self.data_and_label_Path.glob('*ecg.txt'))
label_files = sorted(self.data_and_label_Path.glob('*Rpeak.txt'))
if len(data_files) != len(label_files):
error("Data Quantity not Match...")
self.textBrowser_update(f"操作数据导入错误ecg.txt和Rpeak.txt文件数量不匹配分别是{str(len(data_files))}{str(len(label_files))}")
self.msgBox.setText(f"数据导入错误ecg.txt和Rpeak.txt文件数量不匹配分别是{str(len(data_files))}{str(len(label_files))}")
self.msgBox.setIcon(QMessageBox.Critical)
self.msgBox.exec()
return
for data_file, label_file in zip(data_files, label_files):
if data_file.stem.replace('ecg', '') != label_file.stem.replace('Rpeak', ''):
self.textBrowser_update(f"操作:数据导入错误,文件名称存在不匹配,分别是{str(data_file.stem)}{str(label_file.stem)}")
self.msgBox.setText(f"操作:数据导入错误,文件名称存在不匹配,分别是{str(data_file.stem)}{str(label_file.stem)}")
self.msgBox.setIcon(QMessageBox.Critical)
self.msgBox.exec()
return
nums_for_comboBox = np.array([])
for data_file in data_files:
prefix = data_file.stem.replace('ecg', '')
nums_for_comboBox = np.append(nums_for_comboBox, prefix)
nums_for_comboBox = nums_for_comboBox.astype(np.int8)
nums_for_comboBox.sort()
nums_for_comboBox = nums_for_comboBox.astype(str)
self.comboBox_choose.clear()
self.comboBox_choose.addItems(nums_for_comboBox)
self.label_choose.setEnabled(True)
self.comboBox_choose.setEnabled(True)
self.groupBox_save.setEnabled(True)
self.groupBox_data1.setEnabled(True)
self.groupBox_data2.setEnabled(True)
self.groupBox_label1.setEnabled(True)
self.groupBox_label2.setEnabled(True)
# 更新数据路径文本框
self.lineEdit_savepath.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "location_J.txt")
self.lineEdit_data1path.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "ecg.txt")
self.lineEdit_data2path.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "ecg.txt")
self.lineEdit_label1path.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "Rpeak.txt")
self.lineEdit_label2path.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "Rpeak.txt")
info("Successfully Loaded Root Path.")
self.textBrowser_update("操作:根目录路径选择成功")
else:
info("Failed to Load Root Path.")
self.textBrowser_update("操作:根目录路径选择错误,缺乏必要数据文件夹")
self.msgBox.setText("根目录路径选择错误,缺乏必要数据文件夹")
self.msgBox.setIcon(QMessageBox.Critical)
self.msgBox.exec()
return
else:
info("Canceled Loading Root Path.")
self.textBrowser_update("提示:根目录路径选择取消")
self.msgBox.setText("根目录路径选择取消")
self.msgBox.setIcon(QMessageBox.Warning)
self.msgBox.exec()
elif self.sender() == self.pushButton_savepath_open:
fileDialog.setFileMode(QFileDialog.Directory)
fileDialog.setOption(QFileDialog.ShowDirsOnly, True)
if fileDialog.exec_() == QFileDialog.Accepted:
file_path = fileDialog.selectedFiles()[0]
self.lineEdit_savepath.setText(str(Path(file_path) / "newlocation_J.txt"))
info("Successfully Loaded Save Path.")
self.textBrowser_update("操作:保存路径选择成功")
else:
info("Canceled Loading Save Path.")
self.textBrowser_update("提示:保存路径选择取消")
self.msgBox.setText("保存路径选择取消")
self.msgBox.setIcon(QMessageBox.Warning)
self.msgBox.exec()
else:
fileDialog.setFileMode(QFileDialog.ExistingFile)
fileDialog.setOption(QFileDialog.ReadOnly, True)
fileDialog.setNameFilter("Text Files (*.txt)")
if fileDialog.exec_() == QFileDialog.Accepted:
file_path = fileDialog.selectedFiles()[0]
if self.sender() == self.pushButton_data1path_open:
self.lineEdit_data1path.setText(file_path)
elif self.sender() == self.pushButton_data2path_open:
self.lineEdit_data2path.setText(file_path)
elif self.sender() == self.pushButton_label1path_open:
self.lineEdit_label1path.setText(file_path)
elif self.sender() == self.pushButton_label2path_open:
self.lineEdit_label2path.setText(file_path)
info("Successfully Loaded Data Path.")
self.textBrowser_update("操作:数据路径选择成功")
else:
info("Canceled Loading Data Path.")
self.textBrowser_update("提示:数据路径选择取消")
self.msgBox.setText("数据路径选择取消")
self.msgBox.setIcon(QMessageBox.Warning)
self.msgBox.exec()
def slot_btn_dataInput(self):
if self.lineEdit_data1path.text() != "" or self.lineEdit_data2path.text() != "" or self.lineEdit_label1path.text() != "" or self.lineEdit_label2path.text() != "" or self.lineEdit_savepath.text() != "":
info("Inputing Data...")
self.textBrowser_update("提示:开始导入数据")
2025-02-12 12:14:54 +08:00
# 导入数据
self.label1 = np.array([])
self.label2 = np.array([])
file = open(str(self.lineEdit_data1path.text()), 'r')
self.data1 = file.readlines()
self.data1 = list(map(float, self.data1))
self.data2 = self.data1
self.data1 = self.data_preprocess(self.data1, int(self.lineEdit_data1_fillterNum.text()),
float(self.lineEdit_data1_fillterFrequency_min.text()),
float(self.lineEdit_data1_fillterFrequency_max.text()),
float(self.lineEdit_frequency.text()))
self.data2 = self.data_preprocess(self.data2, int(self.lineEdit_data2_fillterNum.text()),
float(self.lineEdit_data2_fillterFrequency_min.text()),
float(self.lineEdit_data2_fillterFrequency_max.text()),
float(self.lineEdit_frequency.text()))
file = open(str(self.lineEdit_label1path.text()), 'r')
self.label1 = np.array(file.readlines())
self.label2 = self.label1
self.data1 = self.data1.astype(np.float64)
self.data2 = self.data2.astype(np.float64)
self.label1 = self.label1.astype(np.int64)
self.label2 = self.label2.astype(np.int64)
self.points_y_1 = [self.data1[x] for x in self.label1]
self.points_y_2 = [self.data2[x] for x in self.label2]
# 更新tableWidget
self.tableWidget_label1.setRowCount(len(self.label1))
for row, value in enumerate(self.label1):
item = QTableWidgetItem(str(value).strip())
self.tableWidget_label1.setItem(row, 0, item)
self.tableWidget_label2.setRowCount(self.label2.__len__())
for row, value in enumerate(self.label2):
item = QTableWidgetItem(str(value).strip())
self.tableWidget_label2.setItem(row, 0, item)
self.groupBox_labelDisplay.setEnabled(True)
# 更新界面
self.groupBox_inputSetting.setEnabled(False)
self.groupBox_autoplay.setEnabled(True)
self.pushButton_outputLabel.setEnabled(True)
self.figToolbar.action_Label_Single.setEnabled(True)
self.figToolbar.action_Label_Multiple.setEnabled(True)
2025-02-12 12:14:54 +08:00
MainWindow.setWindowTitle(self, QCoreApplication.translate("MainWindow",
"ECG_Label_Check - Data Path: " + self.lineEdit_rootpath.text()))
for action in self.figToolbar._actions.values():
action.setEnabled(True)
# 更新信息
self.label_data1_length.setText(str(len(self.data1)))
self.label_data2_length.setText(str(len(self.data2)))
self.label_label1_length.setText(str(len(self.label1)))
self.label_label2_length.setText(str(len(self.label2)))
# 更新画框
self.figure.clear()
self.plot_data_and_label()
# 连接画框中的槽函数
# Connect mouse events
self.canvas.mpl_connect('motion_notify_event', self.on_motion)
# 保存路径文件是否存在的检查
if not Path(self.lineEdit_savepath.text()).exists():
Path(self.lineEdit_savepath.text()).touch()
np.savetxt(Path(self.lineEdit_savepath.text()), self.label2, fmt='%d', newline='\n')
info("Finished Input Data.")
self.textBrowser_update("提示:导入数据完成")
else:
info("Failed to Input Data!")
self.textBrowser_update("操作:导入数据失败")
self.msgBox.setText("导入失败,请正确输入路径")
self.msgBox.setIcon(QMessageBox.Critical)
self.msgBox.exec()
2025-02-10 19:14:14 +08:00
def slot_radioBtn_inputMode_auto(self):
self.pushButton_rootpath_open.setEnabled(True)
self.label_choose.setEnabled(False)
self.comboBox_choose.setEnabled(False)
self.groupBox_save.setEnabled(False)
self.groupBox_data1.setEnabled(False)
self.groupBox_data2.setEnabled(False)
self.groupBox_label1.setEnabled(False)
self.groupBox_label2.setEnabled(False)
self.lineEdit_savepath.setText("")
self.lineEdit_rootpath.setText("")
self.lineEdit_data1path.setText("")
self.lineEdit_data2path.setText("")
self.lineEdit_label1path.setText("")
self.lineEdit_label2path.setText("")
self.comboBox_choose.clear()
info("Switched to inputMode_auto.")
self.textBrowser_update("操作:切换到输入模式-自动识别")
def slot_radioBtn_inputMode_manual(self):
self.pushButton_rootpath_open.setEnabled(False)
self.label_choose.setEnabled(False)
self.comboBox_choose.setEnabled(False)
self.groupBox_save.setEnabled(True)
self.groupBox_data1.setEnabled(True)
self.groupBox_data2.setEnabled(True)
self.groupBox_label1.setEnabled(True)
self.groupBox_label2.setEnabled(True)
self.lineEdit_rootpath.setText("")
self.comboBox_choose.clear()
info("Switched to inputMode_manual.")
self.textBrowser_update("操作:切换到输入模式-手动输入")
def slot_comboBox_textChanged(self):
# 更新数据路径文本框
self.lineEdit_savepath.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "location_J.txt")
self.lineEdit_data1path.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "ecg.txt")
self.lineEdit_data2path.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "ecg.txt")
self.lineEdit_label1path.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "Rpeak.txt")
self.lineEdit_label2path.setText(
str(self.data_and_label_Path) + "\\" + self.comboBox_choose.currentText() + "Rpeak.txt")
def slot_btn_left_move(self):
self.autoplay_mode = "left"
self.autoplay_xlim_start = int(self.ax0.get_xlim()[1] - self.autoplay_maxRange)
self.autoplay_xlim_end = int(self.ax0.get_xlim()[1])
if self.autoplay_xlim_end > self.data2.__len__():
self.autoplay_xlim_start = int(self.data2.__len__() - self.autoplay_maxRange)
self.autoplay_xlim_end = int(self.data2.__len__())
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
self.timer_autoplay.start(self.autoplay_moveSpeed)
info("Started Autoplay left_mode.")
self.textBrowser_update("操作:开始自动播放-向左")
def slot_btn_pause(self):
self.autoplay_mode = "pause"
self.timer_autoplay.stop()
info("Paused Autoplay.")
self.textBrowser_update("操作:暂停自动播放")
def slot_btn_right_move(self):
self.autoplay_mode = "right"
self.autoplay_xlim_start = int(self.ax0.get_xlim()[0])
self.autoplay_xlim_end = int(self.ax0.get_xlim()[0] + self.autoplay_maxRange)
if self.autoplay_xlim_start < 0:
self.autoplay_xlim_start = 0
self.autoplay_xlim_end = 0 + self.autoplay_maxRange
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
self.timer_autoplay.start(self.autoplay_moveSpeed)
info("Started Autoplay right_mode.")
self.textBrowser_update("操作:开始自动播放-向右")
def slot_radioBtn_move_preset_1(self):
self.autoplay_moveLength = int(self.label_moveLength_preset_1.text())
self.autoplay_maxRange = int(self.label_maxRange_preset_1.text())
self.autoplay_moveSpeed = int(self.label_moveSpeed_preset_1.text())
if self.autoplay_mode != "pause":
if self.autoplay_mode == "right":
self.autoplay_xlim_start = int(self.ax0.get_xlim()[0])
self.autoplay_xlim_end = int(self.ax0.get_xlim()[0] + self.autoplay_maxRange)
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
elif self.autoplay_mode == "left":
self.autoplay_xlim_start = int(self.ax0.get_xlim()[1] - self.autoplay_maxRange)
self.autoplay_xlim_end = int(self.ax0.get_xlim()[1])
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
self.timer_autoplay.start(self.autoplay_moveSpeed)
info("Switched to Autoplay preset_1.")
self.textBrowser_update("操作:切换到自动播放-预设1")
def slot_radioBtn_move_preset_2(self):
self.autoplay_moveLength = int(self.label_moveLength_preset_2.text())
self.autoplay_maxRange = int(self.label_maxRange_preset_2.text())
self.autoplay_moveSpeed = int(self.label_moveSpeed_preset_2.text())
if self.autoplay_mode != "pause":
if self.autoplay_mode == "right":
self.autoplay_xlim_start = int(self.ax0.get_xlim()[0])
self.autoplay_xlim_end = int(self.ax0.get_xlim()[0] + self.autoplay_maxRange)
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
elif self.autoplay_mode == "left":
self.autoplay_xlim_start = int(self.ax0.get_xlim()[1] - self.autoplay_maxRange)
self.autoplay_xlim_end = int(self.ax0.get_xlim()[1])
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
self.timer_autoplay.start(self.autoplay_moveSpeed)
info("Switched to Autoplay preset_2.")
self.textBrowser_update("操作:切换到自动播放-预设2")
def slot_radioBtn_move_preset_3(self):
self.autoplay_moveLength = int(self.label_moveLength_preset_3.text())
self.autoplay_maxRange = int(self.label_maxRange_preset_3.text())
self.autoplay_moveSpeed = int(self.label_moveSpeed_preset_3.text())
if self.autoplay_mode != "pause":
if self.autoplay_mode == "right":
self.autoplay_xlim_start = int(self.ax0.get_xlim()[0])
self.autoplay_xlim_end = int(self.ax0.get_xlim()[0] + self.autoplay_maxRange)
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
elif self.autoplay_mode == "left":
self.autoplay_xlim_start = int(self.ax0.get_xlim()[1] - self.autoplay_maxRange)
self.autoplay_xlim_end = int(self.ax0.get_xlim()[1])
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
self.timer_autoplay.start(self.autoplay_moveSpeed)
info("Switched to Autoplay preset_3.")
self.textBrowser_update("操作:切换到自动播放-预设3")
def slot_radioBtn_move_custom(self):
self.autoplay_moveLength = int(self.lineEdit_moveLength.text())
self.autoplay_maxRange = int(self.lineEdit_maxRange.text())
self.autoplay_moveSpeed = int(self.lineEdit_moveSpeed.text())
if self.autoplay_mode != "pause":
if self.autoplay_mode == "right":
self.autoplay_xlim_start = int(self.ax0.get_xlim()[0])
self.autoplay_xlim_end = int(self.ax0.get_xlim()[0] + self.autoplay_maxRange)
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
elif self.autoplay_mode == "left":
self.autoplay_xlim_start = int(self.ax0.get_xlim()[1] - self.autoplay_maxRange)
self.autoplay_xlim_end = int(self.ax0.get_xlim()[1])
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
self.timer_autoplay.start(self.autoplay_moveSpeed)
info("Switched to Autoplay custom.")
self.textBrowser_update("操作:切换到自动播放-自定义")
self.msgBox.setText("自定义的输入参数未做任何检查,请斟酌输入参数,否则可能会导致程序异常")
self.msgBox.setIcon(QMessageBox.Warning)
self.msgBox.exec()
def slot_tableWidget_1_on_cell_double_clicked(self, row, column):
x = float(self.tableWidget_label1.item(row, column).text())
self.ax0.set_xlim(x - 5000, x + 5000)
self.annotation_tableWidget = self.ax0.annotate(f'x={int(x)}', xy=(int(x), self.ax0.get_ylim()[0]), xytext=(int(x), self.ax0.get_ylim()[0] + (self.ax0.get_ylim()[1] - self.ax0.get_ylim()[0]) * 0.1),
arrowprops=dict(facecolor='black', shrink=0.1))
self.canvas.draw()
info(f"Jumped to x_axis: {str(int(x))}.")
self.textBrowser_update(f"操作跳转到x坐标: {str(int(x))}")
def slot_tableWidget_2_on_cell_double_clicked(self, row, column):
x = float(self.tableWidget_label2.item(row, column).text())
self.ax0.set_xlim(x - 5000, x + 5000)
self.annotation_tableWidget = self.ax0.annotate(f'x={int(x)}', xy=(int(x), self.ax0.get_ylim()[0]), xytext=(int(x), self.ax0.get_ylim()[0] + (self.ax0.get_ylim()[1] - self.ax0.get_ylim()[0]) * 0.1),
arrowprops=dict(facecolor='black', shrink=0.1))
self.canvas.draw()
info(f"Jumped to x_axis: {str(int(x))}.")
self.textBrowser_update(f"操作跳转到x坐标: {str(int(x))}")
def slot_btn_append(self):
dialog = CustomMessageBox(self)
reply = dialog.exec_()
if reply == QDialog.Accepted:
if self.lineEdit_rootpath.text() == "" or len(list((Path(self.lineEdit_rootpath.text()) / "label").rglob("*location_J.txt"))) == 0:
info(f"*location_J.txt Files not Exist in the Directory.")
self.textBrowser_update(f"错误:无法进行<片段合并>")
self.msgBox.setText(f"目录下不存在*location_J.txt文件")
self.msgBox.setIcon(QMessageBox.Warning)
self.msgBox.exec()
return
final_Rpeak = append.Rpeak_Detection(self.lineEdit_rootpath.text(), int(dialog.lineEdit_fs.text()), int(dialog.lineEdit_th1.text()))
pd.DataFrame(final_Rpeak).to_csv(Path(self.lineEdit_rootpath.text()) / "final_Rpeak.txt", index=False, header=None)
info(f"Saved final_Rpeak to Directory {self.lineEdit_rootpath.text()}.")
self.textBrowser_update(f"提示保存final_Rpeak.txt成功至文件夹{self.lineEdit_rootpath.text()}")
self.msgBox.setText(f"保存成功至{self.lineEdit_rootpath.text()}")
self.msgBox.setIcon(QMessageBox.Information)
self.msgBox.exec()
else:
self.textBrowser_update("提示:操作取消")
2025-02-10 19:14:14 +08:00
def slot_btn_outputLabel(self):
np.savetxt(Path(self.lineEdit_savepath.text()), self.label2, fmt='%d', newline='\n')
info(f"Manually Saved Data to: {str(Path(self.lineEdit_savepath.text()))}.")
self.textBrowser_update(f"操作:手动保存数据至{str(Path(self.lineEdit_savepath.text()))}")
def data_preprocess(self, data, n, f1, f2, fs):
f1 = f1 / (fs / 2.0)
f2 = f2 / (fs / 2.0)
b, a = butter(n, [f1, f2], btype = 'bandpass')
data = np.array(filtfilt(b, a, data))
return data
def update_tableWidget_and_info(self):
self.tableWidget_label2.setRowCount(self.label2.__len__())
for row, value in enumerate(self.label2):
item = QTableWidgetItem(str(value).strip())
self.tableWidget_label2.setItem(row, 0, item)
self.groupBox_labelDisplay.setEnabled(True)
self.label_label2_length.setText(str(len(self.label2)))
def textBrowser_update(self, message):
self.textBrowser_infoOutput.append(str(datetime.now().strftime("%H:%M:%S")) + ": " + message)
2025-02-21 19:12:56 +08:00
self.textBrowser_infoOutput.verticalScrollBar().setValue(self.textBrowser_infoOutput.verticalScrollBar().maximum())
2025-02-10 19:14:14 +08:00
def autoplay_move_xlim(self):
if self.autoplay_mode == "left" and self.autoplay_xlim_start < 0:
self.autoplay_mode = "pause"
self.timer_autoplay.stop()
info("Paused Autoplay.")
self.textBrowser_update("操作:暂停自动播放")
elif self.autoplay_mode == "right" and self.autoplay_xlim_end > self.data2.__len__():
self.autoplay_mode = "pause"
self.timer_autoplay.stop()
info("Paused Autoplay.")
self.textBrowser_update("操作:暂停自动播放")
else:
if self.autoplay_mode == "right":
self.autoplay_xlim_start += self.autoplay_moveLength
self.autoplay_xlim_end += self.autoplay_moveLength
elif self.autoplay_mode == "left":
self.autoplay_xlim_start -= self.autoplay_moveLength
self.autoplay_xlim_end -= self.autoplay_moveLength
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
self.canvas.draw()
def plot_data_and_label(self, ax_top=True, ax_bottom=True, ax_left=True, ax_right=True):
self.ax0 = self.figure.add_subplot(self.gs[0])
self.ax0.plot(self.data1, label="data1", color='b')
self.ax0.plot(self.label1, self.points_y_1, 'ro', label='label1')
self.ax0 = plt.gca()
self.ax0.grid(True)
self.ax0.spines["top"].set_visible(ax_top)
self.ax0.spines["right"].set_visible(ax_right)
self.ax0.spines["bottom"].set_visible(ax_bottom)
self.ax0.spines["left"].set_visible(ax_left)
self.ax0.tick_params(axis='x', colors='white')
self.ax0.xaxis.set_major_formatter(FuncFormatter(lambda x, p: f"{x:.0f}"))
self.ax1 = self.figure.add_subplot(self.gs[1], sharex=self.ax0, sharey=self.ax0)
self.line_data2, = self.ax1.plot(self.data2, label="data2", color='b')
self.point_label2, = self.ax1.plot(self.label2, self.points_y_2, 'ro', label='label2')
self.ax1 = plt.gca()
self.ax1.grid(True)
self.ax1.spines["top"].set_visible(ax_top)
self.ax1.spines["right"].set_visible(ax_right)
self.ax1.spines["bottom"].set_visible(ax_bottom)
self.ax1.spines["left"].set_visible(ax_left)
self.ax0.autoscale(False)
self.ax0.callbacks.connect('xlim_changed', lambda ax: self.on_xlim_change(ax))
def toggle_home(self):
if self.timer_autoplay.isActive() == True:
self.autoplay_mode = "pause"
self.timer_autoplay.stop()
info("Paused Autoplay.")
self.textBrowser_update("操作:暂停自动播放")
self.ax0.autoscale(True)
self.ax0.relim()
self.ax0.autoscale_view()
self.canvas.draw()
self.ax0.autoscale(False)
self.textBrowser_update("操作:尺度恢复")
def toggle_changeLabel_Single_mode(self, state):
if state:
self.deactivate_figToolbar_buttons()
self.figToolbar.action_Label_Single.setChecked(True)
self.figToolbar.action_Label_Multiple.setChecked(False)
self.figToolbar.cid_mouse_press = self.canvas.mpl_connect('button_press_event', self.on_click)
self.figToolbar.cid_mouse_release = self.canvas.mpl_connect('button_release_event', self.on_release)
else:
if self.figToolbar.cid_mouse_press is not None:
self.canvas.mpl_disconnect(self.figToolbar.cid_mouse_press)
self.figToolbar.cid_mouse_press = None
if self.figToolbar.cid_mouse_release is not None:
self.canvas.mpl_disconnect(self.figToolbar.cid_mouse_release)
self.figToolbar.cid_mouse_release = None
def toggle_changeLabel_Multiple_mode(self, state):
if state:
self.deactivate_figToolbar_buttons()
self.figToolbar.action_Label_Single.setChecked(False)
self.figToolbar.action_Label_Multiple.setChecked(True)
self.figToolbar.cid_mouse_press = self.canvas.mpl_connect('button_press_event', self.on_click)
self.figToolbar.cid_mouse_release = self.canvas.mpl_connect('button_release_event', self.on_release)
self.figToolbar.cid_mouse_hold = self.canvas.mpl_connect('motion_notify_event', self.on_hold)
else:
if self.figToolbar.cid_mouse_press is not None:
self.canvas.mpl_disconnect(self.figToolbar.cid_mouse_press)
self.figToolbar.cid_mouse_press = None
if self.figToolbar.cid_mouse_release is not None:
self.canvas.mpl_disconnect(self.figToolbar.cid_mouse_release)
self.figToolbar.cid_mouse_release = None
if self.figToolbar.cid_mouse_hold:
self.canvas.mpl_disconnect(self.figToolbar.cid_mouse_hold)
self.figToolbar.cid_mouse_hold = None
def deactivate_figToolbar_buttons(self):
for action in self.figToolbar._actions.values():
if action.isChecked() == True:
if action == self.figToolbar._actions['pan']:
self.figToolbar.pan()
if action == self.figToolbar._actions['zoom']:
self.figToolbar.zoom()
def on_click(self, event):
if self.figToolbar.action_Label_Single.isChecked():
if event.button == 1:
self.is_left_button_pressed = True
self.add_temp_point(event)
elif event.button == 3:
self.is_right_button_pressed = True
self.remove_temp_point(event)
elif self.figToolbar.action_Label_Multiple.isChecked():
if event.button == 1 or event.button == 3: # 左键或右键
if event.button == 1:
self.is_left_button_pressed = True
elif event.button == 3:
self.is_right_button_pressed = True
self.figToolbar.rect_start_x = event.xdata
# 如果矩形patch已存在先移除
if self.figToolbar.rect_patch is not None:
self.figToolbar.rect_patch.remove()
self.figToolbar.rect_patch = None
self.canvas.draw()
def on_release(self, event):
if self.figToolbar.action_Label_Single.isChecked():
if event.button == 1 and self.is_left_button_pressed:
self.is_left_button_pressed = False
if self.temp_point:
self.label2 = np.append(self.label2, self.temp_point[0])
self.points_y_2 = np.append(self.points_y_2, self.temp_point[1])
info(f"Added point: ({str(self.temp_point[0])},{str(self.temp_point[1])}).")
self.textBrowser_update(f"操作:新增点:({str(self.temp_point[0])},{str(self.temp_point[1])})")
self.temp_point = None
self.redraw_plot()
elif event.button == 3 and self.is_right_button_pressed:
self.is_right_button_pressed = False
if self.temp_point:
distances = np.abs(np.array(self.label2) - self.temp_point[0])
if len(distances) > 0:
idx = distances.argmin()
info(f"Removed point {idx + 1}: ({str(self.label2[idx])},{str(self.points_y_2[idx])}).")
self.textBrowser_update(f"操作:删除第{idx + 1}点:({str(self.label2[idx])},{str(self.points_y_2[idx])})")
self.label2 = np.delete(self.label2, idx)
self.points_y_2 = np.delete(self.points_y_2, idx)
self.temp_point = None
self.redraw_plot()
self.label2.sort()
self.points_y_2 = [self.data2[x] for x in self.label2]
self.update_tableWidget_and_info()
np.savetxt(Path(self.lineEdit_savepath.text()), self.label2, fmt='%d', newline='\n')
elif self.figToolbar.action_Label_Multiple.isChecked():
if self.figToolbar.rect_start_x is not None:
self.figToolbar.rect_end_x = event.xdata
if self.figToolbar.rect_start_x is not None and self.figToolbar.rect_end_x is not None:
if self.figToolbar.rect_start_x < self.figToolbar.rect_end_x:
rect_left = self.figToolbar.rect_start_x
rect_right = self.figToolbar.rect_end_x
elif self.figToolbar.rect_start_x > self.figToolbar.rect_end_x:
rect_left = self.figToolbar.rect_end_x
rect_right = self.figToolbar.rect_start_x
else:
rect_left = self.figToolbar.rect_start_x
rect_right = self.figToolbar.rect_start_x
else:
rect_left = self.figToolbar.rect_start_x
rect_right = self.figToolbar.rect_start_x
if event.button == 1 and self.is_left_button_pressed:
self.is_left_button_pressed = False
if rect_left < 0:
rect_left = 0
if rect_right >= len(self.data2):
rect_right = len(self.data2) - 1
selected_area_for_add_points = self.data2[int(rect_left):int(rect_right)]
peaks_idx, _ = find_peaks(selected_area_for_add_points, height=float(self.lineEdit_findpeaks_min_height.text()), distance=float(self.lineEdit_findpeaks_min_interval.text()))
peaks_idx = peaks_idx + int(rect_left)
if len(peaks_idx) != 0:
info(f"Added {len(peaks_idx)} points.")
self.textBrowser_update(f"操作:新增{len(peaks_idx)}个点")
else:
info(f"No point added in selected area.")
self.textBrowser_update(f"操作:所选区间内无新增点")
self.label2 = np.append(self.label2, peaks_idx)
self.points_y_2 = np.append(self.points_y_2, self.data2[peaks_idx])
self.redraw_plot()
elif event.button == 3 and self.is_right_button_pressed:
self.is_right_button_pressed = False
left_label2_to_delete = self.label2 - rect_left
right_label2_to_delete = self.label2 - rect_right
self.left_label2_to_delete_idx = len(left_label2_to_delete[left_label2_to_delete < 0])
self.right_label2_to_delete_idx = len(right_label2_to_delete[right_label2_to_delete < 0])
if self.left_label2_to_delete_idx != self.right_label2_to_delete_idx:
info(f"Removed points from {self.left_label2_to_delete_idx + 1} to {self.right_label2_to_delete_idx}.")
self.textBrowser_update(f"操作:删除第{self.left_label2_to_delete_idx + 1}{self.right_label2_to_delete_idx}")
else:
info(f"No point to delete in selected area.")
self.textBrowser_update(f"操作:所选区间内无删除点")
self.label2 = np.delete(self.label2, np.arange(self.left_label2_to_delete_idx, self.right_label2_to_delete_idx))
self.points_y_2 = np.delete(self.points_y_2, np.arange(self.left_label2_to_delete_idx, self.right_label2_to_delete_idx))
self.redraw_plot()
self.figToolbar.rect_start_x = None
self.figToolbar.rect_end_x = None
self.label2.sort()
self.points_y_2 = [self.data2[x] for x in self.label2]
self.update_tableWidget_and_info()
np.savetxt(Path(self.lineEdit_savepath.text()), self.label2, fmt='%d', newline='\n')
# 移除矩形patch
if self.figToolbar.rect_patch is not None:
self.figToolbar.rect_patch.remove()
self.figToolbar.rect_patch = None
self.canvas.draw()
def on_hold(self, event):
if self.figToolbar.rect_start_x is not None and event.xdata is not None:
self.figToolbar.rect_end_x = event.xdata
# 如果矩形patch不存在则创建一个新的
if self.figToolbar.rect_patch is None:
if self.is_left_button_pressed:
self.figToolbar.rect_patch = plt.Rectangle((0, 0), 1, 1, fill=True, alpha=0.2, color='#ff00ff')
elif self.is_right_button_pressed:
self.figToolbar.rect_patch = plt.Rectangle((0, 0), 1, 1, fill=True, alpha=0.2, color='r')
self.ax1.add_patch(self.figToolbar.rect_patch)
# 更新矩形patch的位置和大小
x_start = self.figToolbar.rect_start_x
x_end = self.figToolbar.rect_end_x
y_min, y_max = self.ax1.get_ylim()
self.figToolbar.rect_patch.set_xy((min(x_start, x_end), y_min))
self.figToolbar.rect_patch.set_width(abs(x_end - x_start))
self.figToolbar.rect_patch.set_height(y_max - y_min)
self.canvas.draw()
def on_motion(self, event):
if event.inaxes:
# Clear previous reference lines and temporary points
for line in self.ax0.lines[1:]:
if line.get_label() == 'vline' or line.get_label() == 'hline' or line.get_label() == 'temp_point':
line.remove()
for line in self.ax1.lines[1:]:
if line.get_label() == 'vline' or line.get_label() == 'hline' or line.get_label() == 'temp_point':
line.remove()
# Draw vertical and horizontal reference lines
self.ax0.axvline(event.xdata, color='gray', linestyle='--', label='vline')
self.ax0.axhline(event.ydata, color='gray', linestyle='--', label='hline')
self.ax1.axvline(event.xdata, color='gray', linestyle='--', label='vline')
self.ax1.axhline(event.ydata, color='gray', linestyle='--', label='hline')
# Draw temporary point if left button is pressed
if self.is_left_button_pressed:
self.add_temp_point(event)
elif self.is_right_button_pressed:
self.remove_temp_point(event)
self.canvas.draw()
def add_temp_point(self, event):
if self.figToolbar.action_Label_Single.isChecked():
# Find the closest x value on the curve
idx = np.abs(np.arange(len(self.data2)) - event.xdata).argmin()
x_point = np.arange(len(self.data2))[idx]
y_point = self.data2[idx]
# Store the temporary point
self.temp_point = (x_point, y_point)
# Plot the temporary point
self.ax1.plot(x_point, y_point, marker='o', color='#ff00ff', label='temp_point')
self.ax1.plot(x_point, y_point, marker='x', color='#ff00ff', markersize=30, label='temp_point')
def remove_temp_point(self, event):
if self.figToolbar.action_Label_Single.isChecked():
if self.label2.any():
# Find the closest point to the current x coordinate
distances = np.abs(np.array(self.label2) - event.xdata)
idx = distances.argmin()
x_point = self.label2[idx]
y_point = self.points_y_2[idx]
# Store the temporary point to be removed
self.temp_point = (x_point, y_point)
# Plot the temporary point to be removed
self.ax1.plot(x_point, y_point, marker='x', color='r', markersize=30, label='temp_point')
def redraw_plot(self):
self.point_label2.remove()
self.point_label2, = self.ax1.plot(self.label2, self.points_y_2, 'ro', label='label2')
self.canvas.draw()
def on_xlim_change(self, event_ax):
try:
if self.annotation_tableWidget:
self.annotation_tableWidget.remove()
except AttributeError:
pass
self.annotation_tableWidget = None
self.canvas.draw()
class CustomNavigationToolbar(NavigationToolbar2QT):
def __init__(self, canvas, parent):
super().__init__(canvas, parent)
# 初始化画框工具栏
self.action_Label_Single = QAction('逐一更改标签(Z)', self)
self.action_Label_Single.setFont(QFont("黑体", 14))
self.action_Label_Single.setCheckable(True)
self.action_Label_Single.setShortcut(QCoreApplication.translate("MainWindow", "Z"))
self.action_Label_Multiple = QAction('批量更改标签(X)', self)
self.action_Label_Multiple.setFont(QFont("黑体", 14))
self.action_Label_Multiple.setCheckable(True)
self.action_Label_Multiple.setShortcut(QCoreApplication.translate("MainWindow", "X"))
self.insertAction(self._actions['pan'], self.action_Label_Single)
self.insertAction(self._actions['pan'], self.action_Label_Multiple)
self._actions['pan'].setShortcut(QCoreApplication.translate("MainWindow", "C"))
# 用于存储事件连接ID
self.cid_mouse_press = None
self.cid_mouse_release = None
self.cid_mouse_hold = None
# 初始化矩形选择区域
self.rect_start_x = None
self.rect_end_x = None
self.rect_patch = None # 用于绘制矩形的patch
def home(self, *args):
pass
def zoom(self, *args):
super().zoom(*args)
self.deactivate_figToorbar_changeLabel_mode()
def pan(self, *args):
super().pan(*args)
self.deactivate_figToorbar_changeLabel_mode()
def deactivate_figToorbar_changeLabel_mode(self):
if self.action_Label_Single.isChecked():
self.action_Label_Single.setChecked(False)
if self.cid_mouse_press is not None:
self.canvas.mpl_disconnect(self.cid_mouse_press)
self.cid_mouse_press = None
if self.cid_mouse_release is not None:
self.canvas.mpl_disconnect(self.cid_mouse_release)
self.cid_mouse_release = None
elif self.action_Label_Multiple.isChecked():
self.action_Label_Multiple.setChecked(False)
if self.cid_mouse_press is not None:
self.canvas.mpl_disconnect(self.cid_mouse_press)
self.cid_mouse_press = None
if self.cid_mouse_release is not None:
self.canvas.mpl_disconnect(self.cid_mouse_release)
self.cid_mouse_release = None
if self.cid_mouse_hold is not None:
self.canvas.mpl_disconnect(self.cid_mouse_hold)
self.cid_mouse_hold = None
class CustomMessageBox(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.resize(300, 300)
self.setWindowTitle("警告:确认操作")
layout = QVBoxLayout()
self.label = QLabel("是否执行<片段合并>?请在执行前确保此份数据的所有片段都已被打标!请输入相应参数后执行任务。")
self.label1 = QLabel(" ")
self.label_fs = QLabel("信号采样率(Hz)")
self.label_th1 = QLabel("寻峰阈值(个)")
self.lineEdit_fs = QLineEdit()
self.lineEdit_th1 = QLineEdit()
font = QtGui.QFont()
font.setFamily("黑体")
font.setPointSize(14)
self.label.setFont(font)
self.label1.setFont(font)
self.label_fs.setFont(font)
self.label_th1.setFont(font)
self.lineEdit_fs.setFont(font)
self.lineEdit_th1.setFont(font)
self.label.setWordWrap(True)
self.label.setFixedWidth(300)
self.lineEdit_fs.setText("1000")
self.lineEdit_th1.setText("130")
layout.addWidget(self.label)
layout.addWidget(self.label1)
layout.addWidget(self.label_fs)
layout.addWidget(self.lineEdit_fs)
layout.addWidget(self.label_th1)
layout.addWidget(self.lineEdit_th1)
self.button_box = QDialogButtonBox(QDialogButtonBox.Yes | QDialogButtonBox.No)
self.button_box.setFont(font)
self.button_box.accepted.connect(self.accept)
self.button_box.rejected.connect(self.reject)
layout.addWidget(self.button_box)
self.setLayout(layout)
2025-02-10 19:14:14 +08:00
# 主函数
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())