1、精简部分公共代码到PublicFunc.py中
2、完成了<人工纠正>的所有代码
This commit is contained in:
@ -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
|
||||
Reference in New Issue
Block a user