1171 lines
62 KiB
Python
1171 lines
62 KiB
Python
"""
|
||
@author:Yosa
|
||
@file:bcg_quality_label.py
|
||
@email:2023025086@m.scnu.edu.cn
|
||
@time:2025/2/11
|
||
"""
|
||
|
||
import sys
|
||
from logging import NOTSET, getLogger, FileHandler, Formatter, StreamHandler, info, error, debug
|
||
from time import time, strftime, localtime
|
||
|
||
import numpy as np
|
||
from pandas import DataFrame, read_csv
|
||
from matplotlib.ticker import FuncFormatter
|
||
from numpy import nan
|
||
from matplotlib import use
|
||
from matplotlib import pyplot as plt
|
||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
from PyQt5.QtCore import QCoreApplication
|
||
from PyQt5.QtWidgets import QFileDialog, QMainWindow, QMessageBox, QButtonGroup, QApplication, QTableWidgetItem, QTableWidget
|
||
from scipy import signal
|
||
|
||
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("--------bcg_quality_label.py--------")
|
||
|
||
class MainWindow(QMainWindow, Ui_MainWindow):
|
||
|
||
# 全局变量初始化
|
||
data = np.array([])
|
||
data = data.astype(np.float64)
|
||
artifact = np.array([])
|
||
artifact = artifact.astype(np.int64)
|
||
last_data_idx = -1
|
||
current_data_idx = 0
|
||
data_part_num = 0
|
||
current_part_num = 1
|
||
artifact_number = np.array([])
|
||
artifact_number = artifact_number.astype(np.int64)
|
||
artifact_type = np.array([])
|
||
artifact_type = artifact_type.astype(np.int64)
|
||
artifact_mask = np.array([])
|
||
artifact_mask = artifact_mask.astype(np.int64)
|
||
longest_continuous_time = 0
|
||
artifact_time_percentage = 0
|
||
label = np.array([])
|
||
label = label.astype(np.str_)
|
||
|
||
# 程序初始化操作
|
||
def __init__(self):
|
||
super(MainWindow, self).__init__()
|
||
self.setupUi(self)
|
||
|
||
# 设置画框
|
||
self.figure = plt.figure(figsize=(12, 6), dpi=150)
|
||
self.ax0 = self.figure.add_subplot(111)
|
||
self.ax0.xaxis.set_major_formatter(FuncFormatter(lambda x, p: f"{x:.0f}"))
|
||
self.canvas = FigureCanvasQTAgg(self.figure)
|
||
self.figToolbar = NavigationToolbar2QT(self.canvas)
|
||
self.verticalLayout_canvas.addWidget(self.canvas)
|
||
self.verticalLayout_canvas.addWidget(self.figToolbar)
|
||
|
||
# 画框子图初始化
|
||
plt.margins(0, 0)
|
||
plt.tight_layout()
|
||
|
||
# 界面状态初始化
|
||
self.radioButton_inputMode_auto.setChecked(True)
|
||
self.lineEdit_rootpath.setEnabled(False)
|
||
self.lineEdit_datapath.setEnabled(False)
|
||
self.lineEdit_artifactpath.setEnabled(False)
|
||
self.lineEdit_savepath.setEnabled(False)
|
||
self.lineEdit_current_part_time.setEnabled(False)
|
||
self.lineEdit_data_part_num.setEnabled(False)
|
||
self.lineEdit_longest_continuous_time.setEnabled(False)
|
||
self.lineEdit_artifact_time_percentage.setEnabled(False)
|
||
self.pushButton_datapath_open.setEnabled(False)
|
||
self.pushButton_artifactpath_open.setEnabled(False)
|
||
self.pushButton_savepath_open.setEnabled(False)
|
||
self.groupBox_artifact_type.setEnabled(False)
|
||
self.groupBox_status.setEnabled(False)
|
||
self.groupBox_function.setEnabled(False)
|
||
self.groupBox_operation.setEnabled(False)
|
||
self.groupBox_labelDisplay_10s.setVisible(False)
|
||
self.groupBox_labelDisplay_30s.setVisible(False)
|
||
self.checkBox_highlight_longest_continuous.setChecked(True)
|
||
|
||
# 初始化按钮快捷键
|
||
self.pushButton_left.setShortcut(QCoreApplication.translate("MainWindow", "A"))
|
||
self.pushButton_right.setShortcut(QCoreApplication.translate("MainWindow", "D"))
|
||
|
||
# 设置表格属性
|
||
self.tableWidget_label10s_a.setHorizontalHeaderLabels(['a'])
|
||
self.tableWidget_label10s_b.setHorizontalHeaderLabels(['b'])
|
||
self.tableWidget_label10s_c.setHorizontalHeaderLabels(['c'])
|
||
self.tableWidget_label10s_tobeLabeled.setHorizontalHeaderLabels(['未打标'])
|
||
self.tableWidget_label30s_a1.setHorizontalHeaderLabels(['a1'])
|
||
self.tableWidget_label30s_a2.setHorizontalHeaderLabels(['a2'])
|
||
self.tableWidget_label30s_b1.setHorizontalHeaderLabels(['b1'])
|
||
self.tableWidget_label30s_b2.setHorizontalHeaderLabels(['b2'])
|
||
self.tableWidget_label30s_c.setHorizontalHeaderLabels(['c'])
|
||
self.tableWidget_label30s_tobeLabeled.setHorizontalHeaderLabels(['未打标'])
|
||
self.tableWidget_label10s_a.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label10s_b.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label10s_c.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label10s_tobeLabeled.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label30s_a1.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label30s_a2.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label30s_b1.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label30s_b2.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label30s_c.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label30s_tobeLabeled.setEditTriggers(QTableWidget.NoEditTriggers)
|
||
self.tableWidget_label10s_a.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label10s_a.horizontalHeader().setSectionResizeMode(1)
|
||
self.tableWidget_label10s_b.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label10s_b.horizontalHeader().setSectionResizeMode(1)
|
||
self.tableWidget_label10s_c.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label10s_c.horizontalHeader().setSectionResizeMode(1)
|
||
self.tableWidget_label10s_tobeLabeled.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label10s_tobeLabeled.horizontalHeader().setSectionResizeMode(1)
|
||
self.tableWidget_label30s_a1.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label30s_a1.horizontalHeader().setSectionResizeMode(1)
|
||
self.tableWidget_label30s_a2.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label30s_a2.horizontalHeader().setSectionResizeMode(1)
|
||
self.tableWidget_label30s_b1.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label30s_b1.horizontalHeader().setSectionResizeMode(1)
|
||
self.tableWidget_label30s_b2.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label30s_b2.horizontalHeader().setSectionResizeMode(1)
|
||
self.tableWidget_label30s_c.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label30s_c.horizontalHeader().setSectionResizeMode(1)
|
||
self.tableWidget_label30s_tobeLabeled.horizontalHeader().setStretchLastSection(True)
|
||
self.tableWidget_label30s_tobeLabeled.horizontalHeader().setSectionResizeMode(1)
|
||
|
||
# 单选框组件分组
|
||
self.buttonGroup_displayMode = QButtonGroup()
|
||
self.buttonGroup_displayMode.addButton(self.radioButton_10s_mode)
|
||
self.buttonGroup_displayMode.addButton(self.radioButton_30s_mode)
|
||
|
||
# 槽函数连接控件初始化
|
||
self.pushButton_rootpath_open.clicked.connect(self.slot_btn_selectPath)
|
||
self.pushButton_datapath_open.clicked.connect(self.slot_btn_selectPath)
|
||
self.pushButton_artifactpath_open.clicked.connect(self.slot_btn_selectPath)
|
||
self.pushButton_savepath_open.clicked.connect(self.slot_btn_selectPath)
|
||
self.pushButton_dataInput.clicked.connect(self.slot_btn_dataInput)
|
||
self.radioButton_inputMode_auto.clicked.connect(self.slot_radioBtn_inputMode_auto)
|
||
self.radioButton_inputMode_manual.clicked.connect(self.slot_radioBtn_inputMode_manual)
|
||
self.checkBox_allin.clicked.connect(self.slot_checkBox_allin)
|
||
self.checkBox_type1.clicked.connect(self.slot_checkBox_type1)
|
||
self.checkBox_type2.clicked.connect(self.slot_checkBox_type2)
|
||
self.checkBox_type3.clicked.connect(self.slot_checkBox_type3)
|
||
self.checkBox_type4.clicked.connect(self.slot_checkBox_type4)
|
||
self.checkBox_type5.clicked.connect(self.slot_checkBox_type5)
|
||
self.pushButton_left.clicked.connect(self.slot_btn_left)
|
||
self.pushButton_right.clicked.connect(self.slot_btn_right)
|
||
self.pushButton_label10s_a.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_label10s_b.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_label10s_c.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_label10s_f.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_label30s_a1.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_label30s_a2.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_label30s_b1.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_label30s_b2.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_label30s_c.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_label30s_f.clicked.connect(self.slot_btn_label)
|
||
self.pushButton_invalid_signal_label.clicked.connect(self.slot_btn_invalid_signal_label)
|
||
self.pushButton_Ctype_signal_label.clicked.connect(self.slot_btn_Ctype_signal_label)
|
||
self.checkBox_highlight_longest_continuous.clicked.connect(self.slot_checkBox_highlight_longest_continuous)
|
||
self.checkBox_display_afterfilter.clicked.connect(self.slot_checkBox_display_afterfilter)
|
||
self.checkBox_examine_tobeLabeled.clicked.connect(self.slot_checkBox_examine_tobeLabeled)
|
||
self.tableWidget_label10s_a.cellDoubleClicked.connect(self.slot_tableWidget_label10s_a_on_cell_double_clicked)
|
||
self.tableWidget_label10s_b.cellDoubleClicked.connect(self.slot_tableWidget_label10s_b_on_cell_double_clicked)
|
||
self.tableWidget_label10s_c.cellDoubleClicked.connect(self.slot_tableWidget_label10s_c_on_cell_double_clicked)
|
||
self.tableWidget_label10s_tobeLabeled.cellDoubleClicked.connect(self.slot_tableWidget_label10s_tobeLabeled_on_cell_double_clicked)
|
||
self.tableWidget_label30s_a1.cellDoubleClicked.connect(self.slot_tableWidget_label30s_a1_on_cell_double_clicked)
|
||
self.tableWidget_label30s_a2.cellDoubleClicked.connect(self.slot_tableWidget_label30s_a2_on_cell_double_clicked)
|
||
self.tableWidget_label30s_b1.cellDoubleClicked.connect(self.slot_tableWidget_label30s_b1_on_cell_double_clicked)
|
||
self.tableWidget_label30s_b2.cellDoubleClicked.connect(self.slot_tableWidget_label30s_b2_on_cell_double_clicked)
|
||
self.tableWidget_label30s_c.cellDoubleClicked.connect(self.slot_tableWidget_label30s_c_on_cell_double_clicked)
|
||
self.tableWidget_label30s_tobeLabeled.cellDoubleClicked.connect(self.slot_tableWidget_label30s_tobeLabeled_on_cell_double_clicked)
|
||
|
||
# 消息弹窗初始化
|
||
self.msgBox = QMessageBox()
|
||
self.msgBox.setWindowTitle("消息")
|
||
|
||
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_artifact_Path = file_path / "Align"
|
||
data_path = self.data_and_artifact_Path / "BCG_sync.txt"
|
||
artifact_path = self.data_and_artifact_Path / "Artifact_a.txt"
|
||
|
||
# 检查路径下的BCG_sync.txt和Artifact_a.txt文件是否存在
|
||
if self.data_and_artifact_Path.exists() and data_path.exists() and artifact_path.exists():
|
||
# 更新数据路径文本框
|
||
self.lineEdit_datapath.setText(str(data_path))
|
||
self.lineEdit_artifactpath.setText(str(artifact_path))
|
||
self.lineEdit_savepath.setText(str(self.data_and_artifact_Path))
|
||
|
||
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)))
|
||
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_datapath_open:
|
||
self.lineEdit_datapath.setText(file_path)
|
||
elif self.sender() == self.pushButton_artifactpath_open:
|
||
self.lineEdit_artifactpath.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_datapath.text() != "" or self.lineEdit_artifactpath.text() != "" or self.lineEdit_savepath.text() != "") and (self.radioButton_30s_mode.isChecked() == True or self.radioButton_10s_mode.isChecked() == True):
|
||
info("Inputing Data...")
|
||
self.textBrowser_update("提示:开始导入数据")
|
||
|
||
# 导入数据
|
||
self.artifact = np.array([])
|
||
file = open(str(self.lineEdit_datapath.text()), 'r')
|
||
self.data = file.readlines()
|
||
self.data = list(map(float, self.data))
|
||
|
||
self.data_without_industrialFrequencyNoise = self.wipe_industrialFrequencyNoise(self.data, 1000)
|
||
file = open(str(self.lineEdit_artifactpath.text()), 'r')
|
||
self.artifact = np.array(file.readlines())
|
||
self.data = np.array(self.data)
|
||
self.data = self.data.astype(np.float64)
|
||
self.data_without_industrialFrequencyNoise = np.array([self.data_without_industrialFrequencyNoise])
|
||
self.data_without_industrialFrequencyNoise = self.data_without_industrialFrequencyNoise.astype(np.float64)[0]
|
||
self.artifact = self.artifact.astype(np.int64)
|
||
|
||
# 获取信号的段数,检查数据长度正确性
|
||
if self.radioButton_10s_mode.isChecked():
|
||
self.data_part_num = len(self.data) // 10000
|
||
self.groupBox_labelDisplay_10s.setVisible(True)
|
||
self.lineEdit_savepath.setText(str(Path(self.lineEdit_savepath.text()) / "SQ_label_10s.csv"))
|
||
elif self.radioButton_30s_mode.isChecked():
|
||
self.data_part_num = len(self.data) // 30000
|
||
self.groupBox_labelDisplay_30s.setVisible(True)
|
||
self.lineEdit_savepath.setText(str(Path(self.lineEdit_savepath.text()) / "SQ_label_30s.csv"))
|
||
if self.data_part_num == 0:
|
||
info("Failed to Input Data!")
|
||
self.textBrowser_update("操作:导入数据失败,请检查数据长度")
|
||
self.msgBox.setText("导入失败,请检查数据长度")
|
||
self.msgBox.setIcon(QMessageBox.Critical)
|
||
self.msgBox.exec()
|
||
return
|
||
|
||
# 检查体动标签正确性
|
||
if len(self.artifact) % 4 == 0:
|
||
for i in range(1, len(self.artifact), 4):
|
||
if self.artifact[i] not in [1, 2, 3, 4, 5]:
|
||
info(f"Failed to Input Artifact! Error in Artifact[{i}] not in [1, 2, 3, 4, 5].")
|
||
self.textBrowser_update("操作:导入体动失败,请检查体动标签格式")
|
||
self.msgBox.setText("导入失败,请检查体动标签格式")
|
||
self.msgBox.setIcon(QMessageBox.Critical)
|
||
self.msgBox.exec()
|
||
return
|
||
else:
|
||
info("Failed to Input Artifact!")
|
||
self.textBrowser_update("操作:导入体动失败,请检查体动长度是否为4的倍数")
|
||
self.msgBox.setText("导入失败,请检查体动长度是否为4的倍数")
|
||
self.msgBox.setIcon(QMessageBox.Critical)
|
||
self.msgBox.exec()
|
||
return
|
||
|
||
# 定义绘制体动所需要的数组
|
||
artifact_start = np.array([])
|
||
artifact_start = artifact_start.astype(np.int64)
|
||
artifact_end = np.array([])
|
||
artifact_end = artifact_end.astype(np.int64)
|
||
for i in range(0, len(self.artifact), 4):
|
||
self.artifact_number = np.append(self.artifact_number, self.artifact[i])
|
||
for i in range(1, len(self.artifact), 4):
|
||
self.artifact_type = np.append(self.artifact_type, self.artifact[i])
|
||
for i in range(2, len(self.artifact), 4):
|
||
artifact_start = np.append(artifact_start, self.artifact[i])
|
||
for i in range(3, len(self.artifact), 4):
|
||
artifact_end = np.append(artifact_end, self.artifact[i])
|
||
self.artifact_mask = np.zeros(len(self.data))
|
||
for i in range(0, len(self.artifact_number)):
|
||
if self.artifact_type[i] == 1:
|
||
self.artifact_mask[artifact_start[i]: artifact_end[i] + 1] = 1
|
||
elif self.artifact_type[i] == 2:
|
||
self.artifact_mask[artifact_start[i]: artifact_end[i] + 1] = 2
|
||
elif self.artifact_type[i] == 3:
|
||
self.artifact_mask[artifact_start[i]: artifact_end[i] + 1] = 3
|
||
elif self.artifact_type[i] == 4:
|
||
self.artifact_mask[artifact_start[i]: artifact_end[i] + 1] = 4
|
||
elif self.artifact_type[i] == 5:
|
||
self.artifact_mask[artifact_start[i]: artifact_end[i] + 1] = 5
|
||
|
||
# 尝试获取之前打标的存档,若不存在存档,则创建新存档
|
||
if self.radioButton_10s_mode.isChecked() == True:
|
||
self.pushButton_Ctype_signal_label.setEnabled(True)
|
||
elif self.radioButton_30s_mode.isChecked() == True:
|
||
self.pushButton_Ctype_signal_label.setEnabled(False)
|
||
if not Path(self.lineEdit_savepath.text()).exists():
|
||
info("Not Found History Archive csv File, Made new csv File.")
|
||
self.textBrowser_update("提示:未找到历史存档csv文件,创建新的csv文件")
|
||
self.label = np.full(self.data_part_num, "f")
|
||
self.df_label = DataFrame(columns=["label", "remark"])
|
||
self.df_label["label"] = self.label
|
||
self.df_label["remark"] = ""
|
||
self.df_label["label"] = self.df_label["label"].astype(str)
|
||
self.df_label["remark"] = self.df_label["remark"].astype(str)
|
||
else:
|
||
info("Found History Archive csv File, Loaded History Archive csv File.")
|
||
self.textBrowser_update("提示:找到历史存档csv文件,载入历史存档csv文件")
|
||
self.df_label = read_csv(self.lineEdit_savepath.text(), encoding="gbk")
|
||
self.label = self.df_label["label"].astype(str)
|
||
self.df_label.to_csv(self.lineEdit_savepath.text(), index=False, encoding="gbk")
|
||
self.lineEdit_savepath.setText(str(self.lineEdit_savepath.text()))
|
||
|
||
# 界面状态更新
|
||
self.groupBox_inputSetting.setEnabled(False)
|
||
self.groupBox_artifact_type.setEnabled(True)
|
||
self.groupBox_status.setEnabled(True)
|
||
self.groupBox_function.setEnabled(True)
|
||
self.groupBox_operation.setEnabled(True)
|
||
MainWindow.setWindowTitle(self, QCoreApplication.translate("MainWindow",
|
||
"BCG_Quality_Label - Data Path: " + self.lineEdit_rootpath.text()))
|
||
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
self.update_tableWidget()
|
||
|
||
info("Finished Input Data.")
|
||
self.textBrowser_update("提示:导入数据完成")
|
||
elif self.radioButton_30s_mode.isChecked() == False and self.radioButton_10s_mode.isChecked() == False:
|
||
info("Failed to Input Data!")
|
||
self.textBrowser_update("操作:导入数据失败")
|
||
self.msgBox.setText("导入失败,请选择显示模式")
|
||
self.msgBox.setIcon(QMessageBox.Critical)
|
||
self.msgBox.exec()
|
||
else:
|
||
info("Failed to Input Data!")
|
||
self.textBrowser_update("操作:导入数据失败")
|
||
self.msgBox.setText("导入失败,请正确输入路径")
|
||
self.msgBox.setIcon(QMessageBox.Critical)
|
||
self.msgBox.exec()
|
||
|
||
def slot_radioBtn_inputMode_auto(self):
|
||
self.pushButton_rootpath_open.setEnabled(True)
|
||
self.pushButton_datapath_open.setEnabled(False)
|
||
self.pushButton_artifactpath_open.setEnabled(False)
|
||
self.pushButton_savepath_open.setEnabled(False)
|
||
|
||
def slot_radioBtn_inputMode_manual(self):
|
||
self.pushButton_rootpath_open.setEnabled(False)
|
||
self.pushButton_datapath_open.setEnabled(True)
|
||
self.pushButton_artifactpath_open.setEnabled(True)
|
||
self.pushButton_savepath_open.setEnabled(True)
|
||
|
||
def slot_btn_left(self):
|
||
if self.current_part_num == 1:
|
||
info(f"Viewing the First Part.")
|
||
self.msgBox.setText("你正在查看第1段信号")
|
||
self.msgBox.setIcon(QMessageBox.Information)
|
||
self.msgBox.exec()
|
||
else:
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num -= 1
|
||
while self.checkBox_examine_tobeLabeled.isChecked() == True and self.df_label.at[self.current_part_num - 1, "label"] != "f":
|
||
self.current_part_num -= 1
|
||
if self.current_part_num == 0:
|
||
self.current_part_num = 1
|
||
info(f"All Parts of Left are Labeled, Jumped to the First Part.")
|
||
self.msgBox.setText("前面的片段都被打标,将跳转至第1段信号")
|
||
self.msgBox.setIcon(QMessageBox.Information)
|
||
self.msgBox.exec()
|
||
break
|
||
if self.radioButton_10s_mode.isChecked() == True:
|
||
self.current_data_idx -= 10000
|
||
elif self.radioButton_30s_mode.isChecked() == True:
|
||
self.current_data_idx -= 30000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Viewing the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:上一段信号,第{self.current_part_num}段")
|
||
|
||
def slot_btn_right(self):
|
||
if self.current_part_num == self.data_part_num:
|
||
info(f"Viewing the Last Part.")
|
||
self.msgBox.setText("你正在查看最后1段信号")
|
||
self.msgBox.setIcon(QMessageBox.Information)
|
||
self.msgBox.exec()
|
||
else:
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num += 1
|
||
while self.checkBox_examine_tobeLabeled.isChecked() == True and self.df_label.at[self.current_part_num - 1, "label"] != "f":
|
||
self.current_part_num += 1
|
||
if self.current_part_num == self.data_part_num + 1:
|
||
self.current_part_num = self.data_part_num
|
||
info(f"All Parts of Right are Labeled, Jumped to the Last Part.")
|
||
self.msgBox.setText("后面的片段都被打标,将跳转至最后1段信号")
|
||
self.msgBox.setIcon(QMessageBox.Information)
|
||
self.msgBox.exec()
|
||
break
|
||
if self.radioButton_10s_mode.isChecked() == True:
|
||
self.current_data_idx += 10000
|
||
elif self.radioButton_30s_mode.isChecked() == True:
|
||
self.current_data_idx += 30000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Viewing the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:下一段信号,第{self.current_part_num}段")
|
||
|
||
def slot_checkBox_allin(self):
|
||
if self.checkBox_allin.isChecked() == True:
|
||
self.checkBox_type1.setChecked(True)
|
||
self.checkBox_type2.setChecked(True)
|
||
self.checkBox_type3.setChecked(True)
|
||
self.checkBox_type4.setChecked(True)
|
||
self.checkBox_type5.setChecked(True)
|
||
else:
|
||
self.checkBox_type1.setChecked(False)
|
||
self.checkBox_type2.setChecked(False)
|
||
self.checkBox_type3.setChecked(False)
|
||
self.checkBox_type4.setChecked(False)
|
||
self.checkBox_type5.setChecked(False)
|
||
self.plot_data_and_artifact()
|
||
|
||
def slot_checkBox_type1(self):
|
||
if self.checkBox_type1.isChecked() == False:
|
||
self.checkBox_allin.setChecked(False)
|
||
self.plot_data_and_artifact()
|
||
if self.checkBox_type1.isChecked() == True and self.checkBox_type2.isChecked() == True and self.checkBox_type3.isChecked() == True and self.checkBox_type4.isChecked() == True and self.checkBox_type5.isChecked() == True:
|
||
self.checkBox_allin.setChecked(True)
|
||
|
||
def slot_checkBox_type2(self):
|
||
if self.checkBox_type2.isChecked() == False:
|
||
self.checkBox_allin.setChecked(False)
|
||
self.plot_data_and_artifact()
|
||
if self.checkBox_type1.isChecked() == True and self.checkBox_type2.isChecked() == True and self.checkBox_type3.isChecked() == True and self.checkBox_type4.isChecked() == True and self.checkBox_type5.isChecked() == True:
|
||
self.checkBox_allin.setChecked(True)
|
||
|
||
def slot_checkBox_type3(self):
|
||
if self.checkBox_type3.isChecked() == False:
|
||
self.checkBox_allin.setChecked(False)
|
||
self.plot_data_and_artifact()
|
||
if self.checkBox_type1.isChecked() == True and self.checkBox_type2.isChecked() == True and self.checkBox_type3.isChecked() == True and self.checkBox_type4.isChecked() == True and self.checkBox_type5.isChecked() == True:
|
||
self.checkBox_allin.setChecked(True)
|
||
|
||
def slot_checkBox_type4(self):
|
||
if self.checkBox_type4.isChecked() == False:
|
||
self.checkBox_allin.setChecked(False)
|
||
self.plot_data_and_artifact()
|
||
if self.checkBox_type1.isChecked() == True and self.checkBox_type2.isChecked() == True and self.checkBox_type3.isChecked() == True and self.checkBox_type4.isChecked() == True and self.checkBox_type5.isChecked() == True:
|
||
self.checkBox_allin.setChecked(True)
|
||
|
||
def slot_checkBox_type5(self):
|
||
if self.checkBox_type5.isChecked() == False:
|
||
self.checkBox_allin.setChecked(False)
|
||
self.plot_data_and_artifact()
|
||
if self.checkBox_type1.isChecked() == True and self.checkBox_type2.isChecked() == True and self.checkBox_type3.isChecked() == True and self.checkBox_type4.isChecked() == True and self.checkBox_type5.isChecked() == True:
|
||
self.checkBox_allin.setChecked(True)
|
||
|
||
def slot_checkBox_highlight_longest_continuous(self):
|
||
self.plot_data_and_artifact()
|
||
info("Clicked checkBox_highlight_longest_continuous.")
|
||
self.textBrowser_update("操作:点击了高亮最长连续")
|
||
|
||
def slot_checkBox_display_afterfilter(self):
|
||
self.plot_data_and_artifact()
|
||
info("Clicked checkBox_display_afterfilter.")
|
||
self.msgBox.setText("操作:点击了去除工频噪声")
|
||
|
||
def slot_checkBox_examine_tobeLabeled(self):
|
||
info("Clicked checkBox_examine_tobeLabeled.")
|
||
self.msgBox.setText("操作:点击了仅查未标片段")
|
||
|
||
def wipe_industrialFrequencyNoise(self, data, fs):
|
||
# 设计带阻滤波器(Notch Filter)来滤除49-51Hz的噪声
|
||
nyq = 0.5 * fs # 奈奎斯特频率
|
||
low = 49 / nyq
|
||
high = 51 / nyq
|
||
b, a = signal.iirfilter(4, [low, high], btype='bandstop', ftype='butter') # 4阶巴特沃斯带阻滤波器
|
||
return signal.lfilter(b, a, data)
|
||
|
||
def update_status(self):
|
||
if self.radioButton_10s_mode.isChecked() == True:
|
||
hour = int(((self.current_data_idx + 10000) / 1000) // 3600)
|
||
min = int((((self.current_data_idx + 10000) / 1000) % 3600) // 60)
|
||
sec = int((((self.current_data_idx + 10000) / 1000) % 3600) % 60)
|
||
elif self.radioButton_30s_mode.isChecked() == True:
|
||
hour = int(((self.current_data_idx + 30000) / 1000) // 3600)
|
||
min = int((((self.current_data_idx + 30000) / 1000) % 3600) // 60)
|
||
sec = int((((self.current_data_idx + 30000) / 1000) % 3600) % 60)
|
||
self.lineEdit_current_part_time.setText(str(hour) + "时" + str(min) + "分" + str(sec) + "秒")
|
||
self.lineEdit_data_part_num.setText(str(self.current_part_num) + "/" + str(self.data_part_num))
|
||
|
||
# 更新表格
|
||
def update_tableWidget(self):
|
||
if self.radioButton_10s_mode.isChecked() == True:
|
||
label_a = np.where(self.label == "a")[0] + 1
|
||
label_b = np.where(self.label == "b")[0] + 1
|
||
label_c = np.where(self.label == "c")[0] + 1
|
||
label_tobeLabeled = np.where(self.label == "f")[0] + 1
|
||
|
||
self.tableWidget_label10s_a.setRowCount(label_a.__len__())
|
||
self.tableWidget_label10s_b.setRowCount(label_b.__len__())
|
||
self.tableWidget_label10s_c.setRowCount(label_c.__len__())
|
||
self.tableWidget_label10s_tobeLabeled.setRowCount(label_tobeLabeled.__len__())
|
||
|
||
for row, value in enumerate(label_a):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label10s_a.setItem(row, 0, item)
|
||
for row, value in enumerate(label_b):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label10s_b.setItem(row, 0, item)
|
||
for row, value in enumerate(label_c):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label10s_c.setItem(row, 0, item)
|
||
for row, value in enumerate(label_tobeLabeled):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label10s_tobeLabeled.setItem(row, 0, item)
|
||
|
||
self.tableWidget_label10s_a.verticalScrollBar().setValue(self.tableWidget_label10s_a.verticalScrollBar().maximum())
|
||
self.tableWidget_label10s_b.verticalScrollBar().setValue(self.tableWidget_label10s_b.verticalScrollBar().maximum())
|
||
self.tableWidget_label10s_c.verticalScrollBar().setValue(self.tableWidget_label10s_c.verticalScrollBar().maximum())
|
||
|
||
elif self.radioButton_30s_mode.isChecked() == True:
|
||
label_a1 = np.where(self.label == "a")[0] + 1
|
||
label_a2 = np.where(self.label == "b")[0] + 1
|
||
label_b1 = np.where(self.label == "c")[0] + 1
|
||
label_b2 = np.where(self.label == "d")[0] + 1
|
||
label_c = np.where(self.label == "e")[0] + 1
|
||
label_tobeLabeled = np.where(self.label == "f")[0] + 1
|
||
|
||
self.tableWidget_label30s_a1.setRowCount(label_a1.__len__())
|
||
self.tableWidget_label30s_a2.setRowCount(label_a2.__len__())
|
||
self.tableWidget_label30s_b1.setRowCount(label_b1.__len__())
|
||
self.tableWidget_label30s_b2.setRowCount(label_b2.__len__())
|
||
self.tableWidget_label30s_c.setRowCount(label_c.__len__())
|
||
self.tableWidget_label30s_tobeLabeled.setRowCount(label_tobeLabeled.__len__())
|
||
|
||
for row, value in enumerate(label_a1):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label30s_a1.setItem(row, 0, item)
|
||
for row, value in enumerate(label_a2):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label30s_a2.setItem(row, 0, item)
|
||
for row, value in enumerate(label_b1):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label30s_b1.setItem(row, 0, item)
|
||
for row, value in enumerate(label_b2):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label30s_b2.setItem(row, 0, item)
|
||
for row, value in enumerate(label_c):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label30s_c.setItem(row, 0, item)
|
||
for row, value in enumerate(label_tobeLabeled):
|
||
item = QTableWidgetItem(str(value).strip())
|
||
self.tableWidget_label30s_tobeLabeled.setItem(row, 0, item)
|
||
|
||
self.tableWidget_label30s_a1.verticalScrollBar().setValue(self.tableWidget_label30s_a1.verticalScrollBar().maximum())
|
||
self.tableWidget_label30s_a2.verticalScrollBar().setValue(self.tableWidget_label30s_a2.verticalScrollBar().maximum())
|
||
self.tableWidget_label30s_b1.verticalScrollBar().setValue(self.tableWidget_label30s_b1.verticalScrollBar().maximum())
|
||
self.tableWidget_label30s_b2.verticalScrollBar().setValue(self.tableWidget_label30s_b2.verticalScrollBar().maximum())
|
||
self.tableWidget_label30s_c.verticalScrollBar().setValue(self.tableWidget_label30s_c.verticalScrollBar().maximum())
|
||
|
||
def slot_tableWidget_label10s_a_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label10s_a.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 10000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_tableWidget_label10s_b_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label10s_b.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 10000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_tableWidget_label10s_c_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label10s_c.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 10000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_tableWidget_label10s_tobeLabeled_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label10s_tobeLabeled.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 10000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_tableWidget_label30s_a1_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label30s_a1.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 30000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_tableWidget_label30s_a2_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label30s_a2.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 30000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_tableWidget_label30s_b1_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label30s_b1.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 30000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_tableWidget_label30s_b2_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label30s_b2.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 30000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_tableWidget_label30s_c_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label30s_c.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 30000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_tableWidget_label30s_tobeLabeled_on_cell_double_clicked(self, row, column):
|
||
self.last_data_idx = self.current_data_idx
|
||
self.current_part_num = int(self.tableWidget_label30s_tobeLabeled.item(row, column).text())
|
||
self.current_data_idx = (self.current_part_num - 1) * 30000
|
||
|
||
# 更新备注内容
|
||
if not str(self.df_label.at[self.current_part_num - 1, "remark"]) == "nan":
|
||
self.lineEdit_remark.setText(str(self.df_label.at[self.current_part_num - 1, "remark"]))
|
||
else:
|
||
self.lineEdit_remark.setText("")
|
||
|
||
# 更新按钮颜色
|
||
self.change_labelBtn_color()
|
||
|
||
if (self.df_label["label"] != "f").all():
|
||
self.textBrowser_update(f"提示:该份数据打标已全部完成")
|
||
self.update_status()
|
||
self.plot_data_and_artifact()
|
||
info(f"Jumped to the {self.current_part_num} Part.")
|
||
self.textBrowser_update(f"操作:跳转到目标片段,第{self.current_part_num}段")
|
||
|
||
def slot_btn_label(self):
|
||
if self.sender() == self.pushButton_label10s_a:
|
||
self.label[self.current_part_num - 1] = "a"
|
||
if self.sender() == self.pushButton_label10s_b:
|
||
self.label[self.current_part_num - 1] = "b"
|
||
if self.sender() == self.pushButton_label10s_c:
|
||
self.label[self.current_part_num - 1] = "c"
|
||
if self.sender() == self.pushButton_label10s_f:
|
||
self.label[self.current_part_num - 1] = "f"
|
||
if self.sender() == self.pushButton_label30s_a1:
|
||
self.label[self.current_part_num - 1] = "a"
|
||
if self.sender() == self.pushButton_label30s_a2:
|
||
self.label[self.current_part_num - 1] = "b"
|
||
if self.sender() == self.pushButton_label30s_b1:
|
||
self.label[self.current_part_num - 1] = "c"
|
||
if self.sender() == self.pushButton_label30s_b2:
|
||
self.label[self.current_part_num - 1] = "d"
|
||
if self.sender() == self.pushButton_label30s_c:
|
||
self.label[self.current_part_num - 1] = "e"
|
||
if self.sender() == self.pushButton_label30s_f:
|
||
self.label[self.current_part_num - 1] = "f"
|
||
self.df_label["label"] = self.label
|
||
self.df_label.at[self.current_part_num - 1, "remark"] = self.lineEdit_remark.text()
|
||
self.df_label.to_csv(self.lineEdit_savepath.text(), index=False, encoding="gbk")
|
||
self.slot_btn_right()
|
||
self.update_tableWidget()
|
||
|
||
def slot_btn_invalid_signal_label(self):
|
||
info(f"Asked whether Label All Parts to Type C.")
|
||
self.textBrowser_update(f"警告:询问是否将所有片段标记为类型C")
|
||
reply = QMessageBox.question(self, "警告:确认操作", "你确定要将所有片段标记为类型C吗?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
|
||
if reply == QMessageBox.Yes:
|
||
if self.radioButton_10s_mode.isChecked() == True:
|
||
self.label = np.full(self.label.shape, "c", dtype="str")
|
||
elif self.radioButton_30s_mode.isChecked() == True:
|
||
self.label = np.full(self.label.shape, "e", dtype="str")
|
||
self.df_label["label"] = self.label
|
||
self.df_label.to_csv(self.lineEdit_savepath.text(), index=False, encoding="gbk")
|
||
self.update_tableWidget()
|
||
info(f"Labeled All Parts to Type C.")
|
||
self.textBrowser_update(f"操作:已将所有片段标记为类型C")
|
||
self.msgBox.setText("已将所有片段标记为类型C")
|
||
self.msgBox.setIcon(QMessageBox.Information)
|
||
self.msgBox.exec()
|
||
else:
|
||
info(f"Operation Canceled.")
|
||
self.textBrowser_update(f"提示:操作已取消")
|
||
|
||
def slot_btn_Ctype_signal_label(self):
|
||
info(f"Asked whether Label All Parts with Artifact to Type C.")
|
||
self.textBrowser_update(f"警告:询问是否将所有带有体动的片段标记为类型C")
|
||
reply = QMessageBox.question(self, "警告:确认操作", "你确定要将所有片段标记为类型C吗?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
|
||
if reply == QMessageBox.Yes:
|
||
artifact_mask = self.artifact_mask[:10000 * int(len(self.data) // 10000)]
|
||
sub_artifact_mask = np.split(artifact_mask, len(artifact_mask) // 10000)
|
||
for index, array in enumerate(sub_artifact_mask):
|
||
if 1 in array or 2 in array or 3 in array or 4 in array or 5 in array:
|
||
self.label[index] = "c"
|
||
self.df_label["label"] = self.label
|
||
self.df_label.to_csv(self.lineEdit_savepath.text(), index=False, encoding="gbk")
|
||
self.update_tableWidget()
|
||
info(f"Labeled Parts With Artifact to Type C.")
|
||
self.textBrowser_update(f"操作:已将所有带有体动的片段标记为类型C")
|
||
self.msgBox.setText("已将所有带有体动的片段标记为类型C")
|
||
self.msgBox.setIcon(QMessageBox.Information)
|
||
self.msgBox.exec()
|
||
else:
|
||
info(f"Operation Canceled.")
|
||
self.textBrowser_update(f"提示:操作已取消")
|
||
|
||
def plot_data_and_artifact(self):
|
||
self.ax0.clear()
|
||
artifact_type_seq = np.array([])
|
||
artifact_type_seq = artifact_type_seq.astype(np.int64)
|
||
if self.checkBox_type1.isChecked():
|
||
artifact_type_seq = np.append(artifact_type_seq, 1)
|
||
if self.checkBox_type2.isChecked():
|
||
artifact_type_seq = np.append(artifact_type_seq, 2)
|
||
if self.checkBox_type3.isChecked():
|
||
artifact_type_seq = np.append(artifact_type_seq, 3)
|
||
if self.checkBox_type4.isChecked():
|
||
artifact_type_seq = np.append(artifact_type_seq, 4)
|
||
if self.checkBox_type5.isChecked():
|
||
artifact_type_seq = np.append(artifact_type_seq, 5)
|
||
|
||
# 是否显示去除工频噪声
|
||
if self.checkBox_display_afterfilter.isChecked():
|
||
display_data = self.data_without_industrialFrequencyNoise
|
||
else:
|
||
display_data = self.data
|
||
|
||
# 绘制数据和体动
|
||
if self.radioButton_10s_mode.isChecked() == True:
|
||
mask = np.array([np.arange(10000), np.arange(10000), np.arange(10000), np.arange(10000), np.arange(10000), np.arange(10000)])
|
||
mask = mask.astype('float')
|
||
if self.current_data_idx != self.last_data_idx:
|
||
self.data_plot, = self.ax0.plot(np.arange(self.current_data_idx, self.current_data_idx + 10000), display_data[self.current_data_idx: self.current_data_idx + 10000], label="bcg_data", color='r')
|
||
for i in artifact_type_seq:
|
||
mask[i] = self.artifact_mask[self.current_data_idx: self.current_data_idx + 10000] == i
|
||
mask[i] = (display_data[self.current_data_idx: self.current_data_idx + 10000] * mask[i]).astype('float')
|
||
np.place(mask[i], mask[i] == 0, nan)
|
||
self.artifact_plot, = self.ax0.plot(np.arange(self.current_data_idx, self.current_data_idx + 10000), mask[i], color='g', linestyle="-")
|
||
|
||
isArtifact = mask[~np.all(mask == range(0, 10000), axis=1)]
|
||
isArtifact = ~np.isnan(isArtifact).all(axis=0)
|
||
|
||
# 计算最长连续时间并更新信息
|
||
longest_continuous_max_length = 0
|
||
longest_continuous_last_length = 0
|
||
longest_continuous_current_length = 0
|
||
longest_continuous_start = 0
|
||
longest_continuous_end = 0
|
||
for index, value in enumerate(isArtifact):
|
||
if value == False:
|
||
longest_continuous_current_length += 1
|
||
if longest_continuous_current_length > longest_continuous_max_length:
|
||
longest_continuous_end = index
|
||
longest_continuous_max_length = max(longest_continuous_max_length, longest_continuous_current_length)
|
||
else:
|
||
longest_continuous_current_length = 0
|
||
longest_continuous_start = longest_continuous_end - longest_continuous_max_length + 1
|
||
if self.checkBox_highlight_longest_continuous.isChecked():
|
||
self.longest_continuous_plot, = self.ax0.plot(np.arange(self.current_data_idx + longest_continuous_start, self.current_data_idx + longest_continuous_end), display_data[self.current_data_idx + longest_continuous_start: self.current_data_idx + longest_continuous_end], color='m', linestyle="-", zorder=3)
|
||
self.lineEdit_longest_continuous_time.setText(str(round(longest_continuous_max_length / 1000, 2)) + "秒")
|
||
|
||
# 计算体动时间占比并更新信息
|
||
self.lineEdit_artifact_time_percentage.setText(str(round(100 * np.count_nonzero(isArtifact) / len(isArtifact), 2)) + "%")
|
||
|
||
elif self.radioButton_30s_mode.isChecked() == True:
|
||
mask = np.array([np.arange(30000), np.arange(30000), np.arange(30000), np.arange(30000), np.arange(30000), np.arange(30000)])
|
||
mask = mask.astype('float')
|
||
if self.current_data_idx != self.last_data_idx:
|
||
self.data_plot, = self.ax0.plot(np.arange(self.current_data_idx, self.current_data_idx + 30000), display_data[self.current_data_idx: self.current_data_idx + 30000], label="bcg_data", color='r')
|
||
for i in artifact_type_seq:
|
||
mask[i] = self.artifact_mask[self.current_data_idx: self.current_data_idx + 30000] == i
|
||
mask[i] = (display_data[self.current_data_idx: self.current_data_idx + 30000] * mask[i]).astype('float')
|
||
np.place(mask[i], mask[i] == 0, nan)
|
||
self.artifact_plot, = self.ax0.plot(np.arange(self.current_data_idx, self.current_data_idx + 30000), mask[i], color='g', linestyle="-")
|
||
|
||
isArtifact = mask[~np.all(mask == range(0, 30000), axis=1)]
|
||
isArtifact = ~np.isnan(isArtifact).all(axis=0)
|
||
|
||
# 计算最长连续时间并更新信息
|
||
longest_continuous_max_length = 0
|
||
longest_continuous_last_length = 0
|
||
longest_continuous_current_length = 0
|
||
longest_continuous_start = 0
|
||
longest_continuous_end = 0
|
||
for index, value in enumerate(isArtifact):
|
||
if value == False:
|
||
longest_continuous_current_length += 1
|
||
if longest_continuous_current_length > longest_continuous_max_length:
|
||
longest_continuous_end = index
|
||
longest_continuous_max_length = max(longest_continuous_max_length, longest_continuous_current_length)
|
||
else:
|
||
longest_continuous_current_length = 0
|
||
longest_continuous_start = longest_continuous_end - longest_continuous_max_length + 1
|
||
if self.checkBox_highlight_longest_continuous.isChecked():
|
||
self.longest_continuous_plot, = self.ax0.plot(np.arange(self.current_data_idx + longest_continuous_start, self.current_data_idx + longest_continuous_end), display_data[self.current_data_idx+ longest_continuous_start: self.current_data_idx + longest_continuous_end], color='m', linestyle="-", zorder=3)
|
||
self.lineEdit_longest_continuous_time.setText(str(round(longest_continuous_max_length / 1000, 2)) + "秒")
|
||
|
||
# 计算体动时间占比并更新信息
|
||
self.lineEdit_artifact_time_percentage.setText(str(round(100 * np.count_nonzero(isArtifact) / len(isArtifact), 2)) + "%")
|
||
self.ax0.grid(True)
|
||
self.canvas.draw()
|
||
|
||
def change_labelBtn_color(self):
|
||
if self.df_label.at[self.current_part_num - 1, "label"] == "a":
|
||
self.pushButton_label10s_a.setStyleSheet("""
|
||
QPushButton {
|
||
background-color: orange; /* 设置背景颜色 */
|
||
padding: 10px; /* 设置内边距 */
|
||
border: 2px solid darkblue; /* 设置边框 */
|
||
border-radius: 10px; /* 设置圆角 */
|
||
}
|
||
QPushButton:hover {
|
||
background-color: yellow; /* 鼠标悬停时的背景颜色 */
|
||
}""")
|
||
self.pushButton_label10s_b.setStyleSheet("")
|
||
self.pushButton_label10s_c.setStyleSheet("")
|
||
self.pushButton_label30s_a1.setStyleSheet("""
|
||
QPushButton {
|
||
background-color: orange; /* 设置背景颜色 */
|
||
padding: 10px; /* 设置内边距 */
|
||
border: 2px solid darkblue; /* 设置边框 */
|
||
border-radius: 10px; /* 设置圆角 */
|
||
}
|
||
QPushButton:hover {
|
||
background-color: yellow; /* 鼠标悬停时的背景颜色 */
|
||
}""")
|
||
self.pushButton_label30s_a2.setStyleSheet("")
|
||
self.pushButton_label30s_b1.setStyleSheet("")
|
||
self.pushButton_label30s_b2.setStyleSheet("")
|
||
self.pushButton_label30s_c.setStyleSheet("")
|
||
elif self.df_label.at[self.current_part_num - 1, "label"] == "b":
|
||
self.pushButton_label10s_a.setStyleSheet("")
|
||
self.pushButton_label10s_b.setStyleSheet("""
|
||
QPushButton {
|
||
background-color: orange; /* 设置背景颜色 */
|
||
padding: 10px; /* 设置内边距 */
|
||
border: 2px solid darkblue; /* 设置边框 */
|
||
border-radius: 10px; /* 设置圆角 */
|
||
}
|
||
QPushButton:hover {
|
||
background-color: yellow; /* 鼠标悬停时的背景颜色 */
|
||
}""")
|
||
self.pushButton_label10s_c.setStyleSheet("")
|
||
self.pushButton_label30s_a1.setStyleSheet("")
|
||
self.pushButton_label30s_a2.setStyleSheet("""
|
||
QPushButton {
|
||
background-color: orange; /* 设置背景颜色 */
|
||
padding: 10px; /* 设置内边距 */
|
||
border: 2px solid darkblue; /* 设置边框 */
|
||
border-radius: 10px; /* 设置圆角 */
|
||
}
|
||
QPushButton:hover {
|
||
background-color: yellow; /* 鼠标悬停时的背景颜色 */
|
||
}""")
|
||
self.pushButton_label30s_b1.setStyleSheet("")
|
||
self.pushButton_label30s_b2.setStyleSheet("")
|
||
self.pushButton_label30s_c.setStyleSheet("")
|
||
elif self.df_label.at[self.current_part_num - 1, "label"] == "c":
|
||
self.pushButton_label10s_a.setStyleSheet("")
|
||
self.pushButton_label10s_b.setStyleSheet("")
|
||
self.pushButton_label10s_c.setStyleSheet("""
|
||
QPushButton {
|
||
background-color: orange; /* 设置背景颜色 */
|
||
padding: 10px; /* 设置内边距 */
|
||
border: 2px solid darkblue; /* 设置边框 */
|
||
border-radius: 10px; /* 设置圆角 */
|
||
}
|
||
QPushButton:hover {
|
||
background-color: yellow; /* 鼠标悬停时的背景颜色 */
|
||
}""")
|
||
self.pushButton_label30s_a1.setStyleSheet("")
|
||
self.pushButton_label30s_a2.setStyleSheet("")
|
||
self.pushButton_label30s_b1.setStyleSheet("""
|
||
QPushButton {
|
||
background-color: orange; /* 设置背景颜色 */
|
||
padding: 10px; /* 设置内边距 */
|
||
border: 2px solid darkblue; /* 设置边框 */
|
||
border-radius: 10px; /* 设置圆角 */
|
||
}
|
||
QPushButton:hover {
|
||
background-color: yellow; /* 鼠标悬停时的背景颜色 */
|
||
}""")
|
||
self.pushButton_label30s_b2.setStyleSheet("")
|
||
self.pushButton_label30s_c.setStyleSheet("")
|
||
elif self.df_label.at[self.current_part_num - 1, "label"] == "d":
|
||
self.pushButton_label10s_a.setStyleSheet("")
|
||
self.pushButton_label10s_b.setStyleSheet("")
|
||
self.pushButton_label10s_c.setStyleSheet("")
|
||
self.pushButton_label30s_a1.setStyleSheet("")
|
||
self.pushButton_label30s_a2.setStyleSheet("")
|
||
self.pushButton_label30s_b1.setStyleSheet("")
|
||
self.pushButton_label30s_b2.setStyleSheet("""
|
||
QPushButton {
|
||
background-color: orange; /* 设置背景颜色 */
|
||
padding: 10px; /* 设置内边距 */
|
||
border: 2px solid darkblue; /* 设置边框 */
|
||
border-radius: 10px; /* 设置圆角 */
|
||
}
|
||
QPushButton:hover {
|
||
background-color: yellow; /* 鼠标悬停时的背景颜色 */
|
||
}""")
|
||
self.pushButton_label30s_c.setStyleSheet("")
|
||
elif self.df_label.at[self.current_part_num - 1, "label"] == "e":
|
||
self.pushButton_label10s_a.setStyleSheet("")
|
||
self.pushButton_label10s_b.setStyleSheet("")
|
||
self.pushButton_label10s_c.setStyleSheet("")
|
||
self.pushButton_label30s_a1.setStyleSheet("")
|
||
self.pushButton_label30s_a2.setStyleSheet("")
|
||
self.pushButton_label30s_b1.setStyleSheet("")
|
||
self.pushButton_label30s_b2.setStyleSheet("")
|
||
self.pushButton_label30s_c.setStyleSheet("""
|
||
QPushButton {
|
||
background-color: orange; /* 设置背景颜色 */
|
||
padding: 10px; /* 设置内边距 */
|
||
border: 2px solid darkblue; /* 设置边框 */
|
||
border-radius: 10px; /* 设置圆角 */
|
||
}
|
||
QPushButton:hover {
|
||
background-color: yellow; /* 鼠标悬停时的背景颜色 */
|
||
}""")
|
||
elif self.df_label.at[self.current_part_num - 1, "label"] == "f":
|
||
self.pushButton_label10s_a.setStyleSheet("")
|
||
self.pushButton_label10s_b.setStyleSheet("")
|
||
self.pushButton_label10s_c.setStyleSheet("")
|
||
self.pushButton_label30s_a1.setStyleSheet("")
|
||
self.pushButton_label30s_a2.setStyleSheet("")
|
||
self.pushButton_label30s_b1.setStyleSheet("")
|
||
self.pushButton_label30s_b2.setStyleSheet("")
|
||
self.pushButton_label30s_c.setStyleSheet("")
|
||
|
||
def textBrowser_update(self, message):
|
||
self.textBrowser_infoOutput.append(str(datetime.now().strftime("%H:%M:%S")) + ": " + message)
|
||
self.textBrowser_infoOutput.verticalScrollBar().setValue(self.textBrowser_infoOutput.verticalScrollBar().maximum())
|
||
|
||
# 主函数
|
||
if __name__ == '__main__':
|
||
app = QApplication(sys.argv)
|
||
mainWindow = MainWindow()
|
||
mainWindow.show()
|
||
sys.exit(app.exec_()) |