1、精简部分公共代码到PublicFunc.py中
2、完成了<人工纠正>的所有代码
This commit is contained in:
@ -54,3 +54,11 @@ def Butterworth_for_BCG_PreProcess(data, sample_rate, type, low_cut=0.0, high_cu
|
||||
return sosfiltfilt(sos, array(data))
|
||||
else: # 警告,滤波器类型必须有
|
||||
raise ValueError("Please choose a type of fliter")
|
||||
|
||||
def data_preprocess_for_label_check(data, n, f1, f2, fs):
|
||||
|
||||
f1 = f1 / (fs / 2.0)
|
||||
f2 = f2 / (fs / 2.0)
|
||||
b, a = butter(n, [f1, f2], btype="bandpass")
|
||||
data = array(filtfilt(b, a, data))
|
||||
return data
|
||||
@ -290,12 +290,11 @@ class MainWindow_detect_Jpeak(QMainWindow):
|
||||
# 清空模型列表
|
||||
self.ui.comboBox_model.clear()
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(1/2)" + Constants.DETECT_JPEAK_LOADING_MODEL))
|
||||
self.progressbar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
self.data = Data()
|
||||
self.model = Model()
|
||||
|
||||
# 寻找模型
|
||||
self.model = Model()
|
||||
PublicFunc.progressbar_update(self, 1, 2, Constants.DETECT_JPEAK_LOADING_MODEL, 0)
|
||||
status, info = self.model.seek_model()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(1/2)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -306,12 +305,8 @@ class MainWindow_detect_Jpeak(QMainWindow):
|
||||
PublicFunc.text_output(self.ui, "(1/2)" + info, Constants.TIPS_TYPE_INFO)
|
||||
self.update_ui_comboBox_model(self.model.model_list)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(2/2)" + Constants.INPUTTING_DATA))
|
||||
self.progressbar.setValue(10)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 导入数据
|
||||
self.data = Data()
|
||||
PublicFunc.progressbar_update(self, 2, 2, Constants.INPUTTING_DATA, 10)
|
||||
status, info = self.data.open_file()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(2/2)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -328,11 +323,8 @@ class MainWindow_detect_Jpeak(QMainWindow):
|
||||
|
||||
PublicFunc.__disableAllButton__(self, ButtonState)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(1/3)" + Constants.DETECT_JPEAK_PROCESSING_DATA))
|
||||
self.progressbar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 数据预处理
|
||||
PublicFunc.progressbar_update(self, 1, 3, Constants.DETECT_JPEAK_PROCESSING_DATA, 0)
|
||||
status, info = self.data.preprocess()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(1/3)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -342,11 +334,8 @@ class MainWindow_detect_Jpeak(QMainWindow):
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(1/3)" + info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(2/3)" + Constants.DETECT_JPEAK_PREDICTING_PEAK))
|
||||
self.progressbar.setValue(10)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 预测峰值
|
||||
PublicFunc.progressbar_update(self, 2, 3, Constants.DETECT_JPEAK_PREDICTING_PEAK, 10)
|
||||
self.model.selected_model = Config["DetectMethod"]
|
||||
status, info = self.data.predict_Jpeak(self.model)
|
||||
if not status:
|
||||
@ -364,11 +353,8 @@ class MainWindow_detect_Jpeak(QMainWindow):
|
||||
PublicFunc.text_output(self.ui, Constants.DETECT_JPEAK_PEAK_AMOUNT + str(len(self.data.peak)),
|
||||
Constants.TIPS_TYPE_INFO)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(3/3)" + Constants.DRAWING_DATA))
|
||||
self.progressbar.setValue(70)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 绘图
|
||||
PublicFunc.progressbar_update(self, 3, 3, Constants.DRAWING_DATA, 70)
|
||||
status, info = self.__plot__()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(3/3)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -390,11 +376,8 @@ class MainWindow_detect_Jpeak(QMainWindow):
|
||||
if reply == QMessageBox.Yes:
|
||||
PublicFunc.__disableAllButton__(self, ButtonState)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(1/1)" + Constants.SAVING_DATA))
|
||||
self.progressbar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 保存
|
||||
PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0)
|
||||
# status, info = self.data.save()
|
||||
total_rows = len(DataFrame(self.data.peak.reshape(-1)))
|
||||
chunk_size = ConfigParams.DETECT_JPEAK_SAVE_CHUNK_SIZE
|
||||
|
||||
@ -273,11 +273,12 @@ class MainWindow_detect_Rpeak(QMainWindow):
|
||||
PublicFunc.__disableAllButton__(self, ButtonState)
|
||||
|
||||
# 清空画框
|
||||
if self.line_data and self.point_peak and self.line_interval:
|
||||
if self.line_data and self.point_peak and self.line_interval and self.point_RRIV:
|
||||
try:
|
||||
self.line_data.remove()
|
||||
self.point_peak.remove()
|
||||
self.line_interval.remove()
|
||||
self.point_RRIV.remove()
|
||||
except ValueError:
|
||||
pass
|
||||
self.canvas.draw()
|
||||
@ -285,11 +286,11 @@ class MainWindow_detect_Rpeak(QMainWindow):
|
||||
# 清空方法列表
|
||||
self.ui.comboBox_method.clear()
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(1/2)" + Constants.DETECT_RPEAK_LOADING_METHOD))
|
||||
self.progressbar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
self.data = Data()
|
||||
|
||||
# 寻找方法
|
||||
PublicFunc.progressbar_update(self, 1, 2, Constants.DETECT_RPEAK_LOADING_METHOD, 0)
|
||||
# TODO:获取检测方法的解耦
|
||||
method_list = get_method()
|
||||
if len(method_list) == 0 or method_list is None:
|
||||
status = False
|
||||
@ -306,12 +307,8 @@ class MainWindow_detect_Rpeak(QMainWindow):
|
||||
PublicFunc.text_output(self.ui, "(1/2)" + info, Constants.TIPS_TYPE_INFO)
|
||||
self.update_ui_comboBox_method(method_list)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(2/2)" + Constants.INPUTTING_DATA))
|
||||
self.progressbar.setValue(10)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 导入数据
|
||||
self.data = Data()
|
||||
PublicFunc.progressbar_update(self, 2, 2, Constants.INPUTTING_DATA, 10)
|
||||
status, info = self.data.open_file()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(2/2)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -328,11 +325,8 @@ class MainWindow_detect_Rpeak(QMainWindow):
|
||||
|
||||
PublicFunc.__disableAllButton__(self, ButtonState)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(1/3)" + Constants.DETECT_RPEAK_PROCESSING_DATA))
|
||||
self.progressbar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 数据预处理
|
||||
PublicFunc.progressbar_update(self, 1, 3, Constants.DETECT_RPEAK_PROCESSING_DATA, 0)
|
||||
status, info = self.data.preprocess()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(1/3)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -342,11 +336,8 @@ class MainWindow_detect_Rpeak(QMainWindow):
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(1/3)" + info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(2/3)" + Constants.DETECT_RPEAK_PREDICTING_PEAK))
|
||||
self.progressbar.setValue(10)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 预测峰值
|
||||
PublicFunc.progressbar_update(self, 2, 3, Constants.DETECT_RPEAK_PREDICTING_PEAK, 10)
|
||||
status, info = self.data.predict_Rpeak()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(2/3)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -363,11 +354,8 @@ class MainWindow_detect_Rpeak(QMainWindow):
|
||||
PublicFunc.text_output(self.ui, Constants.DETECT_RPEAK_PEAK_AMOUNT + str(len(self.data.peak)),
|
||||
Constants.TIPS_TYPE_INFO)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(3/3)" + Constants.DRAWING_DATA))
|
||||
self.progressbar.setValue(70)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 绘图
|
||||
PublicFunc.progressbar_update(self, 3, 3, Constants.DRAWING_DATA, 70)
|
||||
status, info = self.__plot__()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(3/3)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -389,11 +377,8 @@ class MainWindow_detect_Rpeak(QMainWindow):
|
||||
if reply == QMessageBox.Yes:
|
||||
PublicFunc.__disableAllButton__(self, ButtonState)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(1/1)" + Constants.SAVING_DATA))
|
||||
self.progressbar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 保存
|
||||
PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0)
|
||||
# status, info = self.data.save()
|
||||
total_rows = len(DataFrame(self.data.peak.reshape(-1)))
|
||||
chunk_size = ConfigParams.DETECT_RPEAK_SAVE_CHUNK_SIZE
|
||||
|
||||
@ -2,17 +2,21 @@ from gc import collect
|
||||
from pathlib import Path
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from PySide6.QtWidgets import QMessageBox, QMainWindow, QApplication
|
||||
from matplotlib import gridspec
|
||||
from PySide6.QtCore import QTimer, QCoreApplication
|
||||
from PySide6.QtGui import QAction, QFont
|
||||
from PySide6.QtWidgets import QMessageBox, QMainWindow, QApplication, QTableWidgetItem, QTableWidget
|
||||
from matplotlib import gridspec, patches
|
||||
from matplotlib.backends.backend_qt import NavigationToolbar2QT
|
||||
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
|
||||
from numpy import append, delete, arange
|
||||
from overrides import overrides
|
||||
from pandas import read_csv, DataFrame
|
||||
from scipy.signal import resample
|
||||
from scipy.signal import find_peaks
|
||||
from yaml import dump, load, FullLoader
|
||||
|
||||
from func.utils.PublicFunc import PublicFunc
|
||||
from func.utils.Constants import Constants, ConfigParams
|
||||
from func.Filters.Preprocessing import data_preprocess_for_label_check
|
||||
|
||||
from ui.MainWindow.MainWindow_label_check import Ui_MainWindow_label_check
|
||||
from ui.setting.label_check_input_setting import Ui_MainWindow_label_check_input_setting
|
||||
@ -109,7 +113,7 @@ class SettingWindow(QMainWindow):
|
||||
"Mode": self.mode
|
||||
})
|
||||
else:
|
||||
raise ValueError
|
||||
raise ValueError("模式不存在")
|
||||
|
||||
# 数据回显
|
||||
self.ui.spinBox_input_freq_signal.setValue(Config["InputConfig"]["Freq"])
|
||||
@ -125,7 +129,7 @@ class SettingWindow(QMainWindow):
|
||||
self.ui.doubleSpinBox_bandPassLow.setValue(Config["Filter"]["ECGBandPassLow"])
|
||||
self.ui.doubleSpinBox_bandPassHigh.setValue(Config["Filter"]["ECGBandPassHigh"])
|
||||
else:
|
||||
raise ValueError
|
||||
raise ValueError("模式不存在")
|
||||
|
||||
def __write_config__(self):
|
||||
|
||||
@ -143,7 +147,7 @@ class SettingWindow(QMainWindow):
|
||||
Config["Filter"]["ECGBandPassLow"] = self.ui.doubleSpinBox_bandPassLow.value()
|
||||
Config["Filter"]["ECGBandPassHigh"] = self.ui.doubleSpinBox_bandPassHigh.value()
|
||||
else:
|
||||
raise ValueError
|
||||
raise ValueError("模式不存在")
|
||||
|
||||
# 保存配置到文件
|
||||
self.config["InputConfig"]["Freq"] = self.ui.spinBox_input_freq_signal.value()
|
||||
@ -176,7 +180,7 @@ class SettingWindow(QMainWindow):
|
||||
str(self.ui.spinBox_input_freq_signal.value()) +
|
||||
ConfigParams.ENDSWITH_TXT))))
|
||||
else:
|
||||
raise ValueError
|
||||
raise ValueError("模式不存在")
|
||||
|
||||
|
||||
class MainWindow_label_check(QMainWindow):
|
||||
@ -192,8 +196,6 @@ class MainWindow_label_check(QMainWindow):
|
||||
self.sampID = None
|
||||
|
||||
self.data = None
|
||||
self.original_peak = None
|
||||
self.corrected_peak = None
|
||||
|
||||
self.setting = None
|
||||
|
||||
@ -208,11 +210,28 @@ class MainWindow_label_check(QMainWindow):
|
||||
self.gs = None
|
||||
self.ax0 = None
|
||||
self.ax1 = None
|
||||
self.is_left_button_pressed = None
|
||||
self.is_right_button_pressed = None
|
||||
|
||||
self.line_processed_data_1 = None
|
||||
self.line_processed_data_2 = None
|
||||
self.point_peak_original = None
|
||||
self.point_peak_corrected = None
|
||||
self.annotation_tableWidget = None
|
||||
|
||||
# 初始化自动播放定时器
|
||||
self.autoplay_xlim_start = None
|
||||
self.autoplay_xlim_end = None
|
||||
self.timer_autoplay = QTimer()
|
||||
self.timer_autoplay.timeout.connect(self.autoplay_move_xlim)
|
||||
Config.update({
|
||||
"AutoplayArgs": {
|
||||
"AutoplayMode": "pause",
|
||||
"MoveLength": int(self.ui.label_moveLength_preset_1.text()),
|
||||
"MaxRange": int(self.ui.label_maxRange_preset_1.text()),
|
||||
"MoveSpeed": int(self.ui.label_moveSpeed_preset_1.text())
|
||||
}
|
||||
})
|
||||
|
||||
self.msgBox = QMessageBox()
|
||||
self.msgBox.setWindowTitle(Constants.MAINWINDOW_MSGBOX_TITLE)
|
||||
@ -230,10 +249,14 @@ class MainWindow_label_check(QMainWindow):
|
||||
# 初始化画框
|
||||
self.fig = plt.figure(figsize=(12, 9), dpi=100)
|
||||
self.canvas = FigureCanvasQTAgg(self.fig)
|
||||
self.figToolbar = NavigationToolbar2QT(self.canvas)
|
||||
self.figToolbar = CustomNavigationToolbar(self.canvas, self)
|
||||
for action in self.figToolbar._actions.values():
|
||||
action.setEnabled(False)
|
||||
for action in self.figToolbar.actions():
|
||||
if action.text() == "Subplots" or action.text() == "Customize":
|
||||
self.figToolbar.removeAction(action)
|
||||
self.figToolbar._actions['home'].triggered.connect(self.toggle_home)
|
||||
self.figToolbar.action_Label_Multiple.triggered.connect(self.toggle_changeLabel)
|
||||
self.ui.verticalLayout_canvas.addWidget(self.canvas)
|
||||
self.ui.verticalLayout_canvas.addWidget(self.figToolbar)
|
||||
self.gs = gridspec.GridSpec(2, 1, height_ratios=[1, 1])
|
||||
@ -242,17 +265,42 @@ class MainWindow_label_check(QMainWindow):
|
||||
self.ax0.grid(True)
|
||||
self.ax0.xaxis.set_major_formatter(ConfigParams.FORMATTER)
|
||||
self.ax0.tick_params(axis='x', colors=Constants.PLOT_COLOR_WHITE)
|
||||
self.ax1 = self.fig.add_subplot(self.gs[1])
|
||||
self.ax1 = self.fig.add_subplot(self.gs[1], sharex=self.ax0, sharey=self.ax0)
|
||||
self.ax1.grid(True)
|
||||
self.ax1.xaxis.set_major_formatter(ConfigParams.FORMATTER)
|
||||
|
||||
PublicFunc.__resetAllButton__(self, ButtonState)
|
||||
|
||||
self.ui.label_mode.setText(self.mode)
|
||||
self.ui.doubleSpinBox_findpeaks_min_interval.setValue(Config["FindPeaks"]["MinInterval"])
|
||||
self.ui.doubleSpinBox_findpeaks_min_height.setValue(Config["FindPeaks"]["MinHeight"])
|
||||
self.ui.spinBox_moveLength.setValue(Config["CustomAutoplayArgs"]["MoveLength"])
|
||||
self.ui.spinBox_maxRange.setValue(Config["CustomAutoplayArgs"]["MaxRange"])
|
||||
self.ui.spinBox_moveSpeed.setValue(Config["CustomAutoplayArgs"]["MoveSpeed"])
|
||||
|
||||
# self.ui.pushButton_input.clicked.connect(self.__slot_btn_input__)
|
||||
self.ui.tableWidget_peak_original.setHorizontalHeaderLabels(['Original'])
|
||||
self.ui.tableWidget_peak_corrected.setHorizontalHeaderLabels(['Corrected'])
|
||||
self.ui.tableWidget_peak_original.setEditTriggers(QTableWidget.NoEditTriggers)
|
||||
self.ui.tableWidget_peak_corrected.setEditTriggers(QTableWidget.NoEditTriggers)
|
||||
self.ui.tableWidget_peak_original.horizontalHeader().setStretchLastSection(True)
|
||||
self.ui.tableWidget_peak_corrected.horizontalHeader().setStretchLastSection(True)
|
||||
|
||||
self.ui.pushButton_input.clicked.connect(self.__slot_btn_input__)
|
||||
self.ui.pushButton_input_setting.clicked.connect(self.setting.show)
|
||||
# self.ui.pushButton_save.clicked.connect(self.__slot_btn_save__)
|
||||
self.ui.pushButton_save.clicked.connect(self.__slot_btn_save__)
|
||||
self.ui.pushButton_prev_move.clicked.connect(self.__slot_btn_move__)
|
||||
self.ui.pushButton_pause.clicked.connect(self.__slot_btn_move__)
|
||||
self.ui.pushButton_next_move.clicked.connect(self.__slot_btn_move__)
|
||||
self.ui.radioButton_move_preset_1.toggled.connect(self.__change_autoplay_args__)
|
||||
self.ui.radioButton_move_preset_2.toggled.connect(self.__change_autoplay_args__)
|
||||
self.ui.radioButton_move_preset_3.toggled.connect(self.__change_autoplay_args__)
|
||||
self.ui.radioButton_move_custom.toggled.connect(self.__change_autoplay_args__)
|
||||
self.ui.tableWidget_peak_original.cellDoubleClicked.connect(
|
||||
self.__slot_tableWidget_on_cell_double_clicked__)
|
||||
self.ui.tableWidget_peak_corrected.cellDoubleClicked.connect(
|
||||
self.__slot_tableWidget_on_cell_double_clicked__)
|
||||
|
||||
|
||||
self.ui.doubleSpinBox_findpeaks_min_interval.editingFinished.connect(self.__update_config__)
|
||||
self.ui.doubleSpinBox_findpeaks_min_height.editingFinished.connect(self.__update_config__)
|
||||
self.ui.spinBox_moveLength.editingFinished.connect(self.__update_config__)
|
||||
@ -304,18 +352,13 @@ class MainWindow_label_check(QMainWindow):
|
||||
sender = self.sender()
|
||||
|
||||
if sender == self.ui.pushButton_input:
|
||||
# self.point_RRIV, = self.ax0.plot(self.data.peak[2:], self.data.RRIV,
|
||||
# 'r.',
|
||||
# label=Constants.DETECT_RPEAK_PLOT_LABEL_RRIV)
|
||||
# self.line_data, = self.ax1.plot(self.data.processed_data,
|
||||
# color=Constants.PLOT_COLOR_BLUE,
|
||||
# label=Constants.DETECT_RPEAK_PLOT_LABEL_ECG)
|
||||
# self.point_peak, = self.ax1.plot(self.data.peak, self.data.processed_data[self.data.peak],
|
||||
# 'r*',
|
||||
# label=Constants.DETECT_RPEAK_PLOT_LABEL_R_PEAKS)
|
||||
# self.line_interval, = self.ax1.plot(self.data.interval,
|
||||
# color=Constants.PLOT_COLOR_GREEN,
|
||||
# label=Constants.DETECT_RPEAK_PLOT_LABEL_INTERVAL)
|
||||
self.ui.spinBox_data_length.setValue(len(self.data.processed_data))
|
||||
self.line_processed_data_1, = self.ax0.plot(self.data.processed_data,
|
||||
label=Constants.LABEL_CHECK_PLOT_LABEL_SIGNAL,
|
||||
color=Constants.PLOT_COLOR_BLUE)
|
||||
self.line_processed_data_2, = self.ax1.plot(self.data.processed_data,
|
||||
label=Constants.LABEL_CHECK_PLOT_LABEL_SIGNAL,
|
||||
color=Constants.PLOT_COLOR_BLUE)
|
||||
self.ax0.legend(loc=Constants.PLOT_UPPER_RIGHT)
|
||||
self.ax1.legend(loc=Constants.PLOT_UPPER_RIGHT)
|
||||
status = True
|
||||
@ -325,6 +368,54 @@ class MainWindow_label_check(QMainWindow):
|
||||
info = Constants.DRAWING_FAILURE
|
||||
|
||||
self.canvas.draw()
|
||||
self.ax0.autoscale(False)
|
||||
self.ax1.autoscale(False)
|
||||
return status, info
|
||||
|
||||
def __plot_peaks__(self):
|
||||
|
||||
try:
|
||||
self.point_peak_original, = self.ax0.plot(self.data.original_peak, self.data.original_peak_y, 'ro',
|
||||
label=Constants.LABEL_CHECK_PLOT_LABEL_PEAK_ORIGINAL)
|
||||
self.point_peak_corrected, = self.ax1.plot(self.data.corrected_peak, self.data.corrected_peak_y, 'ro',
|
||||
label=Constants.LABEL_CHECK_PLOT_LABEL_PEAK_CORRECTED)
|
||||
self.ax1.callbacks.connect('xlim_changed', lambda ax: self.on_xlim_change(ax))
|
||||
self.ax0.legend(loc=Constants.PLOT_UPPER_RIGHT)
|
||||
self.ax1.legend(loc=Constants.PLOT_UPPER_RIGHT)
|
||||
except Exception as e:
|
||||
return False, Constants.DRAWING_FAILURE
|
||||
|
||||
self.canvas.draw()
|
||||
return True, Constants.DRAWING_FINISHED
|
||||
|
||||
def __redraw_peaks__(self):
|
||||
|
||||
self.point_peak_corrected.remove()
|
||||
self.point_peak_corrected, = self.ax1.plot(self.data.corrected_peak, self.data.corrected_peak_y, 'ro',
|
||||
label=Constants.LABEL_CHECK_PLOT_LABEL_PEAK_CORRECTED)
|
||||
self.canvas.draw()
|
||||
|
||||
def __update_tableWidget_and_info__(self):
|
||||
|
||||
if self.data.original_peak is None or self.data.corrected_peak is None:
|
||||
return False, Constants.LABEL_CHECK_FAILURE_REASON["Peak_Not_Exist"]
|
||||
|
||||
try:
|
||||
self.ui.tableWidget_peak_original.setRowCount(len(self.data.original_peak))
|
||||
self.ui.spinBox_peak_length_original.setValue(len(self.data.original_peak))
|
||||
for row, value in enumerate(self.data.original_peak):
|
||||
item = QTableWidgetItem(str(value).strip())
|
||||
self.ui.tableWidget_peak_original.setItem(row, 0, item)
|
||||
self.ui.tableWidget_peak_corrected.setRowCount(len(self.data.corrected_peak))
|
||||
self.ui.spinBox_peak_length_corrected.setValue(len(self.data.corrected_peak))
|
||||
for row, value in enumerate(self.data.corrected_peak):
|
||||
item = QTableWidgetItem(str(value).strip())
|
||||
self.ui.tableWidget_peak_corrected.setItem(row, 0, item)
|
||||
status = True
|
||||
info = Constants.UPDATING_FINISHED
|
||||
except Exception:
|
||||
status = False
|
||||
info = Constants.UPDATING_FAILURE
|
||||
return status, info
|
||||
|
||||
def __update_config__(self):
|
||||
@ -335,6 +426,459 @@ class MainWindow_label_check(QMainWindow):
|
||||
Config["CustomAutoplayArgs"]["MaxRange"] = self.ui.spinBox_maxRange.value()
|
||||
Config["CustomAutoplayArgs"]["MoveSpeed"] = self.ui.spinBox_moveSpeed.value()
|
||||
|
||||
def __slot_btn_input__(self):
|
||||
|
||||
PublicFunc.__disableAllButton__(self, ButtonState)
|
||||
|
||||
# 清空画框
|
||||
if self.line_processed_data_1 and self.line_processed_data_2 and self.point_peak_original and self.point_peak_corrected:
|
||||
try:
|
||||
self.line_processed_data_1.remove()
|
||||
self.line_processed_data_2.remove()
|
||||
self.point_peak_original.remove()
|
||||
self.point_peak_corrected.remove()
|
||||
except ValueError:
|
||||
pass
|
||||
self.canvas.draw()
|
||||
|
||||
self.data = Data()
|
||||
|
||||
# 导入数据
|
||||
PublicFunc.progressbar_update(self, 1, 6, Constants.INPUTTING_DATA, 0)
|
||||
status, info = self.data.open_file()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(1/6)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR)
|
||||
PublicFunc.finish_operation(self, ButtonState)
|
||||
return
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(1/6)" + info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
# 获取存档
|
||||
PublicFunc.progressbar_update(self, 2, 6, Constants.LABEL_CHECK_LOADING_ARCHIVE, 20)
|
||||
status, info = self.data.get_archive()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(2/6)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR)
|
||||
PublicFunc.finish_operation(self, ButtonState)
|
||||
return
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(2/6)" + info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
# 数据预处理
|
||||
PublicFunc.progressbar_update(self, 3, 6, Constants.LABEL_CHECK_PROCESSING_DATA, 30)
|
||||
status, info = self.data.preprocess()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(3/6)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR)
|
||||
PublicFunc.finish_operation(self, ButtonState)
|
||||
return
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(3/6)" + info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
# 更新表格
|
||||
PublicFunc.progressbar_update(self, 4, 6, Constants.UPDATING_TABLEWIDGET_AND_INFO, 50)
|
||||
status, info = self.__update_tableWidget_and_info__()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(4/6)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR)
|
||||
PublicFunc.finish_operation(self, ButtonState)
|
||||
return
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(4/6)" + info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
# 绘图
|
||||
PublicFunc.progressbar_update(self, 5, 6, Constants.DRAWING_DATA, 60)
|
||||
status, info = self.__plot__()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(5/6)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR)
|
||||
PublicFunc.finish_operation(self, ButtonState)
|
||||
return
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(5/6)" + info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
# 绘点
|
||||
PublicFunc.progressbar_update(self, 6, 6, Constants.DRAWING_DATA, 80)
|
||||
status, info = self.__plot_peaks__()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(6/6)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR)
|
||||
PublicFunc.finish_operation(self, ButtonState)
|
||||
return
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(6/6)" + info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
MainWindow_label_check.__reset__()
|
||||
self.canvas.mpl_connect("motion_notify_event", self.on_motion)
|
||||
self.figToolbar.action_Label_Multiple.setEnabled(True)
|
||||
for action in self.figToolbar._actions.values():
|
||||
action.setEnabled(True)
|
||||
ButtonState["Current"]["pushButton_input"] = False
|
||||
ButtonState["Current"]["pushButton_input_setting"] = False
|
||||
ButtonState["Current"]["pushButton_prev_move"] = True
|
||||
ButtonState["Current"]["pushButton_next_move"] = True
|
||||
ButtonState["Current"]["pushButton_pause"] = True
|
||||
ButtonState["Current"]["pushButton_save"] = True
|
||||
PublicFunc.finish_operation(self, ButtonState)
|
||||
|
||||
def __slot_btn_save__(self):
|
||||
|
||||
reply = QMessageBox.question(self, Constants.QUESTION_TITLE,
|
||||
Constants.QUESTION_CONTENT + Config["Path"]["Save"],
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.Yes)
|
||||
if reply == QMessageBox.Yes:
|
||||
PublicFunc.__disableAllButton__(self, ButtonState)
|
||||
|
||||
# 保存
|
||||
PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0)
|
||||
# status, info = self.data.save()
|
||||
total_rows = len(DataFrame(self.data.corrected_peak.reshape(-1)))
|
||||
chunk_size = ConfigParams.LABEL_CHECK_SAVE_CHUNK_SIZE
|
||||
with open(Config["Path"]["Save"], 'w') as f:
|
||||
for start in range(0, total_rows, chunk_size):
|
||||
end = min(start + chunk_size, total_rows)
|
||||
chunk = DataFrame(self.data.corrected_peak.reshape(-1)).iloc[start:end]
|
||||
status, info = self.data.save(chunk)
|
||||
progress = int((end / total_rows) * 100)
|
||||
self.progressbar.setValue(progress)
|
||||
QApplication.processEvents()
|
||||
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(1/1)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
PublicFunc.msgbox_output(self, info, Constants.MSGBOX_TYPE_ERROR)
|
||||
PublicFunc.finish_operation(self, ButtonState)
|
||||
return
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(1/1)" + info, Constants.TIPS_TYPE_INFO)
|
||||
PublicFunc.msgbox_output(self, info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
PublicFunc.finish_operation(self, ButtonState)
|
||||
|
||||
def __slot_btn_move__(self):
|
||||
|
||||
if self.data is None:
|
||||
return
|
||||
|
||||
sender = self.sender()
|
||||
|
||||
if sender == self.ui.pushButton_prev_move:
|
||||
Config["AutoplayArgs"]["AutoplayMode"] = "prev"
|
||||
self.autoplay_xlim_start = int(self.ax0.get_xlim()[1] - Config["AutoplayArgs"]["MaxRange"])
|
||||
self.autoplay_xlim_end = int(self.ax0.get_xlim()[1])
|
||||
if self.autoplay_xlim_end > len(self.data.processed_data):
|
||||
self.autoplay_xlim_start = int(len(self.data.processed_data) - Config["AutoplayArgs"]["MaxRange"])
|
||||
self.autoplay_xlim_end = int(len(self.data.processed_data))
|
||||
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
|
||||
self.canvas.draw()
|
||||
self.timer_autoplay.start(Config["AutoplayArgs"]["MoveSpeed"])
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_PREV_MOVE, Constants.TIPS_TYPE_INFO)
|
||||
elif sender == self.ui.pushButton_next_move:
|
||||
Config["AutoplayArgs"]["AutoplayMode"] = "next"
|
||||
self.autoplay_xlim_start = int(self.ax0.get_xlim()[0])
|
||||
self.autoplay_xlim_end = int(self.ax0.get_xlim()[0] + Config["AutoplayArgs"]["MaxRange"])
|
||||
if self.autoplay_xlim_start < 0:
|
||||
self.autoplay_xlim_start = 0
|
||||
self.autoplay_xlim_end = 0 + Config["AutoplayArgs"]["MaxRange"]
|
||||
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
|
||||
self.canvas.draw()
|
||||
self.timer_autoplay.start(Config["AutoplayArgs"]["MoveSpeed"])
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_NEXT_MOVE, Constants.TIPS_TYPE_INFO)
|
||||
elif sender == self.ui.pushButton_pause:
|
||||
Config["AutoplayArgs"]["AutoplayMode"] = "pause"
|
||||
self.timer_autoplay.stop()
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_PAUSE, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
def __change_autoplay_args__(self):
|
||||
|
||||
sender = self.sender()
|
||||
|
||||
if sender == self.ui.radioButton_move_preset_1 and self.ui.radioButton_move_preset_1.isChecked():
|
||||
Config["AutoplayArgs"]["MoveLength"] = int(self.ui.label_moveLength_preset_1.text())
|
||||
Config["AutoplayArgs"]["MaxRange"] = int(self.ui.label_maxRange_preset_1.text())
|
||||
Config["AutoplayArgs"]["MoveSpeed"] = int(self.ui.label_moveSpeed_preset_1.text())
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_SWITCH_PRESET_1, Constants.TIPS_TYPE_INFO)
|
||||
elif sender == self.ui.radioButton_move_preset_2 and self.ui.radioButton_move_preset_2.isChecked():
|
||||
Config["AutoplayArgs"]["MoveLength"] = int(self.ui.label_moveLength_preset_2.text())
|
||||
Config["AutoplayArgs"]["MaxRange"] = int(self.ui.label_maxRange_preset_2.text())
|
||||
Config["AutoplayArgs"]["MoveSpeed"] = int(self.ui.label_moveSpeed_preset_2.text())
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_SWITCH_PRESET_2, Constants.TIPS_TYPE_INFO)
|
||||
elif sender == self.ui.radioButton_move_preset_3 and self.ui.radioButton_move_preset_3.isChecked():
|
||||
Config["AutoplayArgs"]["MoveLength"] = int(self.ui.label_moveLength_preset_3.text())
|
||||
Config["AutoplayArgs"]["MaxRange"] = int(self.ui.label_maxRange_preset_3.text())
|
||||
Config["AutoplayArgs"]["MoveSpeed"] = int(self.ui.label_moveSpeed_preset_3.text())
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_SWITCH_PRESET_3, Constants.TIPS_TYPE_INFO)
|
||||
elif sender == self.ui.radioButton_move_custom and self.ui.radioButton_move_custom.isChecked():
|
||||
Config["AutoplayArgs"]["MoveLength"] = int(self.ui.spinBox_moveLength.value())
|
||||
Config["AutoplayArgs"]["MaxRange"] = int(self.ui.spinBox_maxRange.value())
|
||||
Config["AutoplayArgs"]["MoveSpeed"] = int(self.ui.spinBox_moveSpeed.value())
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_SWITCH_CUSTOM, Constants.TIPS_TYPE_INFO)
|
||||
if Config["AutoplayArgs"]["AutoplayMode"] == "next":
|
||||
self.autoplay_xlim_start = int(self.ax0.get_xlim()[0])
|
||||
self.autoplay_xlim_end = int(self.ax0.get_xlim()[0] + Config["AutoplayArgs"]["MaxRange"])
|
||||
if self.autoplay_xlim_start < 0:
|
||||
self.autoplay_xlim_start = 0
|
||||
self.autoplay_xlim_end = 0 + Config["AutoplayArgs"]["MaxRange"]
|
||||
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
|
||||
self.timer_autoplay.start(Config["AutoplayArgs"]["MoveSpeed"])
|
||||
elif Config["AutoplayArgs"]["AutoplayMode"] == "prev":
|
||||
self.autoplay_xlim_start = int(self.ax0.get_xlim()[1] - Config["AutoplayArgs"]["MaxRange"])
|
||||
self.autoplay_xlim_end = int(self.ax0.get_xlim()[1])
|
||||
if self.autoplay_xlim_end > len(self.data.processed_data):
|
||||
self.autoplay_xlim_start = int(self.data.processed_data) - Config["AutoplayArgs"]["MaxRange"]
|
||||
self.autoplay_xlim_end = int(self.data.processed_data)
|
||||
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
|
||||
self.timer_autoplay.start(Config["AutoplayArgs"]["MoveSpeed"])
|
||||
elif Config["AutoplayArgs"]["AutoplayMode"] == "pause":
|
||||
self.timer_autoplay.stop()
|
||||
|
||||
def __slot_tableWidget_on_cell_double_clicked__(self, row, col):
|
||||
|
||||
if Config["AutoplayArgs"]["AutoplayMode"] != "pause":
|
||||
self.ui.pushButton_pause.click()
|
||||
|
||||
sender = self.sender()
|
||||
|
||||
if sender == self.ui.tableWidget_peak_original:
|
||||
x = float(self.ui.tableWidget_peak_original.item(row, col).text())
|
||||
elif sender == self.ui.tableWidget_peak_corrected:
|
||||
x = float(self.ui.tableWidget_peak_corrected.item(row, col).text())
|
||||
else:
|
||||
raise ValueError("表格跳转参数不存在")
|
||||
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=Constants.PLOT_COLOR_BLACK, shrink=0.1))
|
||||
self.canvas.draw()
|
||||
PublicFunc.text_output(self.ui, f"{Constants.LABEL_CHECK_JUMP_X_INDEX}{str(int(x))}", Constants.TIPS_TYPE_INFO)
|
||||
|
||||
def on_xlim_change(self, event_ax):
|
||||
|
||||
try:
|
||||
if self.annotation_tableWidget:
|
||||
self.annotation_tableWidget.remove()
|
||||
except AttributeError:
|
||||
pass
|
||||
self.annotation_tableWidget = None
|
||||
|
||||
def autoplay_move_xlim(self):
|
||||
|
||||
if Config["AutoplayArgs"]["AutoplayMode"] == "prev" and self.autoplay_xlim_start < 0:
|
||||
Config["AutoplayArgs"]["AutoplayMode"] = "pause"
|
||||
self.timer_autoplay.stop()
|
||||
elif Config["AutoplayArgs"]["AutoplayMode"] == "next" and self.autoplay_xlim_end > len(self.data.processed_data):
|
||||
Config["AutoplayArgs"]["AutoplayMode"] = "pause"
|
||||
self.timer_autoplay.stop()
|
||||
else:
|
||||
if Config["AutoplayArgs"]["AutoplayMode"] == "next":
|
||||
self.autoplay_xlim_start += Config["AutoplayArgs"]["MoveLength"]
|
||||
self.autoplay_xlim_end += Config["AutoplayArgs"]["MoveLength"]
|
||||
elif Config["AutoplayArgs"]["AutoplayMode"] == "prev":
|
||||
self.autoplay_xlim_start -= Config["AutoplayArgs"]["MoveLength"]
|
||||
self.autoplay_xlim_end -= Config["AutoplayArgs"]["MoveLength"]
|
||||
self.ax0.set_xlim(self.autoplay_xlim_start, self.autoplay_xlim_end)
|
||||
self.canvas.draw()
|
||||
|
||||
def on_motion(self, event):
|
||||
|
||||
if event.inaxes and self.ui.checkBox_show_reference_line.isChecked():
|
||||
# Clear previous reference lines and temporary points
|
||||
for line in self.ax0.lines[1:]:
|
||||
if (line.get_label() == "vline" or
|
||||
line.get_label() == "hline"):
|
||||
line.remove()
|
||||
for line in self.ax1.lines[1:]:
|
||||
if (line.get_label() == "vline" or
|
||||
line.get_label() == "hline"):
|
||||
line.remove()
|
||||
|
||||
# Draw vertical and horizontal reference lines
|
||||
self.ax0.axvline(event.xdata, color=Constants.PLOT_COLOR_GRAY, linestyle='--', label="vline")
|
||||
self.ax0.axhline(event.ydata, color=Constants.PLOT_COLOR_GRAY, linestyle='--', label="hline")
|
||||
self.ax1.axvline(event.xdata, color=Constants.PLOT_COLOR_GRAY, linestyle='--', label="vline")
|
||||
self.ax1.axhline(event.ydata, color=Constants.PLOT_COLOR_GRAY, linestyle='--', label="hline")
|
||||
|
||||
self.canvas.draw()
|
||||
|
||||
def toggle_home(self):
|
||||
|
||||
if Config["AutoplayArgs"]["AutoplayMode"] != "pause":
|
||||
self.ui.pushButton_pause.click()
|
||||
self.ax0.autoscale(True)
|
||||
self.ax1.autoscale(True)
|
||||
self.ax1.relim()
|
||||
self.ax1.autoscale_view()
|
||||
self.canvas.draw()
|
||||
self.ax0.autoscale(False)
|
||||
self.ax1.autoscale(False)
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_RECOVER_SCALE, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
def toggle_changeLabel(self, state):
|
||||
|
||||
if state:
|
||||
self.deactivate_figToolbar_buttons()
|
||||
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_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_ax0 is not None and self.figToolbar.rect_patch_ax1 is not None:
|
||||
self.figToolbar.rect_patch_ax0.remove()
|
||||
self.figToolbar.rect_patch_ax0 = None
|
||||
self.figToolbar.rect_patch_ax1.remove()
|
||||
self.figToolbar.rect_patch_ax1 = None
|
||||
self.canvas.draw()
|
||||
|
||||
def on_release(self, event):
|
||||
|
||||
if 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
|
||||
elif rect_left >= len(self.data.processed_data):
|
||||
rect_left = 0
|
||||
rect_right = 0
|
||||
if rect_right >= len(self.data.processed_data):
|
||||
rect_right = len(self.data.processed_data) - 1
|
||||
elif rect_right < 0:
|
||||
rect_left = 0
|
||||
rect_right = 0
|
||||
selected_area_for_add_points = self.data.processed_data[int(rect_left):int(rect_right)]
|
||||
peaks_idx, _ = find_peaks(selected_area_for_add_points,
|
||||
height=Config["FindPeaks"]["MinHeight"],
|
||||
distance=Config["FindPeaks"]["MinInterval"])
|
||||
peaks_idx = peaks_idx + int(rect_left)
|
||||
if len(peaks_idx) != 0:
|
||||
PublicFunc.text_output(self.ui, f"{Constants.LABEL_CHECK_ADD_POINTS_SUCCESSFULLY}{peaks_idx}",
|
||||
Constants.TIPS_TYPE_INFO)
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_NO_POINT_IN_THE_INTERVAL,
|
||||
Constants.TIPS_TYPE_INFO)
|
||||
self.data.corrected_peak = append(self.data.corrected_peak, peaks_idx)
|
||||
self.data.corrected_peak_y = append(self.data.corrected_peak_y, self.data.processed_data[peaks_idx])
|
||||
self.__redraw_peaks__()
|
||||
elif event.button == 3 and self.is_right_button_pressed:
|
||||
self.is_right_button_pressed = False
|
||||
left_label2_to_delete = self.data.corrected_peak - rect_left
|
||||
right_label2_to_delete = self.data.corrected_peak - rect_right
|
||||
left_label2_to_delete_idx = len(left_label2_to_delete[left_label2_to_delete < 0])
|
||||
right_label2_to_delete_idx = len(right_label2_to_delete[right_label2_to_delete < 0])
|
||||
if left_label2_to_delete_idx != right_label2_to_delete_idx:
|
||||
PublicFunc.text_output(self.ui, f"{Constants.LABEL_CHECK_REMOVE_POINTS_SUCCESSFULLY}{self.data.corrected_peak[left_label2_to_delete_idx:right_label2_to_delete_idx]}",
|
||||
Constants.TIPS_TYPE_INFO)
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, Constants.LABEL_CHECK_NO_POINT_IN_THE_INTERVAL,
|
||||
Constants.TIPS_TYPE_INFO)
|
||||
self.data.corrected_peak = delete(self.data.corrected_peak, arange(left_label2_to_delete_idx, right_label2_to_delete_idx))
|
||||
self.data.corrected_peak_y = delete(self.data.corrected_peak_y, arange(left_label2_to_delete_idx, right_label2_to_delete_idx))
|
||||
self.__redraw_peaks__()
|
||||
self.figToolbar.rect_start_x = None
|
||||
self.figToolbar.rect_end_x = None
|
||||
self.data.corrected_peak.sort()
|
||||
self.data.corrected_peak_y = [self.data.processed_data[x] for x in self.data.corrected_peak]
|
||||
self.__update_tableWidget_and_info__()
|
||||
DataFrame(self.data.corrected_peak).to_csv(self.data.file_path_save,
|
||||
index=False, header=False)
|
||||
# 移除矩形patch
|
||||
if self.figToolbar.rect_patch_ax0 is not None and self.figToolbar.rect_patch_ax1 is not None:
|
||||
self.figToolbar.rect_patch_ax0.remove()
|
||||
self.figToolbar.rect_patch_ax0 = None
|
||||
self.figToolbar.rect_patch_ax1.remove()
|
||||
self.figToolbar.rect_patch_ax1 = 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_ax0 is None:
|
||||
if self.is_left_button_pressed:
|
||||
self.figToolbar.rect_patch_ax0 = patches.Rectangle((0, 0), 1, 1, fill=True,
|
||||
alpha=ConfigParams.LABEL_CHECK_LABEL_TRANSPARENCY,
|
||||
color=Constants.PLOT_COLOR_PINK)
|
||||
elif self.is_right_button_pressed:
|
||||
self.figToolbar.rect_patch_ax0 = patches.Rectangle((0, 0), 1, 1, fill=True,
|
||||
alpha=ConfigParams.LABEL_CHECK_LABEL_TRANSPARENCY,
|
||||
color=Constants.PLOT_COLOR_RED)
|
||||
self.ax0.add_patch(self.figToolbar.rect_patch_ax0)
|
||||
|
||||
# 如果矩形patch不存在,则创建一个新的
|
||||
if self.figToolbar.rect_patch_ax1 is None:
|
||||
if self.is_left_button_pressed:
|
||||
self.figToolbar.rect_patch_ax1 = patches.Rectangle((0, 0), 1, 1, fill=True,
|
||||
alpha=ConfigParams.LABEL_CHECK_LABEL_TRANSPARENCY,
|
||||
color=Constants.PLOT_COLOR_PINK)
|
||||
elif self.is_right_button_pressed:
|
||||
self.figToolbar.rect_patch_ax1 = patches.Rectangle((0, 0), 1, 1, fill=True,
|
||||
alpha=ConfigParams.LABEL_CHECK_LABEL_TRANSPARENCY,
|
||||
color=Constants.PLOT_COLOR_RED)
|
||||
self.ax1.add_patch(self.figToolbar.rect_patch_ax1)
|
||||
|
||||
# 更新矩形patch的位置和大小
|
||||
x_start = self.figToolbar.rect_start_x
|
||||
x_end = self.figToolbar.rect_end_x
|
||||
rect_down = min(self.ax0.get_ylim()[0], self.ax1.get_ylim()[0]) - 1000
|
||||
rect_up = max(self.ax0.get_ylim()[1], self.ax1.get_ylim()[1]) + 1000
|
||||
self.figToolbar.rect_patch_ax0.set_xy((min(x_start, x_end), rect_down))
|
||||
self.figToolbar.rect_patch_ax0.set_width(abs(x_end - x_start))
|
||||
self.figToolbar.rect_patch_ax0.set_height(rect_up - rect_down)
|
||||
self.figToolbar.rect_patch_ax1.set_xy((min(x_start, x_end), rect_down))
|
||||
self.figToolbar.rect_patch_ax1.set_width(abs(x_end - x_start))
|
||||
self.figToolbar.rect_patch_ax1.set_height(rect_up - rect_down)
|
||||
|
||||
self.canvas.draw()
|
||||
|
||||
|
||||
class Data:
|
||||
|
||||
@ -345,4 +889,142 @@ class Data:
|
||||
|
||||
self.raw_data = None
|
||||
self.processed_data = None
|
||||
self.peak = None
|
||||
self.original_peak = None
|
||||
self.original_peak_y = None
|
||||
self.corrected_peak = None
|
||||
self.corrected_peak_y = None
|
||||
|
||||
def open_file(self):
|
||||
|
||||
if (not Path(Config["Path"]["Input_Signal"]).exists()) or (not Path(Config["Path"]["Input_Peak"]).exists()):
|
||||
return False, Constants.INPUT_FAILURE + Constants.LABEL_CHECK_FAILURE_REASON["Data_Path_Not_Exist"]
|
||||
|
||||
try:
|
||||
self.raw_data = read_csv(self.file_path_input_signal,
|
||||
encoding=ConfigParams.UTF8_ENCODING,
|
||||
header=None).to_numpy().reshape(-1)
|
||||
self.original_peak = read_csv(self.file_path_input_peak,
|
||||
encoding=ConfigParams.UTF8_ENCODING,
|
||||
header=None).to_numpy().reshape(-1)
|
||||
except Exception:
|
||||
return False, Constants.INPUT_FAILURE + Constants.LABEL_CHECK_FAILURE_REASON["Read_Data_Exception"]
|
||||
|
||||
return True, Constants.INPUT_FINISHED
|
||||
|
||||
def get_archive(self):
|
||||
|
||||
if not Path(Config["Path"]["Save"]).exists():
|
||||
self.corrected_peak = self.original_peak
|
||||
return True, Constants.LABEL_CHECK_ARCHIVE_NOT_EXIST
|
||||
else:
|
||||
self.corrected_peak = read_csv(self.file_path_save,
|
||||
encoding=ConfigParams.UTF8_ENCODING,
|
||||
header=None).to_numpy().reshape(-1)
|
||||
return True, Constants.LABEL_CHECK_ARCHIVE_EXIST
|
||||
|
||||
def preprocess(self):
|
||||
|
||||
if self.raw_data is None:
|
||||
return False, Constants.LABEL_CHECK_PROCESS_FAILURE + Constants.LABEL_CHECK_FAILURE_REASON["Raw_Data_Not_Exist"]
|
||||
|
||||
try:
|
||||
if Config["Mode"] == "BCG":
|
||||
self.processed_data = data_preprocess_for_label_check(self.raw_data,
|
||||
Config["Filter"]["BCGBandPassOrder"],
|
||||
Config["Filter"]["BCGBandPassLow"],
|
||||
Config["Filter"]["BCGBandPassHigh"],
|
||||
Config["InputConfig"]["Freq"])
|
||||
elif Config["Mode"] == "ECG":
|
||||
self.processed_data = data_preprocess_for_label_check(self.raw_data,
|
||||
Config["Filter"]["ECGBandPassOrder"],
|
||||
Config["Filter"]["ECGBandPassLow"],
|
||||
Config["Filter"]["ECGBandPassHigh"],
|
||||
Config["InputConfig"]["Freq"])
|
||||
else:
|
||||
raise ValueError("模式不存在")
|
||||
self.original_peak_y = [self.processed_data[x] for x in self.original_peak]
|
||||
self.corrected_peak_y = [self.processed_data[x] for x in self.corrected_peak]
|
||||
except Exception:
|
||||
return False, Constants.LABEL_CHECK_PROCESS_FAILURE + Constants.LABEL_CHECK_FAILURE_REASON["Filter_Exception"]
|
||||
|
||||
return True, Constants.LABEL_CHECK_PROCESS_FINISHED
|
||||
|
||||
def save(self, chunk):
|
||||
|
||||
if self.corrected_peak is None:
|
||||
return False, Constants.SAVING_FAILURE + Constants.LABEL_CHECK_FAILURE_REASON["Peak_Not_Exist"]
|
||||
|
||||
try:
|
||||
# DataFrame(self.corrected_peak.reshape(-1)).to_csv(self.file_path_save,
|
||||
# index=False,
|
||||
# header=False)
|
||||
chunk.to_csv(self.file_path_save, mode='a', index=False, header=False)
|
||||
except Exception:
|
||||
return False, Constants.SAVING_FAILURE + Constants.LABEL_CHECK_FAILURE_REASON["Save_Exception"]
|
||||
|
||||
return True, Constants.SAVING_FINISHED
|
||||
|
||||
|
||||
class CustomNavigationToolbar(NavigationToolbar2QT):
|
||||
|
||||
|
||||
def __init__(self, canvas, parent):
|
||||
super().__init__(canvas, parent)
|
||||
# 初始化画框工具栏
|
||||
self.action_Label_Multiple = QAction(Constants.LABEL_CHECK_ACTION_LABEL_MULTIPLE_NAME, self)
|
||||
self.action_Label_Multiple.setFont(QFont(ConfigParams.FONT, 14))
|
||||
self.action_Label_Multiple.setCheckable(True)
|
||||
self.action_Label_Multiple.setShortcut(QCoreApplication.translate(
|
||||
"MainWindow",
|
||||
ConfigParams.LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY))
|
||||
self.insertAction(self._actions['pan'], self.action_Label_Multiple)
|
||||
|
||||
self._actions['pan'].setShortcut(QCoreApplication.translate(
|
||||
"MainWindow",
|
||||
ConfigParams.ACTION_PAN_SHORTCUT_KEY))
|
||||
self._actions['zoom'].setShortcut(QCoreApplication.translate(
|
||||
"MainWindow",
|
||||
ConfigParams.ACTION_ZOOM_SHORTCUT_KEY))
|
||||
|
||||
# 用于存储事件连接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_ax0 = None # 用于绘制矩形的patch
|
||||
self.rect_patch_ax1 = 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_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
|
||||
@ -4,12 +4,14 @@ from PySide6.QtWidgets import QMainWindow, QMessageBox, QFileDialog
|
||||
from matplotlib import use
|
||||
from yaml import dump, load, FullLoader
|
||||
|
||||
|
||||
from func.utils.PublicFunc import PublicFunc
|
||||
from ui.MainWindow.MainWindow_menu import Ui_Signal_Label
|
||||
|
||||
from func.Module_preprocess import MainWindow_preprocess
|
||||
from func.Module_detect_Jpeak import MainWindow_detect_Jpeak
|
||||
from func.Module_detect_Rpeak import MainWindow_detect_Rpeak
|
||||
from func.Module_label_check import MainWindow_label_check
|
||||
|
||||
from func.utils.Constants import Constants, ConfigParams
|
||||
|
||||
@ -115,7 +117,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
|
||||
|
||||
def __slot_btn_label_check__(self):
|
||||
|
||||
self.label_check = MainWindow_detect_Rpeak()
|
||||
self.label_check = MainWindow_label_check()
|
||||
|
||||
sender = self.sender()
|
||||
root_path = self.ui.plainTextEdit_root_path.toPlainText()
|
||||
|
||||
@ -100,7 +100,7 @@ class SettingWindow(QMainWindow):
|
||||
"Mode": self.mode
|
||||
})
|
||||
else:
|
||||
raise ValueError
|
||||
raise ValueError("模式不存在")
|
||||
|
||||
# 数据回显
|
||||
self.ui.spinBox_input_freq.setValue(Config["InputConfig"]["Freq"])
|
||||
@ -162,7 +162,7 @@ class SettingWindow(QMainWindow):
|
||||
str(self.ui.spinBox_output_freq.value()) +
|
||||
ConfigParams.ENDSWITH_TXT))))
|
||||
else:
|
||||
raise ValueError
|
||||
raise ValueError("模式不存在")
|
||||
|
||||
|
||||
class MainWindow_preprocess(QMainWindow):
|
||||
@ -235,7 +235,7 @@ class MainWindow_preprocess(QMainWindow):
|
||||
self.ui.doubleSpinBox_bandPassLow.setValue(Config["Filter"]["ECGBandPassLow"])
|
||||
self.ui.doubleSpinBox_bandPassHigh.setValue(Config["Filter"]["ECGBandPassHigh"])
|
||||
else:
|
||||
raise ValueError
|
||||
raise ValueError("模式不存在")
|
||||
|
||||
self.ui.pushButton_input.clicked.connect(self.__slot_btn_input__)
|
||||
self.ui.pushButton_input_setting.clicked.connect(self.setting.show)
|
||||
@ -314,7 +314,7 @@ class MainWindow_preprocess(QMainWindow):
|
||||
Config["Filter"]["ECGBandPassLow"] = self.ui.doubleSpinBox_bandPassLow.value()
|
||||
Config["Filter"]["ECGBandPassHigh"] = self.ui.doubleSpinBox_bandPassHigh.value()
|
||||
else:
|
||||
raise ValueError
|
||||
raise ValueError("模式不存在")
|
||||
|
||||
def __slot_btn_input__(self):
|
||||
|
||||
@ -329,12 +329,10 @@ class MainWindow_preprocess(QMainWindow):
|
||||
pass
|
||||
self.canvas.draw()
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(1/1)" + Constants.INPUTTING_DATA))
|
||||
self.progressbar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
self.data = Data()
|
||||
|
||||
# 导入数据
|
||||
self.data = Data()
|
||||
PublicFunc.progressbar_update(self, 1, 1, Constants.INPUTTING_DATA, 0)
|
||||
status, info = self.data.open_file()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(1/1)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -351,11 +349,8 @@ class MainWindow_preprocess(QMainWindow):
|
||||
|
||||
PublicFunc.__disableAllButton__(self, ButtonState)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(1/2)" + Constants.PREPROCESS_PROCESSING_DATA))
|
||||
self.progressbar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 数据预处理
|
||||
PublicFunc.progressbar_update(self, 1, 2, Constants.PREPROCESS_PROCESSING_DATA, 0)
|
||||
status, info = self.data.preprocess()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(1/2)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -365,11 +360,8 @@ class MainWindow_preprocess(QMainWindow):
|
||||
else:
|
||||
PublicFunc.text_output(self.ui, "(1/2)" + info, Constants.TIPS_TYPE_INFO)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(2/2)" + Constants.DRAWING_DATA))
|
||||
self.progressbar.setValue(50)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 绘图
|
||||
PublicFunc.progressbar_update(self, 2, 2, Constants.DRAWING_DATA, 50)
|
||||
status, info = self.__plot__()
|
||||
if not status:
|
||||
PublicFunc.text_output(self.ui, "(2/2)" + info, Constants.TIPS_TYPE_ERROR)
|
||||
@ -391,11 +383,8 @@ class MainWindow_preprocess(QMainWindow):
|
||||
if reply == QMessageBox.Yes:
|
||||
PublicFunc.__disableAllButton__(self, ButtonState)
|
||||
|
||||
PublicFunc.statusbar_show_msg(self, PublicFunc.format_status_msg("(1/1)" + Constants.SAVING_DATA))
|
||||
self.progressbar.setValue(0)
|
||||
QApplication.processEvents()
|
||||
|
||||
# 保存
|
||||
PublicFunc.progressbar_update(self, 1, 1, Constants.SAVING_DATA, 0)
|
||||
# status, info = self.data.save()
|
||||
total_rows = len(DataFrame(self.data.processed_data.reshape(-1)))
|
||||
chunk_size = ConfigParams.PREPROCESS_SAVE_CHUNK_SIZE
|
||||
@ -467,7 +456,7 @@ class Data:
|
||||
order=Config["Filter"]["ECGBandPassOrder"],
|
||||
sample_rate=Config["OutputConfig"]["Freq"])
|
||||
else:
|
||||
raise ValueError
|
||||
raise ValueError("模式不存在")
|
||||
except Exception:
|
||||
return False, Constants.PREPROCESS_PROCESS_FAILURE + Constants.PREPROCESS_FAILURE_REASON["Filter_Exception"]
|
||||
|
||||
|
||||
@ -124,6 +124,8 @@ class ConfigParams:
|
||||
LABEL_CHECK_INPUT_RPEAK_FILENAME: str = "final_Rpeak"
|
||||
LABEL_CHECK_SAVE_RPEAK_FILENAME: str = "final_Rpeak_corrected"
|
||||
LABEL_CHECK_SAVE_CHUNK_SIZE: int = 100
|
||||
LABEL_CHECK_LABEL_TRANSPARENCY: float = 0.2
|
||||
LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY: str = "Z"
|
||||
|
||||
# 体动标注
|
||||
|
||||
@ -156,35 +158,6 @@ class ConfigParams:
|
||||
APPROXIMATELY_ALIGN_BUTTERHIGHPASSFREQ_DEFAULT: float = 0.70
|
||||
APPROXIMATELY_ALIGN_APPLYFREQ_DEFAULT: float = 5
|
||||
|
||||
# 人工纠正
|
||||
LABEL_CHECK_INPUT_BCG_FILENAME: str = "DSbcg_sig_"
|
||||
LABEL_CHECK_INPUT_JPEAK_FILENAME: str = "JPeak_revise"
|
||||
LABEL_CHECK_SAVE_JPEAK_FILENAME: str = "JPeak_revise_corrected"
|
||||
LABEL_CHECK_INPUT_ECG_FILENAME: str = "ECG_filter_"
|
||||
LABEL_CHECK_INPUT_RPEAK_FILENAME: str = "final_Rpeak"
|
||||
LABEL_CHECK_SAVE_RPEAK_FILENAME: str = "final_Rpeak_corrected"
|
||||
|
||||
LABEL_CHECK_INPUT_DEFAULT_FS: int = 1000
|
||||
|
||||
LABEL_CHECK_DATA1_FILTER_ORDER_DEFAULT: int = 2
|
||||
LABEL_CHECK_DATA1_BANDPASS_LOW_DEFAULT: int = 2
|
||||
LABEL_CHECK_DATA1_BANDPASS_HIGH_DEFAULT: int = 10
|
||||
LABEL_CHECK_DATA2_FILTER_ORDER_DEFAULT: int = 2
|
||||
LABEL_CHECK_DATA2_BANDPASS_LOW_DEFAULT: int = 2
|
||||
LABEL_CHECK_DATA2_BANDPASS_HIGH_DEFAULT: int = 15
|
||||
LABEL_CHECK_FINDPEAKS_MIN_INTERVAL_DEFAULT: int = 1000
|
||||
LABEL_CHECK_FINDPEAKS_MIN_HEIGHT_DEFAULT: int = 0.5
|
||||
LABEL_CHECK_MOVELENGTH_DEFAULT: int = 15000
|
||||
LABEL_CHECK_MAXRANGE_DEFAULT: int = 60000
|
||||
LABEL_CHECK_MOVESPEED_DEFAULT: int = 1000
|
||||
|
||||
LABEL_CHECK_FILTER: str = "bandpass"
|
||||
|
||||
LABEL_CHECK_LABEL_TRANSPARENCY: float = 0.2
|
||||
|
||||
LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY: str = "Z"
|
||||
|
||||
|
||||
# 体动打标
|
||||
ARTIFACT_LABEL_INPUT_BCG_FILENAME: str = "BCG_sync_"
|
||||
ARTIFACT_LABEL_INPUT_XINXIAO_FILENAME: str = "orgBcg_sync_"
|
||||
|
||||
@ -19,6 +19,10 @@ class Constants:
|
||||
DRAWING_FINISHED: str = "绘制完成"
|
||||
DRAWING_FAILURE: str = "绘制失败"
|
||||
|
||||
UPDATING_TABLEWIDGET_AND_INFO: str = "正在更新表格和信息"
|
||||
UPDATING_FINISHED: str = "更新完成"
|
||||
UPDATING_FAILURE: str = "更新失败"
|
||||
|
||||
SAVING_DATA: str = "正在保存数据"
|
||||
SAVING_FINISHED: str = "保存完成"
|
||||
SAVING_FAILURE: str = "保存失败"
|
||||
@ -158,22 +162,38 @@ class Constants:
|
||||
LABEL_CHECK_PROCESS_FINISHED: str = "处理完成"
|
||||
LABEL_CHECK_PROCESS_FAILURE: str = "处理失败"
|
||||
|
||||
LABEL_CHECK_LOADING_ARCHIVE: str = "正在获取历史存档"
|
||||
LABEL_CHECK_ARCHIVE_EXIST: str = "找到历史存档,成功读取"
|
||||
LABEL_CHECK_ARCHIVE_NOT_EXIST: str = "未找到历史存档,创建新存档"
|
||||
|
||||
LABEL_CHECK_FAILURE_REASON = {
|
||||
"Data_Path_Not_Exist": "(数据路径不存在)",
|
||||
"Read_Data_Exception": "(读取数据异常)",
|
||||
"Method_Not_Exist": "(检测方法不存在)",
|
||||
"Read_Method_Exception": "(读取方法异常)",
|
||||
"Predict_Exception": "(峰值预测异常)",
|
||||
"Raw_Data_Not_Exist": "(原始数据不存在)",
|
||||
"Filter_Exception": "(滤波器异常)",
|
||||
"Processed_Data_Not_Exist": "(处理后数据不存在)",
|
||||
"Peak_Not_Exist": "(预测的峰值不存在)",
|
||||
"Peak_Not_Exist": "(峰值不存在)",
|
||||
"Save_Exception": "(保存异常)"
|
||||
}
|
||||
|
||||
LABEL_CHECK_PLOT_LABEL_BCG: str = "Data_Processed"
|
||||
LABEL_CHECK_PLOT_LABEL_SIGNAL: str = "Data_Processed"
|
||||
LABEL_CHECK_PLOT_LABEL_PEAK_ORIGINAL: str = "Peaks_Original"
|
||||
LABEL_CHECK_PLOT_LABEL_PEAK_CORRECTED: str = "Peaks_Corrected"
|
||||
LABEL_CHECK_PREV_MOVE: str = "向前移动"
|
||||
LABEL_CHECK_NEXT_MOVE: str = "向后移动"
|
||||
LABEL_CHECK_PAUSE: str = "暂停移动"
|
||||
LABEL_CHECK_SWITCH_PRESET_1: str = "变更为预设1"
|
||||
LABEL_CHECK_SWITCH_PRESET_2: str = "变更为预设2"
|
||||
LABEL_CHECK_SWITCH_PRESET_3: str = "变更为预设3"
|
||||
LABEL_CHECK_SWITCH_CUSTOM: str = "变更为自定义,请注意,自定义的参数未经校验,过大或过小的参数可能导致程序异常"
|
||||
LABEL_CHECK_JUMP_X_INDEX: str = "跳转到x坐标: "
|
||||
LABEL_CHECK_RECOVER_SCALE: str = "尺度恢复"
|
||||
LABEL_CHECK_ADD_POINTS_SUCCESSFULLY: str = "成功新增点,横坐标:"
|
||||
LABEL_CHECK_REMOVE_POINTS_SUCCESSFULLY: str = "成功删除点,横坐标:"
|
||||
LABEL_CHECK_NO_POINT_IN_THE_INTERVAL: str = "所选区间内无新增或删除点"
|
||||
LABEL_CHECK_ACTION_LABEL_MULTIPLE_NAME: str = f"批量更改标签({ConfigParams.LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY})"
|
||||
|
||||
|
||||
|
||||
|
||||
# 体动标注
|
||||
@ -198,45 +218,6 @@ class Constants:
|
||||
APPROXIMATELY_ALIGN_RUNNING: str = "开始执行任务<数据粗同步>"
|
||||
APPROXIMATELY_RECORD_NOT_FOUND: str = "没有保存记录"
|
||||
|
||||
# 人工纠正
|
||||
LABEL_CHECK_FILES_BCG_NOT_FOUND: str = f"无法找到{ConfigParams.LABEL_CHECK_INPUT_BCG_FILENAME}{ConfigParams.ENDSWITH_TXT}或{ConfigParams.LABEL_CHECK_INPUT_JPEAK_FILENAME}{ConfigParams.ENDSWITH_TXT},无法执行<BCG的J峰人工纠正>"
|
||||
LABEL_CHECK_FILES_BCG_FOUND: str = f"找到{ConfigParams.LABEL_CHECK_INPUT_BCG_FILENAME}{ConfigParams.ENDSWITH_TXT}和{ConfigParams.LABEL_CHECK_INPUT_JPEAK_FILENAME}{ConfigParams.ENDSWITH_TXT}"
|
||||
LABEL_CHECK_FILES_ECG_NOT_FOUND: str = f"无法找到{ConfigParams.LABEL_CHECK_INPUT_ECG_FILENAME}{ConfigParams.ENDSWITH_TXT}或{ConfigParams.LABEL_CHECK_INPUT_RPEAK_FILENAME}{ConfigParams.ENDSWITH_TXT},无法执行<ECG的R峰人工纠正>"
|
||||
LABEL_CHECK_FILES_ECG_FOUND: str = f"找到{ConfigParams.LABEL_CHECK_INPUT_ECG_FILENAME}{ConfigParams.ENDSWITH_TXT}和{ConfigParams.LABEL_CHECK_INPUT_RPEAK_FILENAME}{ConfigParams.ENDSWITH_TXT}"
|
||||
LABEL_CHECK_HISTORICAL_SAVE_FOUND: str = f"找到历史存档文件{ConfigParams.LABEL_CHECK_SAVE_JPEAK_FILENAME}{ConfigParams.ENDSWITH_TXT}或{ConfigParams.LABEL_CHECK_SAVE_RPEAK_FILENAME}{ConfigParams.ENDSWITH_TXT},已成功读取"
|
||||
|
||||
LABEL_CHECK_RUNNING: str = "开始执行任务<人工纠正>"
|
||||
LABEL_CHECK_BCG_MODE: str = "BCG_MODE"
|
||||
LABEL_CHECK_ECG_MODE: str = "ECG_MODE"
|
||||
LABEL_CHECK_PLOT_LABEL_DATA1: str = "Data 1"
|
||||
LABEL_CHECK_PLOT_LABEL_DATA2: str = "Data 2"
|
||||
LABEL_CHECK_PLOT_LABEL_LABEL1: str = "Label 1"
|
||||
LABEL_CHECK_PLOT_LABEL_LABEL2: str = "Label 2"
|
||||
LABEL_CHECK_PLOT_LABEL_VLINE: str = "vline"
|
||||
LABEL_CHECK_PLOT_LABEL_HLINE: str = "hline"
|
||||
LABEL_CHECK_AUTOPLAY_LEFT: str = "LEFT"
|
||||
LABEL_CHECK_AUTOPLAY_PAUSE: str = "PAUSE"
|
||||
LABEL_CHECK_AUTOPLAY_RIGHT: str = "RIGHT"
|
||||
LABEL_CHECK_AUTOPLAY_LEFT_INFO: str = "开始自动播放-向左"
|
||||
LABEL_CHECK_AUTOPLAY_PAUSE_INFO: str = "暂停自动播放"
|
||||
LABEL_CHECK_AUTOPLAY_RIGHT_INFO: str = "开始自动播放-向右"
|
||||
LABEL_CHECK_AUTOPLAY_PRESET1_INFO: str = "切换到自动播放-预设1"
|
||||
LABEL_CHECK_AUTOPLAY_PRESET2_INFO: str = "切换到自动播放-预设2"
|
||||
LABEL_CHECK_AUTOPLAY_PRESET3_INFO: str = "切换到自动播放-预设3"
|
||||
LABEL_CHECK_AUTOPLAY_PRESET_CUSTOM_INFO: str = "切换到自动播放-自定义"
|
||||
LABEL_CHECK_AUTOPLAY_PRESET_CUSTOM_WARNING: str = "自定义的输入参数未做任何检查,请斟酌输入参数,否则可能会导致程序异常"
|
||||
LABEL_CHECK_JUMP_X_INDEX: str = "跳转到x坐标: "
|
||||
LABEL_CHECK_RECOVER_SCALE: str = "尺度恢复"
|
||||
LABEL_CHECK_BUTTON_PRESS_EVENT: str = "button_press_event"
|
||||
LABEL_CHECK_BUTTON_RELEASE_EVENT: str = "button_release_event"
|
||||
LABEL_CHECK_MOTION_NOTIFY_EVENT: str = "motion_notify_event"
|
||||
LABEL_CHECK_ADD_POINTS_SUCCESSFULLY: str = "成功新增点,横坐标:"
|
||||
LABEL_CHECK_REMOVE_POINTS_SUCCESSFULLY: str = "成功删除点,横坐标:"
|
||||
LABEL_CHECK_NO_POINT_IN_THE_INTERVAL: str = "所选区间内无新增或删除点"
|
||||
LABEL_CHECK_CUSTOM_NAVIGATIONTOOLBAR_WIDGET_NAME: str = "MainWindow"
|
||||
LABEL_CHECK_ACTION_LABEL_MULTIPLE_NAME: str = f"批量更改标签({ConfigParams.LABEL_CHECK_ACTION_LABEL_MULTIPLE_SHORTCUT_KEY})"
|
||||
|
||||
|
||||
# 体动打标
|
||||
ARTIFACT_LABEL_FILES_NOT_FOUND: str = f"无法找到{ConfigParams.ARTIFACT_LABEL_INPUT_BCG_FILENAME}{ConfigParams.ENDSWITH_TXT}或{ConfigParams.ARTIFACT_LABEL_INPUT_XINXIAO_FILENAME}{ConfigParams.ENDSWITH_TXT},无法执行<体动标注>"
|
||||
ARTIFACT_LABEL_FILES_FOUND: str = f"找到{ConfigParams.ARTIFACT_LABEL_INPUT_BCG_FILENAME}{ConfigParams.ENDSWITH_TXT}和{ConfigParams.ARTIFACT_LABEL_INPUT_XINXIAO_FILENAME}{ConfigParams.ENDSWITH_TXT}"
|
||||
|
||||
@ -155,3 +155,14 @@ class PublicFunc:
|
||||
QApplication.processEvents()
|
||||
|
||||
PublicFunc.__enableAllButton__(mainWindow, buttonState)
|
||||
|
||||
@staticmethod
|
||||
def progressbar_update(mainWindow, current: int, total: int, msg: str, progressbarState: int):
|
||||
|
||||
if current > total:
|
||||
raise ValueError("当前进度值大于总进度值")
|
||||
if progressbarState < 0 or progressbarState > 100:
|
||||
raise ValueError("进度条值的范围应该在[0, 100]")
|
||||
PublicFunc.statusbar_show_msg(mainWindow, PublicFunc.format_status_msg(f"({str(current)}/{str(total)}){msg}"))
|
||||
mainWindow.progressbar.setValue(progressbarState)
|
||||
QApplication.processEvents()
|
||||
@ -250,6 +250,8 @@ class Ui_MainWindow_artifact_label(object):
|
||||
self.spinBox_moveLength.setObjectName(u"spinBox_moveLength")
|
||||
self.spinBox_moveLength.setFont(font1)
|
||||
self.spinBox_moveLength.setButtonSymbols(QAbstractSpinBox.ButtonSymbols.NoButtons)
|
||||
self.spinBox_moveLength.setMinimum(1000)
|
||||
self.spinBox_moveLength.setMaximum(100000)
|
||||
|
||||
self.gridLayout_3.addWidget(self.spinBox_moveLength, 4, 1, 1, 1)
|
||||
|
||||
@ -290,6 +292,8 @@ class Ui_MainWindow_artifact_label(object):
|
||||
self.spinBox_maxRange.setObjectName(u"spinBox_maxRange")
|
||||
self.spinBox_maxRange.setFont(font1)
|
||||
self.spinBox_maxRange.setButtonSymbols(QAbstractSpinBox.ButtonSymbols.NoButtons)
|
||||
self.spinBox_maxRange.setMinimum(1000)
|
||||
self.spinBox_maxRange.setMaximum(100000)
|
||||
|
||||
self.gridLayout_3.addWidget(self.spinBox_maxRange, 4, 2, 1, 1)
|
||||
|
||||
@ -304,6 +308,8 @@ class Ui_MainWindow_artifact_label(object):
|
||||
self.spinBox_moveSpeed.setObjectName(u"spinBox_moveSpeed")
|
||||
self.spinBox_moveSpeed.setFont(font1)
|
||||
self.spinBox_moveSpeed.setButtonSymbols(QAbstractSpinBox.ButtonSymbols.NoButtons)
|
||||
self.spinBox_moveSpeed.setMinimum(100)
|
||||
self.spinBox_moveSpeed.setMaximum(10000)
|
||||
|
||||
self.gridLayout_3.addWidget(self.spinBox_moveSpeed, 4, 3, 1, 1)
|
||||
|
||||
|
||||
@ -422,6 +422,12 @@
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
@ -503,6 +509,12 @@
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
@ -530,6 +542,12 @@
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
|
||||
@ -209,6 +209,8 @@ class Ui_MainWindow_label_check(object):
|
||||
self.spinBox_moveLength.setObjectName(u"spinBox_moveLength")
|
||||
self.spinBox_moveLength.setFont(font1)
|
||||
self.spinBox_moveLength.setButtonSymbols(QAbstractSpinBox.ButtonSymbols.NoButtons)
|
||||
self.spinBox_moveLength.setMinimum(1000)
|
||||
self.spinBox_moveLength.setMaximum(100000)
|
||||
|
||||
self.gridLayout_3.addWidget(self.spinBox_moveLength, 4, 1, 1, 1)
|
||||
|
||||
@ -249,6 +251,8 @@ class Ui_MainWindow_label_check(object):
|
||||
self.spinBox_maxRange.setObjectName(u"spinBox_maxRange")
|
||||
self.spinBox_maxRange.setFont(font1)
|
||||
self.spinBox_maxRange.setButtonSymbols(QAbstractSpinBox.ButtonSymbols.NoButtons)
|
||||
self.spinBox_maxRange.setMinimum(1000)
|
||||
self.spinBox_maxRange.setMaximum(100000)
|
||||
|
||||
self.gridLayout_3.addWidget(self.spinBox_maxRange, 4, 2, 1, 1)
|
||||
|
||||
@ -263,6 +267,9 @@ class Ui_MainWindow_label_check(object):
|
||||
self.spinBox_moveSpeed.setObjectName(u"spinBox_moveSpeed")
|
||||
self.spinBox_moveSpeed.setFont(font1)
|
||||
self.spinBox_moveSpeed.setButtonSymbols(QAbstractSpinBox.ButtonSymbols.NoButtons)
|
||||
self.spinBox_moveSpeed.setMinimum(100)
|
||||
self.spinBox_moveSpeed.setMaximum(10000)
|
||||
self.spinBox_moveSpeed.setValue(100)
|
||||
|
||||
self.gridLayout_3.addWidget(self.spinBox_moveSpeed, 4, 3, 1, 1)
|
||||
|
||||
@ -344,11 +351,11 @@ class Ui_MainWindow_label_check(object):
|
||||
|
||||
self.horizontalLayout_3 = QHBoxLayout()
|
||||
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
|
||||
self.checkBox = QCheckBox(self.groupBox_left)
|
||||
self.checkBox.setObjectName(u"checkBox")
|
||||
self.checkBox.setFont(font1)
|
||||
self.checkBox_show_reference_line = QCheckBox(self.groupBox_left)
|
||||
self.checkBox_show_reference_line.setObjectName(u"checkBox_show_reference_line")
|
||||
self.checkBox_show_reference_line.setFont(font1)
|
||||
|
||||
self.horizontalLayout_3.addWidget(self.checkBox)
|
||||
self.horizontalLayout_3.addWidget(self.checkBox_show_reference_line)
|
||||
|
||||
self.pushButton_save = QPushButton(self.groupBox_left)
|
||||
self.pushButton_save.setObjectName(u"pushButton_save")
|
||||
@ -440,14 +447,20 @@ class Ui_MainWindow_label_check(object):
|
||||
self.gridLayout_4.addWidget(self.spinBox_peak_length_corrected, 3, 1, 1, 1)
|
||||
|
||||
self.tableWidget_peak_original = QTableWidget(self.groupBox_right)
|
||||
if (self.tableWidget_peak_original.columnCount() < 1):
|
||||
self.tableWidget_peak_original.setColumnCount(1)
|
||||
self.tableWidget_peak_original.setObjectName(u"tableWidget_peak_original")
|
||||
self.tableWidget_peak_original.setFont(font1)
|
||||
self.tableWidget_peak_original.setColumnCount(1)
|
||||
|
||||
self.gridLayout_4.addWidget(self.tableWidget_peak_original, 4, 0, 1, 1)
|
||||
|
||||
self.tableWidget_peak_corrected = QTableWidget(self.groupBox_right)
|
||||
if (self.tableWidget_peak_corrected.columnCount() < 1):
|
||||
self.tableWidget_peak_corrected.setColumnCount(1)
|
||||
self.tableWidget_peak_corrected.setObjectName(u"tableWidget_peak_corrected")
|
||||
self.tableWidget_peak_corrected.setFont(font1)
|
||||
self.tableWidget_peak_corrected.setColumnCount(1)
|
||||
|
||||
self.gridLayout_4.addWidget(self.tableWidget_peak_corrected, 4, 1, 1, 1)
|
||||
|
||||
@ -507,7 +520,7 @@ class Ui_MainWindow_label_check(object):
|
||||
self.label_7.setText(QCoreApplication.translate("MainWindow_label_check", u"\u79fb\u52a8\u8ddd\u79bb", None))
|
||||
self.label_6.setText(QCoreApplication.translate("MainWindow_label_check", u"\u6700\u5927\u8303\u56f4", None))
|
||||
self.label_8.setText(QCoreApplication.translate("MainWindow_label_check", u"\u79fb\u52a8\u95f4\u9694(ms)", None))
|
||||
self.checkBox.setText(QCoreApplication.translate("MainWindow_label_check", u"\u7ed8\u5236\u53c2\u8003\u7ebf", None))
|
||||
self.checkBox_show_reference_line.setText(QCoreApplication.translate("MainWindow_label_check", u"\u7ed8\u5236\u53c2\u8003\u7ebf", None))
|
||||
self.pushButton_save.setText(QCoreApplication.translate("MainWindow_label_check", u"\u5bfc\u51fa\u6807\u7b7e", None))
|
||||
self.groupBox_4.setTitle(QCoreApplication.translate("MainWindow_label_check", u"\u65e5\u5fd7", None))
|
||||
self.groupBox_right.setTitle(QCoreApplication.translate("MainWindow_label_check", u"\u5cf0\u503c\u5750\u6807\u548c\u4fe1\u606f", None))
|
||||
|
||||
@ -348,6 +348,12 @@
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
@ -429,6 +435,12 @@
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
@ -456,6 +468,15 @@
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::ButtonSymbols::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
@ -587,7 +608,7 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<widget class="QCheckBox" name="checkBox_show_reference_line">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
@ -756,6 +777,10 @@
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
@ -765,6 +790,10 @@
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
|
||||
Reference in New Issue
Block a user