438 lines
19 KiB
Python
438 lines
19 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""
|
|||
|
|
结果预览选项卡
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import customtkinter as ctk
|
|||
|
|
import matplotlib.pyplot as plt
|
|||
|
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
|
|||
|
|
import numpy as np
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
class ResultPreviewTab(ctk.CTkFrame):
|
|||
|
|
def __init__(self, parent):
|
|||
|
|
super().__init__(parent)
|
|||
|
|
|
|||
|
|
self.grid_columnconfigure(0, weight=1)
|
|||
|
|
self.grid_rowconfigure(0, weight=1)
|
|||
|
|
|
|||
|
|
viz_frame = ctk.CTkFrame(self, fg_color="#2b2b2b")
|
|||
|
|
viz_frame.grid(row=0, column=0, sticky="nsew")
|
|||
|
|
viz_frame.grid_columnconfigure(0, weight=1)
|
|||
|
|
viz_frame.grid_rowconfigure(0, weight=0)
|
|||
|
|
viz_frame.grid_rowconfigure(1, weight=1)
|
|||
|
|
|
|||
|
|
ctk.CTkLabel(
|
|||
|
|
viz_frame,
|
|||
|
|
text="可视化预览",
|
|||
|
|
font=ctk.CTkFont(size=14, weight="bold"),
|
|||
|
|
text_color="white"
|
|||
|
|
).grid(row=0, column=0, sticky="w", padx=10, pady=10)
|
|||
|
|
|
|||
|
|
self.chart_frame = ctk.CTkFrame(viz_frame, fg_color="#2b2b2b")
|
|||
|
|
self.chart_frame.grid(row=1, column=0, sticky="nsew", padx=5, pady=5)
|
|||
|
|
self.chart_frame.grid_columnconfigure(0, weight=1)
|
|||
|
|
self.chart_frame.grid_rowconfigure(0, weight=1)
|
|||
|
|
|
|||
|
|
self.fig = None
|
|||
|
|
self.canvas = None
|
|||
|
|
|
|||
|
|
self.update_chart([])
|
|||
|
|
|
|||
|
|
def update_chart(self, events, detector_configs=None):
|
|||
|
|
"""更新图表"""
|
|||
|
|
# 清空图表框架
|
|||
|
|
for widget in self.chart_frame.winfo_children():
|
|||
|
|
widget.destroy()
|
|||
|
|
|
|||
|
|
if not events:
|
|||
|
|
ctk.CTkLabel(
|
|||
|
|
self.chart_frame,
|
|||
|
|
text="暂无数据",
|
|||
|
|
font=ctk.CTkFont(size=16),
|
|||
|
|
text_color="white"
|
|||
|
|
).pack(expand=True)
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
timestamps = {0: [], 1: [], 2: []}
|
|||
|
|
energies = {0: [], 1: [], 2: []}
|
|||
|
|
|
|||
|
|
from core.encoder import BitFieldEncoder
|
|||
|
|
encoder = BitFieldEncoder()
|
|||
|
|
|
|||
|
|
from core.simulator import SampleSpaceGenerator
|
|||
|
|
sample_generator = SampleSpaceGenerator()
|
|||
|
|
|
|||
|
|
# 使用传入的探测器配置,如果没有则使用默认配置
|
|||
|
|
if detector_configs is None:
|
|||
|
|
detector_configs = {
|
|||
|
|
"detector1": {
|
|||
|
|
"energy_distribution": {"type": "normal", "mean": 1000.0, "std": 200.0},
|
|||
|
|
"timestamp_distribution": {"type": "exponential", "scale": 50.0}
|
|||
|
|
},
|
|||
|
|
"detector2": {
|
|||
|
|
"energy_distribution": {"type": "normal", "mean": 800.0, "std": 150.0},
|
|||
|
|
"timestamp_distribution": {"type": "uniform", "low": 0.0, "high": 200.0}
|
|||
|
|
},
|
|||
|
|
"detector3": {
|
|||
|
|
"energy_distribution": {"type": "gamma", "shape": 2.0, "scale": 500.0},
|
|||
|
|
"timestamp_distribution": {"type": "normal", "mean": 100.0, "std": 30.0}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for event in events:
|
|||
|
|
for signal in event:
|
|||
|
|
if signal != 0:
|
|||
|
|
decoded = encoder.decode(signal)
|
|||
|
|
# 为每个探测器单独收集时间戳和能量
|
|||
|
|
for i in range(3):
|
|||
|
|
if decoded['detector_fired'][i]: # 如果该探测器点火
|
|||
|
|
timestamps[i].append(decoded['timestamp'])
|
|||
|
|
energies[i].append(decoded['energies'][i])
|
|||
|
|
|
|||
|
|
# 增大字体大小以匹配左侧面板(再大两号)
|
|||
|
|
label_fontsize = 10
|
|||
|
|
title_fontsize = 10
|
|||
|
|
tick_fontsize = 10
|
|||
|
|
legend_fontsize = 10
|
|||
|
|
|
|||
|
|
# 使用固定大小,确保每次更新图表大小一致
|
|||
|
|
self.fig = plt.figure(figsize=(16, 12), dpi=100)
|
|||
|
|
self.fig.patch.set_facecolor('#2b2b2b')
|
|||
|
|
|
|||
|
|
colors = ['#ff6b6b', '#4ecdc4', '#45b7d1']
|
|||
|
|
labels = ['Detector 1', 'Detector 2', 'Detector 3']
|
|||
|
|
markers = ['o', 's', '^'] # 不同的标记:圆圈、方块、三角形
|
|||
|
|
|
|||
|
|
# 减小图表之间的间隔,增大图表大小
|
|||
|
|
plt.subplots_adjust(hspace=0.4, wspace=0.25, left=0.06, right=0.98, top=0.98, bottom=0.06)
|
|||
|
|
|
|||
|
|
# 第1-3张图:探测器1-3的信号时间分布
|
|||
|
|
for i in range(3):
|
|||
|
|
ax = self.fig.add_subplot(3, 3, i+1)
|
|||
|
|
if timestamps[i]:
|
|||
|
|
ax.hist(timestamps[i], bins=20, alpha=0.7, color=colors[i])
|
|||
|
|
ax.set_xlabel('Timestamp (us)', fontsize=label_fontsize)
|
|||
|
|
ax.set_ylabel('Count', fontsize=label_fontsize)
|
|||
|
|
ax.set_title(f'{labels[i]} - Signal Time Distribution', fontsize=title_fontsize, fontweight='bold')
|
|||
|
|
ax.grid(True, alpha=0.3)
|
|||
|
|
ax.set_facecolor('#1e1e1e')
|
|||
|
|
ax.tick_params(colors='white', labelsize=tick_fontsize)
|
|||
|
|
ax.xaxis.label.set_color('white')
|
|||
|
|
ax.yaxis.label.set_color('white')
|
|||
|
|
ax.title.set_color('white')
|
|||
|
|
for spine in ax.spines.values():
|
|||
|
|
spine.set_color('#444444')
|
|||
|
|
|
|||
|
|
# 第4-6张图:探测器1-3的信号能量分布
|
|||
|
|
for i in range(3):
|
|||
|
|
ax = self.fig.add_subplot(3, 3, i+4)
|
|||
|
|
if energies[i]:
|
|||
|
|
ax.hist(energies[i], bins=20, alpha=0.7, color=colors[i])
|
|||
|
|
ax.set_xlabel('Energy (keV)', fontsize=label_fontsize)
|
|||
|
|
ax.set_ylabel('Count', fontsize=label_fontsize)
|
|||
|
|
ax.set_title(f'{labels[i]} - Signal Energy Distribution', fontsize=title_fontsize, fontweight='bold')
|
|||
|
|
ax.grid(True, alpha=0.3)
|
|||
|
|
ax.set_facecolor('#1e1e1e')
|
|||
|
|
ax.tick_params(colors='white', labelsize=tick_fontsize)
|
|||
|
|
ax.xaxis.label.set_color('white')
|
|||
|
|
ax.yaxis.label.set_color('white')
|
|||
|
|
ax.title.set_color('white')
|
|||
|
|
for spine in ax.spines.values():
|
|||
|
|
spine.set_color('#444444')
|
|||
|
|
|
|||
|
|
# 第7张图:3个探测器信号在时间-能量平面上的散点图(占据整行)
|
|||
|
|
ax = self.fig.add_subplot(3, 1, 3)
|
|||
|
|
for i in range(3):
|
|||
|
|
if timestamps[i] and energies[i]:
|
|||
|
|
ax.scatter(timestamps[i], energies[i],
|
|||
|
|
c=colors[i], marker=markers[i],
|
|||
|
|
s=30, alpha=0.6, label=labels[i])
|
|||
|
|
ax.set_xlabel('Timestamp (us)', fontsize=label_fontsize)
|
|||
|
|
ax.set_ylabel('Energy (keV)', fontsize=label_fontsize)
|
|||
|
|
ax.set_title('Detector Signals in Time-Energy Space', fontsize=title_fontsize, fontweight='bold')
|
|||
|
|
ax.legend(fontsize=legend_fontsize)
|
|||
|
|
ax.grid(True, alpha=0.3)
|
|||
|
|
ax.set_facecolor('#1e1e1e')
|
|||
|
|
ax.tick_params(colors='white', labelsize=tick_fontsize)
|
|||
|
|
ax.xaxis.label.set_color('white')
|
|||
|
|
ax.yaxis.label.set_color('white')
|
|||
|
|
ax.title.set_color('white')
|
|||
|
|
for spine in ax.spines.values():
|
|||
|
|
spine.set_color('#444444')
|
|||
|
|
|
|||
|
|
# # 第7-9张图:探测器1-3的样本空间分布(能量+时间,使用双Y轴)
|
|||
|
|
# for i in range(3):
|
|||
|
|
# ax = self.fig.add_subplot(3, 3, i+7)
|
|||
|
|
# detector_key = f"detector{i+1}"
|
|||
|
|
|
|||
|
|
# # 使用generate_sample_space方法生成样本空间(一次生成能量和时间戳)
|
|||
|
|
# detector_config = detector_configs[detector_key].copy()
|
|||
|
|
# detector_config['name'] = detector_key
|
|||
|
|
# sample_space = sample_generator.generate_sample_space(detector_config)
|
|||
|
|
# energy_data = sample_space[:, 0] # 第一列是能量
|
|||
|
|
# timestamp_data = sample_space[:, 1] # 第二列是时间戳
|
|||
|
|
|
|||
|
|
# # 创建双Y轴
|
|||
|
|
# ax2 = ax.twinx()
|
|||
|
|
|
|||
|
|
# # 绘制能量分布(左侧Y轴,使用探测器颜色)
|
|||
|
|
# ax.hist(energy_data, bins=50, alpha=0.6, color=colors[i], label='Energy (keV)')
|
|||
|
|
# ax.set_xlabel('Energy (keV)', fontsize=label_fontsize)
|
|||
|
|
# ax.set_ylabel('Energy Count', fontsize=label_fontsize, color=colors[i])
|
|||
|
|
# ax.tick_params(axis='y', labelcolor=colors[i], colors='white', labelsize=tick_fontsize)
|
|||
|
|
|
|||
|
|
# # 绘制时间分布(右侧Y轴,白色)
|
|||
|
|
# ax2.hist(timestamp_data, bins=50, alpha=0.6, color='white', label='Time (us)')
|
|||
|
|
# ax2.set_ylabel('Time Count', fontsize=label_fontsize, color='white')
|
|||
|
|
# ax2.tick_params(axis='y', labelcolor='white', colors='white', labelsize=tick_fontsize)
|
|||
|
|
|
|||
|
|
# ax.set_title(f'{labels[i]} - Sample Space Distribution', fontsize=title_fontsize, fontweight='bold')
|
|||
|
|
# ax.grid(True, alpha=0.3)
|
|||
|
|
# ax.set_facecolor('#1e1e1e')
|
|||
|
|
# ax.tick_params(axis='x', colors='white', labelsize=tick_fontsize)
|
|||
|
|
# ax.xaxis.label.set_color('white')
|
|||
|
|
# ax.title.set_color('white')
|
|||
|
|
# for spine in ax.spines.values():
|
|||
|
|
# spine.set_color('#444444')
|
|||
|
|
# for spine in ax2.spines.values():
|
|||
|
|
# spine.set_color('#444444')
|
|||
|
|
|
|||
|
|
self.canvas = FigureCanvasTkAgg(self.fig, master=self.chart_frame)
|
|||
|
|
self.canvas.draw()
|
|||
|
|
self.canvas.get_tk_widget().pack(fill="both", expand=True)
|
|||
|
|
|
|||
|
|
toolbar = NavigationToolbar2Tk(self.canvas, self.chart_frame, pack_toolbar=False)
|
|||
|
|
toolbar.update()
|
|||
|
|
toolbar.pack(side="top", fill="x")
|
|||
|
|
|
|||
|
|
def update_chart_with_time_series(self, time_series, detector_configs=None):
|
|||
|
|
"""使用时间序列数据更新图表"""
|
|||
|
|
# 清空图表框架
|
|||
|
|
for widget in self.chart_frame.winfo_children():
|
|||
|
|
widget.destroy()
|
|||
|
|
|
|||
|
|
if not time_series:
|
|||
|
|
ctk.CTkLabel(
|
|||
|
|
self.chart_frame,
|
|||
|
|
text="暂无时间序列数据",
|
|||
|
|
font=ctk.CTkFont(size=16),
|
|||
|
|
text_color="white"
|
|||
|
|
).pack(expand=True)
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 获取理论分布类型
|
|||
|
|
distribution_types = {0: "unknown", 1: "unknown", 2: "unknown"}
|
|||
|
|
if detector_configs:
|
|||
|
|
for i, det_name in enumerate(["detector1", "detector2", "detector3"]):
|
|||
|
|
if det_name in detector_configs:
|
|||
|
|
dist_config = detector_configs[det_name].get("timestamp_distribution", {})
|
|||
|
|
dist_type = dist_config.get("type", "unknown")
|
|||
|
|
distribution_types[i] = dist_type
|
|||
|
|
|
|||
|
|
# 准备时间序列数据
|
|||
|
|
timestamps = {0: [], 1: [], 2: []}
|
|||
|
|
energies = {0: [], 1: [], 2: []}
|
|||
|
|
|
|||
|
|
detector_keys = ["detector1", "detector2", "detector3"]
|
|||
|
|
for det_idx, det_name in enumerate(detector_keys):
|
|||
|
|
signals = time_series.get(det_name, [])
|
|||
|
|
for signal in signals:
|
|||
|
|
if len(signal) == 2:
|
|||
|
|
timestamp, energy = signal
|
|||
|
|
timestamps[det_idx].append(timestamp)
|
|||
|
|
energies[det_idx].append(energy)
|
|||
|
|
|
|||
|
|
# 增大字体大小
|
|||
|
|
label_fontsize = 10
|
|||
|
|
title_fontsize = 10
|
|||
|
|
tick_fontsize = 10
|
|||
|
|
|
|||
|
|
# 使用固定大小
|
|||
|
|
self.fig = plt.figure(figsize=(16, 12), dpi=100)
|
|||
|
|
self.fig.patch.set_facecolor('#2b2b2b')
|
|||
|
|
|
|||
|
|
colors = ['#e74c3c', '#2ecc71', '#3498db']
|
|||
|
|
labels = ['Detector 1', 'Detector 2', 'Detector 3']
|
|||
|
|
|
|||
|
|
# 获取能量分布类型
|
|||
|
|
energy_dist_types = {0: "unknown", 1: "unknown", 2: "unknown"}
|
|||
|
|
if detector_configs:
|
|||
|
|
for i, det_name in enumerate(["detector1", "detector2", "detector3"]):
|
|||
|
|
if det_name in detector_configs:
|
|||
|
|
dist_config = detector_configs[det_name].get("energy_distribution", {})
|
|||
|
|
dist_type = dist_config.get("type", "unknown")
|
|||
|
|
energy_dist_types[i] = dist_type
|
|||
|
|
|
|||
|
|
plt.subplots_adjust(hspace=0.5, wspace=0.4, left=0.06, right=0.94, top=0.96, bottom=0.06)
|
|||
|
|
|
|||
|
|
# 第1-3张图:各探测器的时间分布直方图
|
|||
|
|
for i in range(3):
|
|||
|
|
ax = self.fig.add_subplot(3, 3, i+1)
|
|||
|
|
if timestamps[i]:
|
|||
|
|
ax.hist(timestamps[i], bins=30, alpha=0.7, color=colors[i])
|
|||
|
|
ax.set_xlabel('Time (us)', fontsize=label_fontsize)
|
|||
|
|
ax.set_ylabel('Count', fontsize=label_fontsize)
|
|||
|
|
total_count = len(timestamps[i])
|
|||
|
|
ax.set_title(f'{labels[i]} - Time Distribution\n({distribution_types[i]}, n={total_count})',
|
|||
|
|
fontsize=title_fontsize, fontweight='bold')
|
|||
|
|
ax.grid(True, alpha=0.3)
|
|||
|
|
ax.set_facecolor('#1e1e1e')
|
|||
|
|
ax.tick_params(colors='white', labelsize=tick_fontsize)
|
|||
|
|
ax.xaxis.label.set_color('white')
|
|||
|
|
ax.yaxis.label.set_color('white')
|
|||
|
|
ax.title.set_color('white')
|
|||
|
|
for spine in ax.spines.values():
|
|||
|
|
spine.set_color('#444444')
|
|||
|
|
|
|||
|
|
# 第4-6张图:各探测器的能量分布直方图(mV)
|
|||
|
|
for i in range(3):
|
|||
|
|
ax = self.fig.add_subplot(3, 3, i+4)
|
|||
|
|
if energies[i]:
|
|||
|
|
ax.hist(energies[i], bins=30, alpha=0.7, color=colors[i])
|
|||
|
|
ax.set_xlabel('Energy (mV)', fontsize=label_fontsize)
|
|||
|
|
ax.set_ylabel('Count', fontsize=label_fontsize)
|
|||
|
|
total_count = len(energies[i])
|
|||
|
|
avg_energy = sum(energies[i]) / total_count if total_count > 0 else 0
|
|||
|
|
ax.set_title(f'{labels[i]} - Energy Distribution\n({energy_dist_types[i]}, n={total_count}, avg={avg_energy:.0f})',
|
|||
|
|
fontsize=title_fontsize, fontweight='bold')
|
|||
|
|
ax.grid(True, alpha=0.3)
|
|||
|
|
ax.set_facecolor('#1e1e1e')
|
|||
|
|
ax.tick_params(colors='white', labelsize=tick_fontsize)
|
|||
|
|
ax.xaxis.label.set_color('white')
|
|||
|
|
ax.yaxis.label.set_color('white')
|
|||
|
|
ax.title.set_color('white')
|
|||
|
|
for spine in ax.spines.values():
|
|||
|
|
spine.set_color('#444444')
|
|||
|
|
|
|||
|
|
# 第7-9张图:各探测器的时间-能量散点图
|
|||
|
|
for i in range(3):
|
|||
|
|
ax = self.fig.add_subplot(3, 3, i+7)
|
|||
|
|
if timestamps[i] and energies[i]:
|
|||
|
|
ax.scatter(timestamps[i], energies[i], alpha=0.5, c=colors[i], s=10)
|
|||
|
|
ax.set_xlabel('Time (us)', fontsize=label_fontsize)
|
|||
|
|
ax.set_ylabel('Energy (mV)', fontsize=label_fontsize)
|
|||
|
|
ax.set_title(f'{labels[i]} - Time vs Energy',
|
|||
|
|
fontsize=title_fontsize, fontweight='bold')
|
|||
|
|
ax.grid(True, alpha=0.3)
|
|||
|
|
ax.set_facecolor('#1e1e1e')
|
|||
|
|
ax.tick_params(colors='white', labelsize=tick_fontsize)
|
|||
|
|
ax.xaxis.label.set_color('white')
|
|||
|
|
ax.yaxis.label.set_color('white')
|
|||
|
|
ax.title.set_color('white')
|
|||
|
|
for spine in ax.spines.values():
|
|||
|
|
spine.set_color('#444444')
|
|||
|
|
|
|||
|
|
self.canvas = FigureCanvasTkAgg(self.fig, master=self.chart_frame)
|
|||
|
|
self.canvas.draw()
|
|||
|
|
self.canvas.get_tk_widget().pack(fill="both", expand=True)
|
|||
|
|
|
|||
|
|
toolbar = NavigationToolbar2Tk(self.canvas, self.chart_frame, pack_toolbar=False)
|
|||
|
|
toolbar.update()
|
|||
|
|
toolbar.pack(side="top", fill="x")
|
|||
|
|
|
|||
|
|
def verify_files(self, base_filename):
|
|||
|
|
"""验证输出文件"""
|
|||
|
|
files = []
|
|||
|
|
|
|||
|
|
# 检查二进制文件
|
|||
|
|
bin_file = f"{base_filename}.bin"
|
|||
|
|
if Path(bin_file).exists():
|
|||
|
|
size = Path(bin_file).stat().st_size
|
|||
|
|
files.append({"name": bin_file, "size": size, "exists": True})
|
|||
|
|
else:
|
|||
|
|
files.append({"name": bin_file, "size": 0, "exists": False})
|
|||
|
|
|
|||
|
|
# 检查文本文件
|
|||
|
|
txt_file = f"{base_filename}_v4.txt"
|
|||
|
|
if Path(txt_file).exists():
|
|||
|
|
size = Path(txt_file).stat().st_size
|
|||
|
|
files.append({"name": txt_file, "size": size, "exists": True})
|
|||
|
|
else:
|
|||
|
|
files.append({"name": txt_file, "size": 0, "exists": False})
|
|||
|
|
|
|||
|
|
# 检查调试文本文件
|
|||
|
|
debug_file = f"{base_filename}_debug.txt"
|
|||
|
|
if Path(debug_file).exists():
|
|||
|
|
size = Path(debug_file).stat().st_size
|
|||
|
|
files.append({"name": debug_file, "size": size, "exists": True})
|
|||
|
|
else:
|
|||
|
|
files.append({"name": debug_file, "size": 0, "exists": False})
|
|||
|
|
|
|||
|
|
return files
|
|||
|
|
|
|||
|
|
def update_chart_with_sample_space(self, sample_spaces, detector_configs):
|
|||
|
|
"""使用预生成的样本空间更新图表(仅显示样本空间分布)"""
|
|||
|
|
# 清空图表框架
|
|||
|
|
for widget in self.chart_frame.winfo_children():
|
|||
|
|
widget.destroy()
|
|||
|
|
|
|||
|
|
if not sample_spaces:
|
|||
|
|
ctk.CTkLabel(
|
|||
|
|
self.chart_frame,
|
|||
|
|
text="暂无样本空间数据",
|
|||
|
|
font=ctk.CTkFont(size=16),
|
|||
|
|
text_color="white"
|
|||
|
|
).pack(expand=True)
|
|||
|
|
return
|
|||
|
|
|
|||
|
|
# 增大字体大小
|
|||
|
|
label_fontsize = 10
|
|||
|
|
title_fontsize = 10
|
|||
|
|
tick_fontsize = 10
|
|||
|
|
|
|||
|
|
# 使用固定大小
|
|||
|
|
self.fig = plt.figure(figsize=(16, 12), dpi=100)
|
|||
|
|
self.fig.patch.set_facecolor('#2b2b2b')
|
|||
|
|
|
|||
|
|
colors = ['#e74c3c', '#2ecc71', '#3498db']
|
|||
|
|
labels = ['Detector 1', 'Detector 2', 'Detector 3']
|
|||
|
|
|
|||
|
|
plt.subplots_adjust(hspace=0.4, wspace=0.4, left=0.06, right=0.94, top=0.98, bottom=0.06)
|
|||
|
|
|
|||
|
|
# 显示3个探测器的样本空间分布(使用双Y轴)
|
|||
|
|
for i in range(3):
|
|||
|
|
ax = self.fig.add_subplot(3, 1, i+1)
|
|||
|
|
detector_key = f"detector{i+1}"
|
|||
|
|
|
|||
|
|
if detector_key not in sample_spaces:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
sample_space = sample_spaces[detector_key]
|
|||
|
|
energy_data = sample_space[:, 0] # 第一列是能量
|
|||
|
|
timestamp_data = sample_space[:, 1] # 第二列是时间戳
|
|||
|
|
|
|||
|
|
# 创建双Y轴
|
|||
|
|
ax2 = ax.twinx()
|
|||
|
|
|
|||
|
|
# 绘制能量分布(左侧Y轴,使用探测器颜色)
|
|||
|
|
ax.hist(energy_data, bins=50, alpha=0.6, color=colors[i], label='Energy (keV)')
|
|||
|
|
ax.set_xlabel('Energy (keV)', fontsize=label_fontsize)
|
|||
|
|
ax.set_ylabel('Energy Count', fontsize=label_fontsize, color=colors[i])
|
|||
|
|
ax.tick_params(axis='y', labelcolor=colors[i], colors='white', labelsize=tick_fontsize)
|
|||
|
|
|
|||
|
|
# 绘制时间分布(右侧Y轴,白色)
|
|||
|
|
ax2.hist(timestamp_data, bins=50, alpha=0.6, color='white', label='Time (us)')
|
|||
|
|
ax2.set_ylabel('Time Count', fontsize=label_fontsize, color='white')
|
|||
|
|
ax2.tick_params(axis='y', labelcolor='white', colors='white', labelsize=tick_fontsize)
|
|||
|
|
|
|||
|
|
ax.set_title(f'{labels[i]} - Sample Space Distribution (n={len(energy_data)})',
|
|||
|
|
fontsize=title_fontsize, fontweight='bold')
|
|||
|
|
ax.grid(True, alpha=0.3)
|
|||
|
|
ax.set_facecolor('#1e1e1e')
|
|||
|
|
ax.tick_params(axis='x', colors='white', labelsize=tick_fontsize)
|
|||
|
|
ax.xaxis.label.set_color('white')
|
|||
|
|
ax.title.set_color('white')
|
|||
|
|
for spine in ax.spines.values():
|
|||
|
|
spine.set_color('#444444')
|
|||
|
|
for spine in ax2.spines.values():
|
|||
|
|
spine.set_color('#444444')
|
|||
|
|
|
|||
|
|
self.canvas = FigureCanvasTkAgg(self.fig, master=self.chart_frame)
|
|||
|
|
self.canvas.draw()
|
|||
|
|
self.canvas.get_tk_widget().pack(fill="both", expand=True)
|
|||
|
|
|
|||
|
|
toolbar = NavigationToolbar2Tk(self.canvas, self.chart_frame, pack_toolbar=False)
|
|||
|
|
toolbar.update()
|
|||
|
|
toolbar.pack(side="top", fill="x")
|