Compare commits

1 Commits

11 changed files with 266 additions and 299 deletions

View File

@ -0,0 +1,18 @@
from pathlib import Path
import pandas as pd
import numpy as np
samp_np = 10395
missing_second = 11495+11463-6300
missing_length = 17.29-2.81
fs = 500
missging_bcg = Path(rf"E:\code\DataCombine2023\ZD5Y2\OrgBCG_Text\{samp_np}\OrgBCG_Raw_500.txt")
bcg_data = pd.read_csv(missging_bcg, header=None).to_numpy().reshape(-1)
miss_start = int(missing_second * fs)
bcg_data_filled = np.concatenate([bcg_data[:miss_start],
np.full(int(missing_length * fs), np.mean(bcg_data)),
bcg_data[miss_start:]])
output_path = Path(rf"E:\code\DataCombine2023\ZD5Y2\OrgBCG_Text\{samp_np}\OrgBCG_Raw_500_filled.txt")
np.savetxt(output_path, bcg_data_filled, fmt="%d")

View File

@ -0,0 +1,71 @@
from pathlib import Path
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
from func.Filters.Preprocessing import Butterworth_for_ECG_PreProcess, Butterworth_for_BCG_PreProcess
# # 原始
# psg_dir = Path(r"E:\code\DataCombine2023\ZD5Y2\PSG_Text\10787")
# org_bcg_dir = Path(r"E:\code\DataCombine2023\ZD5Y2\OrgBCG_Text\10787")
# tho_file_path = psg_dir / "Effort Tho_Raw_100.txt"
# abd_file_path = psg_dir / "Effort Abd_Raw_100.txt"
# tho_fs = 100
# abd_fs = 100
# orgbcg_file_path = org_bcg_dir / "OrgBCG_Raw_500.txt"
# orgbcg_fs = 500
# 对齐后
psg_dir = Path(r"E:\code\DataCombine2023\ZD5Y2\PSG_Aligned\10787")
org_bcg_dir = Path(r"E:\code\DataCombine2023\ZD5Y2\OrgBCG_Aligned\10787")
tho_file_path = psg_dir / "Effort Tho_Sync_100.txt"
abd_file_path = psg_dir / "Effort Abd_Sync_100.txt"
tho_fs = 100
abd_fs = 100
orgbcg_file_path = org_bcg_dir / "OrgBCG_Sync_1000.txt"
orgbcg_fs = 1000
tho_raw = pd.read_csv(tho_file_path, header=None).to_numpy().reshape(-1)
abd_raw = pd.read_csv(abd_file_path, header=None).to_numpy().reshape(-1)
orgbcg_raw = pd.read_csv(orgbcg_file_path, header=None).to_numpy().reshape(-1)
tho_filtered = Butterworth_for_ECG_PreProcess(tho_raw, tho_fs, type="bandpass", low_cut=0.01, high_cut=15.0, order=4)
abd_filtered = Butterworth_for_ECG_PreProcess(abd_raw, abd_fs, type="bandpass", low_cut=0.01, high_cut=15.0, order=4)
orgbcg_filtered = Butterworth_for_BCG_PreProcess(orgbcg_raw, orgbcg_fs, type="bandpass", low_cut=0.01, high_cut=0.7, order=4)
# 降采样
orgbcg_filtered = orgbcg_filtered[::orgbcg_fs//10] # 从500Hz降采样到10Hz
tho_filtered = tho_filtered[::tho_fs//10] # 从100Hz降采样到10Hz
abd_filtered = abd_filtered[::abd_fs//10] # 从100Hz降采样到10Hz
plt.figure(figsize=(12, 8))
psg_x = np.linspace(0, len(tho_filtered) / 10, len(tho_filtered))
orgbcg_x = np.linspace(0, len(orgbcg_filtered) / 10, len(orgbcg_filtered))
plt.subplot(3, 1, 1)
plt.plot(psg_x, tho_filtered, label='Thoracic Effort', color='blue')
plt.title('Thoracic Effort Signal (Filtered)')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid()
plt.legend()
plt.subplot(3, 1, 2)
plt.plot(psg_x, abd_filtered, label='Abdominal Effort', color='green')
plt.title('Abdominal Effort Signal (Filtered)')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid()
plt.legend()
plt.subplot(3, 1, 3)
plt.plot(orgbcg_x, orgbcg_filtered, label='Original BCG', color='red')
plt.title('Original BCG Signal (Filtered)')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid()
plt.legend()
plt.tight_layout()
plt.show()

View File

@ -48,6 +48,7 @@ ButtonState = {
"radioButton_NTHO": False,
"radioButton_NABD": False,
"radioButton_custom": False,
"radioButton_customFreq": False,
"radioButton_freqTHO": False,
"radioButton_freqABD": False,
},
@ -71,6 +72,7 @@ ButtonState = {
"radioButton_NTHO": False,
"radioButton_NABD": False,
"radioButton_custom": False,
"radioButton_customFreq": False,
"radioButton_freqTHO": False,
"radioButton_freqABD": False,
}
@ -303,6 +305,7 @@ class MainWindow_approximately_align(QMainWindow):
self.ui.radioButton_custom.clicked.connect(self.__enableAlign__)
self.ui.radioButton_freqTHO.clicked.connect(self.__EstimateFrequencySelect__)
self.ui.radioButton_freqABD.clicked.connect(self.__EstimateFrequencySelect__)
self.ui.radioButton_customFreq.clicked.connect(self.__EstimateFrequencySelect__)
@overrides
def closeEvent(self, event):
@ -353,6 +356,7 @@ class MainWindow_approximately_align(QMainWindow):
self.ui.spinBox_SelectEpoch.setMinimum(0)
self.ui.radioButton_freqABD.setChecked(False)
self.ui.radioButton_freqTHO.setChecked(False)
self.ui.radioButton_customFreq.setChecked(False)
self.ui.radioButton_freqTHO.setText("备选1")
self.ui.radioButton_freqABD.setText("备选2")
@ -664,22 +668,22 @@ class MainWindow_approximately_align(QMainWindow):
response = self.data.estimate_frequency(tho_bias_list)
tho_y = response.data["estimate_y"]
tho_frequency = response.data["frequency"]
tho_frequency_ratio = response.data["frequency"]
tho_slope = response.data["slope"]
tho_intercept = response.data["intercept"]
response = self.data.estimate_frequency(abd_bias_list)
abd_y = response.data["estimate_y"]
abd_frequency = response.data["frequency"]
abd_frequency_ratio = response.data["frequency"]
abd_slope = response.data["slope"]
abd_intercept = response.data["intercept"]
result = self.__plot__(epoch_min, epoch_max, tho_bias_list, abd_bias_list, tho_y, abd_y,
tho_frequency, abd_frequency)
tho_frequency_ratio, abd_frequency_ratio)
Config["estimate"] = {}
Config["estimate"]["tho_frequency"] = tho_frequency
Config["estimate"]["tho_frequency"] = tho_frequency_ratio
Config["estimate"]["tho_slope"] = tho_slope
Config["estimate"]["tho_intercept"] = tho_intercept
Config["estimate"]["abd_frequency"] = abd_frequency
Config["estimate"]["abd_frequency"] = abd_frequency_ratio
Config["estimate"]["abd_slope"] = abd_slope
Config["estimate"]["abd_intercept"] = abd_intercept
@ -687,6 +691,7 @@ class MainWindow_approximately_align(QMainWindow):
self.ui.radioButton_freqABD.setText(str(Config["estimate"]["abd_frequency"] * Config["InputConfig"]["orgBcgFreq"]))
ButtonState["Current"]["radioButton_freqTHO"] = True
ButtonState["Current"]["radioButton_freqABD"] = True
ButtonState["Current"]["radioButton_customFreq"] = True
if not result.status:
PublicFunc.text_output(self.ui, "(1/1)" + result.info, Constants.TIPS_TYPE_ERROR)
@ -719,15 +724,30 @@ class MainWindow_approximately_align(QMainWindow):
def __EstimateFrequencySelect__(self):
PublicFunc.__disableAllButton__(self, ButtonState)
if self.ui.radioButton_freqTHO.isChecked():
frequency = Config["estimate"]["tho_frequency"]
Config["estimate_freq"] = frequency
frequency_ratio = Config["estimate"]["tho_frequency"]
Config["estimate_freq"] = frequency_ratio
Config["estimate_slope"] = Config["estimate"]["tho_slope"]
Config["estimate_intercept"] = Config["estimate"]["tho_intercept"]
elif self.ui.radioButton_freqABD.isChecked():
frequency = Config["estimate"]["abd_frequency"]
Config["estimate_freq"] = frequency
frequency_ratio = Config["estimate"]["abd_frequency"]
Config["estimate_freq"] = frequency_ratio
Config["estimate_slope"] = Config["estimate"]["abd_slope"]
Config["estimate_intercept"] = Config["estimate"]["abd_intercept"]
elif self.ui.radioButton_customFreq.isChecked():
# self.ui.lineEdit_customFreq.text()
try:
float(self.ui.lineEdit_customFreq.text())
except ValueError:
PublicFunc.msgbox_output(self, "自定义频率输入不合法,请输入数字类型数据!", Constants.MSGBOX_TYPE_ERROR)
PublicFunc.finish_operation(self, ButtonState)
return
frequency_ratio = float(self.ui.lineEdit_customFreq.text()) / Config["InputConfig"]["orgBcgFreq"]
Config["estimate_freq"] = frequency_ratio
Config["estimate_slope"] = None
Config["estimate_intercept"] = None
else:
return
@ -1046,12 +1066,12 @@ class MainWindow_approximately_align(QMainWindow):
return Result().success(info=Constants.DRAW_FINISHED)
def DrawAlignScatter(self, epoch_min, epoch_max, tho_bias_list, abd_bias_list, tho_y, abd_y,
tho_frequency, abd_frequency):
tho_frequency_ratio, abd_frequency_ratio):
try:
ax1 = self.fig.add_subplot(211)
ax1.scatter(linspace(epoch_min, epoch_max, len(tho_bias_list)), tho_bias_list, alpha=0.2)
ax1.plot(linspace(epoch_min, epoch_max, len(tho_bias_list)), tho_y, color='orange',
label=f"THO Frequency: {tho_frequency} Hz")
label=f"THO Frequency_ratio: {tho_frequency_ratio}")
ax1.axhline(y=0, color='red', linestyle='--', alpha=0.3)
ax1.set_xlabel("Epoch")
ax1.set_ylabel("Tho Bias / s")
@ -1061,7 +1081,7 @@ class MainWindow_approximately_align(QMainWindow):
ax2 = self.fig.add_subplot(212)
ax2.scatter(linspace(epoch_min, epoch_max, len(abd_bias_list)), abd_bias_list, alpha=0.2)
ax2.plot(linspace(epoch_min, epoch_max, len(abd_bias_list)), abd_y, color='orange',
label=f"ABD Frequency: {abd_frequency} Hz")
label=f"ABD Frequency_ratio: {abd_frequency_ratio}")
ax2.axhline(y=0, color='red', linestyle='--', alpha=0.3)
ax2.set_xlabel("Epoch")
ax2.set_ylabel("Abd Bias / s")
@ -1260,12 +1280,12 @@ class Data:
if Config["PSGConfig"]["PSGDelBase"]:
# 减去四秒钟平均滤波
self.processed_Tho = self.processed_Tho - convolve(
self.processed_Tho, ones(int(4 * temp_frequency)) / int(4 * temp_frequency), mode='same')
self.processed_Tho, ones(int(10 * temp_frequency)) / int(10 * temp_frequency), mode='same')
self.processed_Abd = self.processed_Abd - convolve(
self.processed_Abd, ones(int(4 * temp_frequency)) / int(4 * temp_frequency), mode='same')
self.processed_Abd, ones(int(10 * temp_frequency)) / int(10 * temp_frequency), mode='same')
if Config["orgBcgConfig"]["orgBcgDelBase"]:
self.processed_orgBcg = self.processed_orgBcg - convolve(
self.processed_orgBcg, ones(int(4 * temp_frequency)) / int(4 * temp_frequency), mode='same')
self.processed_orgBcg, ones(int(10 * temp_frequency)) / int(10 * temp_frequency), mode='same')
except Exception as e:
return Result().failure(
info=Constants.APPROXIMATELY_DELETE_BASE_FAILURE + Constants.FAILURE_REASON[
@ -1306,9 +1326,16 @@ class Data:
try:
# 用[::]完成
temp_frequency = Config["TempFrequency"]
self.processed_downsample_Tho = self.processed_Tho[::int(temp_frequency / Config["ApplyFrequency"])]
self.processed_downsample_Abd = self.processed_Abd[::int(temp_frequency / Config["ApplyFrequency"])]
self.processed_downsample_orgBcg = self.processed_orgBcg[::int(temp_frequency / Config["ApplyFrequency"])]
# self.processed_downsample_Tho = self.processed_Tho[::int(temp_frequency / Config["ApplyFrequency"])]
# self.processed_downsample_Abd = self.processed_Abd[::int(temp_frequency / Config["ApplyFrequency"])]
# self.processed_downsample_orgBcg = self.processed_orgBcg[::int(temp_frequency / Config["ApplyFrequency"])]
# 用resample完成
self.processed_downsample_Tho = resample(
self.processed_Tho, int(Config["PSG_seconds"] * Config["ApplyFrequency"]))
self.processed_downsample_Abd = resample(
self.processed_Abd, int(Config["PSG_seconds"] * Config["ApplyFrequency"]))
self.processed_downsample_orgBcg = resample(
self.processed_orgBcg, int(Config["orgBcg_seconds"] * Config["ApplyFrequency"]))
except Exception as e:
@ -1333,10 +1360,10 @@ class Data:
v = self.processed_downsample_orgBcg[
Config["orgBcgConfig"]["PreCut"]:len(self.processed_downsample_orgBcg) - Config["orgBcgConfig"][
"PostCut"]].copy()
a *= MULTIPLE_FACTOER
v *= MULTIPLE_FACTOER
a = a.astype(int64)
v = v.astype(int64)
# a *= MULTIPLE_FACTOER
# v *= MULTIPLE_FACTOER
# a = a.astype(int64)
# v = v.astype(int64)
tho_relate = correlate(a, v, mode='full')
tho_relate = tho_relate / (MULTIPLE_FACTOER ** 2)
tho_relate2 = - tho_relate
@ -1358,12 +1385,12 @@ class Data:
v = self.processed_downsample_orgBcg[
Config["orgBcgConfig"]["PreCut"]:len(self.processed_downsample_orgBcg) - Config["orgBcgConfig"][
"PostCut"]].copy()
a *= 100
v *= 100
a = a.astype(int64)
v = v.astype(int64)
# a *= 100
# v *= 100
# a = a.astype(int64)
# v = v.astype(int64)
abd_relate = correlate(a, v, mode='full')
abd_relate = abd_relate / 10000
# abd_relate = abd_relate / 10000
abd_relate2 = - abd_relate
result = {"abd_relate": abd_relate, "abd_relate2": abd_relate2}
@ -1397,7 +1424,7 @@ class Data:
# 获取epoch
try:
epoch_second = Params.APPROXIMATELY_ALIGN_CONFIG_NEW_CONTENT["Second_PerEpoch"]
epoch_min = max(0, Config["pos"] // epoch_second // Config["ApplyFrequency"] + 1)
epoch_min = max(0, Config["pos"] // (epoch_second * Config["ApplyFrequency"])) + 1
epoch_max = min(len(self.processed_downsample_Tho) // epoch_second // Config["ApplyFrequency"] - 1,
(len(self.processed_downsample_orgBcg) + Config["pos"]) // epoch_second // Config[
"ApplyFrequency"] - 1)
@ -1476,16 +1503,17 @@ class Data:
if slope != 0:
drift_rate = slope / epoch_second
# frequency = temp_freq * (1 - drift_rate)
frequency = 1 - drift_rate
# frequency_ratio = 1 - drift_rate
frequency_ratio = 1 / (1 + drift_rate)
else:
# frequency = float(temp_freq)
frequency = 1
frequency_ratio = 1
theilsen_y = theilsen.predict(X)
return Result().success(info=Constants.APPROXIMATELY_ESTIMATE_FREQUENCY_FINISHED,
data={"estimate_y": theilsen_y,
"frequency": frequency,
"frequency": frequency_ratio,
"slope": slope,
"intercept": theilsen.intercept_},
)

View File

@ -420,7 +420,7 @@ class Data:
self.alignInfo = read_csv(Path(Config["Path"]["InputAlignInfo"]),
encoding=Params.UTF8_ENCODING,
header=None).to_numpy().reshape(-1)
cleaned_str = re.sub(r'np\.(int64|float64|float32|int32)\((.*?)\)', r'\2', self.alignInfo[0])
cleaned_str = re.sub(r'np\.\w+\(\s*([^)]+?)\s*\)', r'\1', self.alignInfo[0])
self.alignInfo = literal_eval(cleaned_str)
except Exception as e:

View File

@ -183,7 +183,7 @@ class MainWindow(QMainWindow, Ui_Signal_Label):
self.check_save_path_and_mkdir(root_path, sampID)
def __slot_btn_preprocess__(self):
self.preprocess = MainWindow_preprocess(Config["Plot_Mode"])
self.preprocess = MainWindow_preprocess()
sender = self.sender()
root_path = self.ui.plainTextEdit_root_path.toPlainText()

View File

@ -7,12 +7,9 @@ from PySide6.QtWidgets import QMessageBox, QMainWindow, QApplication
from matplotlib import gridspec
from matplotlib.backends.backend_qt import NavigationToolbar2QT
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
from numpy import column_stack, arange
from overrides import overrides
from pandas import read_csv, DataFrame
from scipy.signal import resample
from vispy import scene
from vispy.scene import visuals
from yaml import dump, load, FullLoader
from func.utils.ConfigParams import Filename, Params
@ -20,7 +17,6 @@ from func.utils.PublicFunc import PublicFunc
from func.utils.Constants import Constants
from func.Filters.Preprocessing import Butterworth_for_BCG_PreProcess, Butterworth_for_ECG_PreProcess
from func.utils.Result import Result
from func.utils.FloatingImagePanel import add_floating_image_panel
from ui.MainWindow.MainWindow_preprocess import Ui_MainWindow_preprocess
from ui.setting.preprocess_input_setting import Ui_MainWindow_preprocess_input_setting
@ -171,7 +167,7 @@ class SettingWindow(QMainWindow):
class MainWindow_preprocess(QMainWindow):
def __init__(self, plot_mode):
def __init__(self):
super(MainWindow_preprocess, self).__init__()
self.ui = Ui_MainWindow_preprocess()
self.ui.setupUi(self)
@ -188,30 +184,12 @@ class MainWindow_preprocess(QMainWindow):
self.progressbar = None
PublicFunc.add_progressbar(self)
self.image_overlay = add_floating_image_panel(
self.centralWidget(),
title="参考图例",
img_path=r"image\legend_preprocess.png"
)
self.plot_mode = plot_mode
if self.plot_mode == "matplotlib":
#初始化画框
self.fig = None
self.canvas = None
self.figToolbar = None
self.gs = None
self.ax0 = None
elif self.plot_mode == "vispy":
# 初始化画框
self.canvas = None
self.view = None
self.y_axis = None
self.x_axis = None
self.view = None
self.grid_lines = None
self.line_original = None
self.line_processed = None
#初始化画框
self.fig = None
self.canvas = None
self.figToolbar = None
self.gs = None
self.ax0 = None
self.ui.textBrowser_info.setStyleSheet("QTextBrowser { background-color: rgb(255, 255, 200); }")
PublicFunc.__styleAllButton__(self, ButtonState)
@ -228,50 +206,20 @@ class MainWindow_preprocess(QMainWindow):
self.setting = SettingWindow(mode, root_path, sampID)
if self.plot_mode == "matplotlib":
# 初始化画框
self.fig = plt.figure(figsize=(12, 9), dpi=100)
self.canvas = FigureCanvasQTAgg(self.fig)
self.figToolbar = NavigationToolbar2QT(self.canvas)
for action in self.figToolbar.actions():
if action.text() == "Subplots" or action.text() == "Customize":
self.figToolbar.removeAction(action)
self.ui.verticalLayout_canvas.addWidget(self.canvas)
self.ui.verticalLayout_canvas.addWidget(self.figToolbar)
self.gs = gridspec.GridSpec(1, 1, height_ratios=[1])
self.fig.subplots_adjust(top=0.98, bottom=0.05, right=0.98, left=0.1, hspace=0, wspace=0)
self.ax0 = self.fig.add_subplot(self.gs[0])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
elif self.plot_mode == "vispy":
# 初始化画框
self.canvas = scene.SceneCanvas(keys='interactive', show=True, bgcolor='white')
self.ui.verticalLayout_canvas.addWidget(self.canvas.native)
self.main_grid = self.canvas.central_widget.add_grid(spacing=0)
self.y_axis = scene.AxisWidget(orientation='left',
axis_color='black',
tick_color='black',
text_color='black',
axis_font_size=4,
tick_font_size=4,
tick_label_margin=20)
self.y_axis.width_max = 80
self.x_axis = scene.AxisWidget(orientation='bottom',
axis_color='black',
tick_color='black',
text_color='black',
axis_font_size=4,
tick_font_size=4,
tick_label_margin=20)
self.x_axis.height_max = 40
self.view = self.main_grid.add_view(row=0, col=1, camera='panzoom')
self.main_grid.add_widget(self.y_axis, row=0, col=0)
self.main_grid.add_widget(self.x_axis, row=1, col=1)
self.x_axis.link_view(self.view)
self.y_axis.link_view(self.view)
self.grid_lines = visuals.GridLines(color=(0.3, 0.3, 0.3, 0.5), parent=self.view.scene)
self.grid_lines.set_gl_state(line_width=1)
self.grid_lines.order = 100
# 初始化画框
self.fig = plt.figure(figsize=(12, 9), dpi=100)
self.canvas = FigureCanvasQTAgg(self.fig)
self.figToolbar = NavigationToolbar2QT(self.canvas)
for action in self.figToolbar.actions():
if action.text() == "Subplots" or action.text() == "Customize":
self.figToolbar.removeAction(action)
self.ui.verticalLayout_canvas.addWidget(self.canvas)
self.ui.verticalLayout_canvas.addWidget(self.figToolbar)
self.gs = gridspec.GridSpec(1, 1, height_ratios=[1])
self.fig.subplots_adjust(top=0.98, bottom=0.05, right=0.98, left=0.1, hspace=0, wspace=0)
self.ax0 = self.fig.add_subplot(self.gs[0])
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
PublicFunc.__resetAllButton__(self, ButtonState)
@ -305,17 +253,14 @@ class MainWindow_preprocess(QMainWindow):
QApplication.processEvents()
# 清空画框
if self.plot_mode == "matplotlib":
if self.ax0 is not None:
self.ax0.clear()
self.fig.clf()
plt.close(self.fig)
elif self.plot_mode == "vispy":
self.canvas.close()
if self.ax0 is not None:
self.ax0.clear()
# 释放资源
self.setting.close()
del self.data
self.fig.clf()
plt.close(self.fig)
self.deleteLater()
collect()
self.canvas = None
@ -328,53 +273,23 @@ class MainWindow_preprocess(QMainWindow):
def __plot__(self):
# 清空画框
if self.plot_mode == "matplotlib":
self.reset_axes()
sender = self.sender()
if sender == self.ui.pushButton_view:
self.ax0.plot(self.data.raw_data,
color=Constants.PLOT_COLOR_RED,
label=Constants.PREPROCESS_PLOT_LABEL_ORIGINAL_DATA)
self.ax0.plot(self.data.processed_data + Constants.PREPROCESS_OUTPUT_INPUT_AMP_OFFSET,
color=Constants.PLOT_COLOR_BLUE,
label=Constants.PREPROCESS_PLOT_LABEL_PROCESSED_DATA)
self.ax0.legend(loc=Constants.PLOT_UPPER_RIGHT)
self.canvas.draw()
return Result().success(info=Constants.DRAW_FINISHED)
else:
self.canvas.draw()
return Result().failure(info=Constants.DRAW_FAILURE)
elif self.plot_mode == "vispy":
sender = self.sender()
if self.line_original is not None:
self.line_original.parent = None
if self.line_processed is not None:
self.line_processed.parent = None
if sender == self.ui.pushButton_view:
t = arange(len(self.data.raw_data))
raw_data_2d = column_stack((t, self.data.raw_data))
self.line_original = visuals.Line(raw_data_2d,
color=Constants.PLOT_COLOR_RED,
parent=self.view.scene,
antialias=False,
width=2,
method='gl')
processed_y = self.data.processed_data + Constants.PREPROCESS_OUTPUT_INPUT_AMP_OFFSET
processed_data_2d = column_stack((t, processed_y))
self.line_processed = visuals.Line(processed_data_2d,
color=Constants.PLOT_COLOR_BLUE,
parent=self.view.scene,
antialias=False,
width=2,
method='gl')
self.line_original.order = 0
self.line_processed.order = -1
self.view.camera.set_range()
self.canvas.update()
return Result().success(info=Constants.DRAW_FINISHED)
else:
self.reset_axes()
return Result().failure(info=Constants.DRAW_FAILURE)
sender = self.sender()
if sender == self.ui.pushButton_view:
self.ax0.plot(self.data.raw_data,
color=Constants.PLOT_COLOR_RED,
label=Constants.PREPROCESS_PLOT_LABEL_ORIGINAL_DATA)
self.ax0.plot(self.data.processed_data + Constants.PREPROCESS_OUTPUT_INPUT_AMP_OFFSET,
color=Constants.PLOT_COLOR_BLUE,
label=Constants.PREPROCESS_PLOT_LABEL_PROCESSED_DATA)
self.ax0.legend(loc=Constants.PLOT_UPPER_RIGHT)
self.canvas.draw()
return Result().success(info=Constants.DRAW_FINISHED)
else:
self.canvas.draw()
return Result().success(info=Constants.DRAW_FAILURE)
def __update_config__(self):
if self.mode == "BCG":
@ -391,12 +306,10 @@ class MainWindow_preprocess(QMainWindow):
def __slot_btn_input__(self):
PublicFunc.__disableAllButton__(self, ButtonState)
if self.plot_mode == "matplotlib":
# 清空画框
self.reset_axes()
self.canvas.draw()
elif self.plot_mode == "vispy":
self.canvas.update()
# 清空画框
self.reset_axes()
self.canvas.draw()
self.data = Data()
@ -499,18 +412,6 @@ class MainWindow_preprocess(QMainWindow):
self.ax0.grid(True)
self.ax0.xaxis.set_major_formatter(Params.FORMATTER)
def update_overlay_position(self):
"""手动定位函数"""
margin = 20
x = self.width() - self.image_overlay.width() - margin
y = margin
self.image_overlay.move(x, y)
def resizeEvent(self, event):
"""确保窗口变大小时,悬浮窗依然在右上角"""
super().resizeEvent(event)
self.update_overlay_position()
class Data:

View File

@ -76,8 +76,7 @@ class Params:
PUBLIC_CONFIG_NEW_CONTENT = {
"Path": {
"Root": ""
},
"Plot_Mode": "matplotlib"
}
}
UTF8_ENCODING: str = "utf-8"
GBK_ENCODING: str = "gbk"

View File

@ -1,95 +0,0 @@
from PySide6 import QtWidgets, QtCore, QtGui
class FloatingImagePanel(QtWidgets.QWidget):
def __init__(self, parent, title="原始比例预览", image_path=None):
super().__init__(parent)
self.is_expanded = True
# 1. 样式配置 (保持深色风格,方便看清信号)
self.setAttribute(QtCore.Qt.WA_StyledBackground, True)
self.setStyleSheet("""
FloatingImagePanel {
background-color: rgba(30, 30, 30, 220);
border: 2px solid #444;
border-radius: 4px;
}
QLabel#title_label { color: #ffffff; font-weight: bold; font-family: 'Consolas'; }
QPushButton#toggle_btn { background: #444; color: white; border: none; }
""")
# 2. 布局初始化
self.main_layout = QtWidgets.QVBoxLayout(self)
self.main_layout.setContentsMargins(4, 4, 4, 4)
self.main_layout.setSpacing(2)
# --- 标题栏 ---
self.header = QtWidgets.QWidget()
header_layout = QtWidgets.QHBoxLayout(self.header)
header_layout.setContentsMargins(2, 2, 2, 2)
self.title_label = QtWidgets.QLabel(title)
self.title_label.setObjectName("title_label")
self.toggle_btn = QtWidgets.QPushButton("")
self.toggle_btn.setFixedSize(22, 22)
header_layout.addWidget(self.title_label)
header_layout.addStretch()
header_layout.addWidget(self.toggle_btn)
self.main_layout.addWidget(self.header)
# --- 图片展示区 ---
self.image_label = QtWidgets.QLabel()
# 关键点 1关闭自动填充确保我们手动控制尺寸
self.image_label.setScaledContents(False)
# 关键点 2设置对齐方式为中心
self.image_label.setAlignment(QtCore.Qt.AlignCenter)
self.main_layout.addWidget(self.image_label)
# 3. 信号绑定
self.toggle_btn.clicked.connect(self.toggle_content)
# 4. 加载图片
if image_path:
self.update_image(image_path)
def update_image(self, path):
"""完全根据图片的物理尺寸调整窗口"""
pixmap = QtGui.QPixmap(path)
if not pixmap.isNull():
# 拿到图片的原始宽高
w = pixmap.width()
h = pixmap.height()
# 强制 Label 等于图片大小
self.image_label.setFixedSize(w, h)
self.image_label.setPixmap(pixmap)
# 让整个窗口重新计算布局,贴合 Label
self.adjustSize()
# 保持展开状态
self.set_expanded(True)
def set_expanded(self, expanded: bool):
self.is_expanded = expanded
self.image_label.setVisible(expanded)
self.toggle_btn.setText("" if expanded else "")
# 关键点 3重置窗口大小
# 展开时它会变大包住图片,收起时它会缩成标题栏大小
self.adjustSize()
# 通知父窗口刷新位置,防止因为变大而超出右边界
if hasattr(self.parent(), 'update_overlay_position'):
self.parent().update_overlay_position()
def toggle_content(self):
self.set_expanded(not self.is_expanded)
# --- 封装的调用函数 ---
def add_floating_image_panel(parent_widget, title="图片原尺寸", img_path=None):
panel = FloatingImagePanel(parent_widget, title, img_path)
panel.raise_()
return panel

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -16,10 +16,10 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QAbstractSpinBox, QApplication, QCheckBox, QGridLayout,
QGroupBox, QHBoxLayout, QLabel, QMainWindow,
QPushButton, QRadioButton, QSizePolicy, QSpacerItem,
QSpinBox, QStatusBar, QTextBrowser, QVBoxLayout,
QWidget)
QGroupBox, QHBoxLayout, QLabel, QLineEdit,
QMainWindow, QPushButton, QRadioButton, QSizePolicy,
QSpacerItem, QSpinBox, QStatusBar, QTextBrowser,
QVBoxLayout, QWidget)
class Ui_MainWindow_approximately_align(object):
def setupUi(self, MainWindow_approximately_align):
@ -400,26 +400,43 @@ class Ui_MainWindow_approximately_align(object):
self.groupBox_2.setMinimumSize(QSize(0, 0))
self.layoutWidget = QWidget(self.groupBox_2)
self.layoutWidget.setObjectName(u"layoutWidget")
self.layoutWidget.setGeometry(QRect(11, 18, 401, 41))
self.layoutWidget.setGeometry(QRect(11, 18, 411, 60))
self.verticalLayout_3 = QVBoxLayout(self.layoutWidget)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_3 = QHBoxLayout()
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.radioButton_freqTHO = QRadioButton(self.layoutWidget)
self.radioButton_freqTHO.setObjectName(u"radioButton_freqTHO")
self.radioButton_freqTHO.setFont(font1)
self.gridLayout_5 = QGridLayout()
self.gridLayout_5.setObjectName(u"gridLayout_5")
self.radioButton_customFreq = QRadioButton(self.layoutWidget)
self.radioButton_customFreq.setObjectName(u"radioButton_customFreq")
self.radioButton_customFreq.setFont(font1)
self.horizontalLayout_3.addWidget(self.radioButton_freqTHO)
self.gridLayout_5.addWidget(self.radioButton_customFreq, 1, 0, 1, 1)
self.radioButton_freqABD = QRadioButton(self.layoutWidget)
self.radioButton_freqABD.setObjectName(u"radioButton_freqABD")
self.radioButton_freqABD.setFont(font1)
self.horizontalLayout_3.addWidget(self.radioButton_freqABD)
self.gridLayout_5.addWidget(self.radioButton_freqABD, 0, 1, 1, 1)
self.radioButton_freqTHO = QRadioButton(self.layoutWidget)
self.radioButton_freqTHO.setObjectName(u"radioButton_freqTHO")
self.radioButton_freqTHO.setFont(font1)
self.gridLayout_5.addWidget(self.radioButton_freqTHO, 0, 0, 1, 1)
self.lineEdit_customFreq = QLineEdit(self.layoutWidget)
self.lineEdit_customFreq.setObjectName(u"lineEdit_customFreq")
sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.lineEdit_customFreq.sizePolicy().hasHeightForWidth())
self.lineEdit_customFreq.setSizePolicy(sizePolicy1)
self.lineEdit_customFreq.setFont(font1)
self.gridLayout_5.addWidget(self.lineEdit_customFreq, 1, 1, 1, 1)
self.verticalLayout_3.addLayout(self.horizontalLayout_3)
self.verticalLayout_3.addLayout(self.gridLayout_5)
self.verticalLayout.addWidget(self.groupBox_2)
@ -530,7 +547,7 @@ class Ui_MainWindow_approximately_align(object):
self.verticalLayout.setStretch(2, 3)
self.verticalLayout.setStretch(3, 4)
self.verticalLayout.setStretch(4, 3)
self.verticalLayout.setStretch(5, 2)
self.verticalLayout.setStretch(5, 3)
self.verticalLayout.setStretch(6, 4)
self.verticalLayout.setStretch(7, 1)
self.verticalLayout.setStretch(8, 6)
@ -607,8 +624,9 @@ class Ui_MainWindow_approximately_align(object):
self.pushButton_GetPos.setText(QCoreApplication.translate("MainWindow_approximately_align", u"\u8ba1\u7b97\u5bf9\u9f50", None))
self.radioButton_NABD.setText(QCoreApplication.translate("MainWindow_approximately_align", u"\u5907\u90094", None))
self.groupBox_2.setTitle(QCoreApplication.translate("MainWindow_approximately_align", u"\u91c7\u6837\u7387\u4f30\u8ba1", None))
self.radioButton_freqTHO.setText(QCoreApplication.translate("MainWindow_approximately_align", u"\u5907\u90091", None))
self.radioButton_customFreq.setText(QCoreApplication.translate("MainWindow_approximately_align", u"\u81ea\u5b9a\u4e49", None))
self.radioButton_freqABD.setText(QCoreApplication.translate("MainWindow_approximately_align", u"\u5907\u90092", None))
self.radioButton_freqTHO.setText(QCoreApplication.translate("MainWindow_approximately_align", u"\u5907\u90091", None))
self.groupBox_view_partially.setTitle(QCoreApplication.translate("MainWindow_approximately_align", u"\u5c40\u90e8\u89c2\u6d4b", None))
self.label_9.setText(QCoreApplication.translate("MainWindow_approximately_align", u"Epoch\uff1a", None))
self.pushButton_JUMP.setText(QCoreApplication.translate("MainWindow_approximately_align", u"\u8df3\u8f6c", None))

View File

@ -25,7 +25,7 @@
<property name="title">
<string>数据粗同步</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,1,3,4,3,2,4,1,6">
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,1,3,4,3,3,4,1,6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
@ -728,14 +728,38 @@
<rect>
<x>11</x>
<y>18</y>
<width>401</width>
<height>41</height>
<width>411</width>
<height>60</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QGridLayout" name="gridLayout_5">
<item row="1" column="0">
<widget class="QRadioButton" name="radioButton_customFreq">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>自定义</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="radioButton_freqABD">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>备选2</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="radioButton_freqTHO">
<property name="font">
<font>
@ -747,16 +771,19 @@
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_freqABD">
<item row="1" column="1">
<widget class="QLineEdit" name="lineEdit_customFreq">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>备选2</string>
</property>
</widget>
</item>
</layout>