style: Step4 图表中文排版升级,对齐Step12风格
- 添加 matplotlib rcParams 中文字体配置(Microsoft YaHei / SimHei) - 散点图标题→'采样点空间分布',坐标轴→'经度/X'、'纬度/Y' - 光谱图标题→'采样点 ID: X 光谱曲线',坐标轴→'波长/特征'、'反射率' - 悬停提示框中文化:ID + 经度 + 纬度 - 标题字号统一为 fontsize=14 fontweight='bold' pad=12 - 轴标签字号统一为 fontsize=11
This commit is contained in:
@ -14,9 +14,14 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
|
# ── 全局中文字体配置(与 Step12 统一)──
|
||||||
|
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'sans-serif']
|
||||||
|
plt.rcParams['axes.unicode_minus'] = False
|
||||||
|
|
||||||
_HERE = os.path.dirname(os.path.abspath(__file__))
|
_HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
if _HERE not in sys.path:
|
if _HERE not in sys.path:
|
||||||
sys.path.insert(0, _HERE)
|
sys.path.insert(0, _HERE)
|
||||||
@ -169,41 +174,44 @@ class Step4SamplingPanel(QWidget):
|
|||||||
left_widget.setMinimumWidth(360)
|
left_widget.setMinimumWidth(360)
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════
|
# ═══════════════════════════════════════════════
|
||||||
# 右侧:可视化区(嵌入式 Matplotlib 视图)
|
# 右侧:可视化区(参考 Step12 ImageViewer 的白底卡片风格)
|
||||||
# ═══════════════════════════════════════════════
|
# ═══════════════════════════════════════════════
|
||||||
right_widget = QWidget()
|
right_widget = QWidget()
|
||||||
right_layout = QVBoxLayout()
|
right_layout = QVBoxLayout()
|
||||||
right_layout.setContentsMargins(12, 24, 24, 24)
|
right_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
right_layout.setSpacing(0)
|
right_layout.setSpacing(0)
|
||||||
|
|
||||||
|
# 给画板穿上卡片外衣,确保视觉上的绝对统一
|
||||||
viz_group = QGroupBox("📊 采样点交互式探索")
|
viz_group = QGroupBox("📊 采样点交互式探索")
|
||||||
viz_layout = QVBoxLayout()
|
viz_layout = QVBoxLayout()
|
||||||
viz_layout.setContentsMargins(8, 20, 8, 8)
|
viz_layout.setContentsMargins(8, 20, 8, 8)
|
||||||
viz_layout.setSpacing(0)
|
viz_layout.setSpacing(0)
|
||||||
|
|
||||||
# Matplotlib 画布(1×2 子图:散点图 + 光谱曲线)
|
# Matplotlib 画布(1×2 子图:散点图 + 光谱曲线)
|
||||||
self._fig = Figure(figsize=(9, 5))
|
self._fig = Figure(figsize=(10, 7), facecolor='white')
|
||||||
self._ax_scatter = self._fig.add_subplot(121)
|
self._ax_scatter = self._fig.add_subplot(121)
|
||||||
self._ax_spectrum = self._fig.add_subplot(122)
|
self._ax_spectrum = self._fig.add_subplot(122)
|
||||||
self._canvas = FigureCanvas(self._fig)
|
self._canvas = FigureCanvas(self._fig)
|
||||||
self._canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
self._canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||||
|
self._canvas.setStyleSheet("background-color: white;")
|
||||||
|
|
||||||
# 设置子图初始状态
|
# 设置子图初始状态
|
||||||
self._ax_scatter.set_title("采样点分布", fontsize=11, fontweight='bold')
|
for ax, title, xlabel, ylabel in [
|
||||||
self._ax_scatter.set_xlabel("X 坐标")
|
(self._ax_scatter, "采样点空间分布", "经度 / X", "纬度 / Y"),
|
||||||
self._ax_scatter.set_ylabel("Y 坐标")
|
(self._ax_spectrum, "光谱曲线", "波长 / 特征", "反射率"),
|
||||||
|
]:
|
||||||
|
ax.set_title(title, fontsize=14, fontweight='bold', pad=12)
|
||||||
|
ax.set_xlabel(xlabel, fontsize=11)
|
||||||
|
ax.set_ylabel(ylabel, fontsize=11)
|
||||||
|
ax.set_facecolor('white')
|
||||||
|
ax.tick_params(labelsize=9)
|
||||||
|
|
||||||
self._ax_scatter.text(0.5, 0.5, "等待采样数据生成...\n\n请先配置参数并运行步骤\n或选择已有的 CSV 后刷新",
|
self._ax_scatter.text(0.5, 0.5, "等待采样数据生成...\n\n请先配置参数并运行步骤\n或选择已有的 CSV 后刷新",
|
||||||
ha='center', va='center', transform=self._ax_scatter.transAxes,
|
ha='center', va='center', transform=self._ax_scatter.transAxes,
|
||||||
fontsize=12, color='#888888')
|
fontsize=13, color='#AAAAAA')
|
||||||
self._ax_scatter.grid(False)
|
|
||||||
|
|
||||||
self._ax_spectrum.set_title("光谱曲线", fontsize=11, fontweight='bold')
|
|
||||||
self._ax_spectrum.set_xlabel("波长 (nm)")
|
|
||||||
self._ax_spectrum.set_ylabel("反射率")
|
|
||||||
self._ax_spectrum.text(0.5, 0.5, "点击左侧散点\n查看光谱曲线",
|
self._ax_spectrum.text(0.5, 0.5, "点击左侧散点\n查看光谱曲线",
|
||||||
ha='center', va='center', transform=self._ax_spectrum.transAxes,
|
ha='center', va='center', transform=self._ax_spectrum.transAxes,
|
||||||
fontsize=12, color='#888888')
|
fontsize=13, color='#AAAAAA')
|
||||||
self._ax_spectrum.grid(False)
|
|
||||||
|
|
||||||
self._fig.tight_layout(pad=2.0)
|
self._fig.tight_layout(pad=2.0)
|
||||||
|
|
||||||
@ -213,13 +221,13 @@ class Step4SamplingPanel(QWidget):
|
|||||||
viz_layout.addWidget(self._canvas)
|
viz_layout.addWidget(self._canvas)
|
||||||
|
|
||||||
viz_group.setLayout(viz_layout)
|
viz_group.setLayout(viz_layout)
|
||||||
right_layout.addWidget(viz_group)
|
right_layout.addWidget(viz_group, 1)
|
||||||
right_widget.setLayout(right_layout)
|
right_widget.setLayout(right_layout)
|
||||||
|
|
||||||
# ── 组装分栏 ──
|
# ── 组装分栏 ──
|
||||||
splitter.addWidget(left_widget)
|
splitter.addWidget(left_widget)
|
||||||
splitter.addWidget(right_widget)
|
splitter.addWidget(right_widget)
|
||||||
splitter.setSizes([420, 680]) # 初始比例 ≈ 38:62
|
splitter.setSizes([400, 700])
|
||||||
splitter.setStretchFactor(0, 1)
|
splitter.setStretchFactor(0, 1)
|
||||||
splitter.setStretchFactor(1, 2)
|
splitter.setStretchFactor(1, 2)
|
||||||
|
|
||||||
@ -499,53 +507,57 @@ class Step4SamplingPanel(QWidget):
|
|||||||
|
|
||||||
# ── 绘制 ax1:散点图 ──
|
# ── 绘制 ax1:散点图 ──
|
||||||
self._ax_scatter.clear()
|
self._ax_scatter.clear()
|
||||||
|
self._ax_scatter.set_facecolor('white')
|
||||||
x = df[x_col].values
|
x = df[x_col].values
|
||||||
y = df[y_col].values
|
y = df[y_col].values
|
||||||
|
|
||||||
self._scatter = self._ax_scatter.scatter(
|
self._scatter = self._ax_scatter.scatter(
|
||||||
x, y,
|
x, y,
|
||||||
c='#0078D7', alpha=0.7, edgecolors='white',
|
c='#0078D7', alpha=0.75, edgecolors='white',
|
||||||
linewidth=0.5, s=40, picker=True, zorder=3
|
linewidth=0.6, s=45, picker=True, zorder=3
|
||||||
)
|
)
|
||||||
self._ax_scatter.set_xlabel(str(x_col), fontsize=10)
|
self._ax_scatter.set_xlabel("经度 / X", fontsize=11)
|
||||||
self._ax_scatter.set_ylabel(str(y_col), fontsize=10)
|
self._ax_scatter.set_ylabel("纬度 / Y", fontsize=11)
|
||||||
self._ax_scatter.set_title(f"采样点分布 (共 {len(df)} 个点)", fontsize=11, fontweight='bold')
|
self._ax_scatter.set_title(f"采样点空间分布 (共 {len(df)} 个点)", fontsize=14, fontweight='bold', pad=12)
|
||||||
self._ax_scatter.grid(True, alpha=0.3, linestyle='--')
|
self._ax_scatter.grid(True, alpha=0.2, linestyle='-', linewidth=0.5)
|
||||||
self._ax_scatter.set_facecolor('#F8F9FA')
|
self._ax_scatter.tick_params(labelsize=9)
|
||||||
|
|
||||||
# ── 绘制 ax2:光谱曲线(初始状态)──
|
# ── 绘制 ax2:光谱曲线(初始状态)──
|
||||||
self._ax_spectrum.clear()
|
self._ax_spectrum.clear()
|
||||||
|
self._ax_spectrum.set_facecolor('white')
|
||||||
if band_cols:
|
if band_cols:
|
||||||
self._ax_spectrum.set_title("光谱曲线(点击左侧散点查看)", fontsize=11, fontweight='bold')
|
self._ax_spectrum.set_title("光谱曲线(点击左侧散点查看)", fontsize=14, fontweight='bold', pad=12)
|
||||||
self._ax_spectrum.set_xlabel("波长 (nm)", fontsize=10)
|
self._ax_spectrum.set_xlabel("波长 / 特征", fontsize=11)
|
||||||
self._ax_spectrum.set_ylabel("反射率", fontsize=10)
|
self._ax_spectrum.set_ylabel("反射率", fontsize=11)
|
||||||
self._ax_spectrum.grid(True, alpha=0.3, linestyle='--')
|
self._ax_spectrum.grid(True, alpha=0.2, linestyle='-', linewidth=0.5)
|
||||||
|
self._ax_spectrum.tick_params(labelsize=9)
|
||||||
self._ax_spectrum.text(0.5, 0.5, "点击左侧散点\n查看光谱曲线",
|
self._ax_spectrum.text(0.5, 0.5, "点击左侧散点\n查看光谱曲线",
|
||||||
ha='center', va='center', transform=self._ax_spectrum.transAxes,
|
ha='center', va='center', transform=self._ax_spectrum.transAxes,
|
||||||
fontsize=12, color='#999999')
|
fontsize=13, color='#AAAAAA')
|
||||||
else:
|
else:
|
||||||
self._ax_spectrum.text(0.5, 0.5, "缺少光谱数据列",
|
self._ax_spectrum.text(0.5, 0.5, "缺少光谱数据列",
|
||||||
ha='center', va='center', transform=self._ax_spectrum.transAxes,
|
ha='center', va='center', transform=self._ax_spectrum.transAxes,
|
||||||
fontsize=12, color='#999999')
|
fontsize=13, color='#AAAAAA')
|
||||||
|
|
||||||
self._fig.tight_layout(pad=2.0)
|
self._fig.tight_layout(pad=2.0)
|
||||||
self._canvas.draw()
|
self._canvas.draw()
|
||||||
|
|
||||||
def _show_empty_state(self, message: str):
|
def _show_empty_state(self, message: str):
|
||||||
"""在右侧画布显示提示信息。"""
|
"""在右侧画布显示提示信息。"""
|
||||||
self._ax_scatter.clear()
|
for ax in (self._ax_scatter, self._ax_spectrum):
|
||||||
self._ax_scatter.set_title("采样点分布", fontsize=11, fontweight='bold')
|
ax.clear()
|
||||||
|
ax.set_facecolor('white')
|
||||||
|
ax.tick_params(labelsize=0)
|
||||||
|
|
||||||
|
self._ax_scatter.set_title("采样点空间分布", fontsize=14, fontweight='bold', pad=12)
|
||||||
self._ax_scatter.text(0.5, 0.5, message, ha='center', va='center',
|
self._ax_scatter.text(0.5, 0.5, message, ha='center', va='center',
|
||||||
transform=self._ax_scatter.transAxes,
|
transform=self._ax_scatter.transAxes,
|
||||||
fontsize=12, color='#888888')
|
fontsize=13, color='#AAAAAA')
|
||||||
self._ax_scatter.grid(False)
|
|
||||||
|
|
||||||
self._ax_spectrum.clear()
|
self._ax_spectrum.set_title("光谱曲线", fontsize=14, fontweight='bold', pad=12)
|
||||||
self._ax_spectrum.set_title("光谱曲线", fontsize=11, fontweight='bold')
|
|
||||||
self._ax_spectrum.text(0.5, 0.5, "等待数据...",
|
self._ax_spectrum.text(0.5, 0.5, "等待数据...",
|
||||||
ha='center', va='center', transform=self._ax_spectrum.transAxes,
|
ha='center', va='center', transform=self._ax_spectrum.transAxes,
|
||||||
fontsize=12, color='#888888')
|
fontsize=13, color='#AAAAAA')
|
||||||
self._ax_spectrum.grid(False)
|
|
||||||
|
|
||||||
self._fig.tight_layout(pad=2.0)
|
self._fig.tight_layout(pad=2.0)
|
||||||
self._canvas.draw()
|
self._canvas.draw()
|
||||||
@ -588,7 +600,7 @@ class Step4SamplingPanel(QWidget):
|
|||||||
y_val = row[self._y_col]
|
y_val = row[self._y_col]
|
||||||
|
|
||||||
# 创建或更新 Annotation
|
# 创建或更新 Annotation
|
||||||
text = f"#{idx}\n({x_val:.4f}, {y_val:.4f})"
|
text = f"ID: {idx}\n经度: {x_val:.4f}\n纬度: {y_val:.4f}"
|
||||||
if self._annot is None:
|
if self._annot is None:
|
||||||
self._annot = self._ax_scatter.annotate(
|
self._annot = self._ax_scatter.annotate(
|
||||||
text,
|
text,
|
||||||
@ -629,31 +641,33 @@ class Step4SamplingPanel(QWidget):
|
|||||||
y = self._df[self._y_col].values
|
y = self._df[self._y_col].values
|
||||||
|
|
||||||
colors = ['#0078D7'] * len(self._df)
|
colors = ['#0078D7'] * len(self._df)
|
||||||
sizes = [40] * len(self._df)
|
sizes = [45] * len(self._df)
|
||||||
colors[idx] = '#E74C3C'
|
colors[idx] = '#E74C3C'
|
||||||
sizes[idx] = 80
|
sizes[idx] = 80
|
||||||
|
|
||||||
self._ax_scatter.clear()
|
self._ax_scatter.clear()
|
||||||
|
self._ax_scatter.set_facecolor('white')
|
||||||
self._scatter = self._ax_scatter.scatter(
|
self._scatter = self._ax_scatter.scatter(
|
||||||
x, y, c=colors, s=sizes,
|
x, y, c=colors, s=sizes,
|
||||||
alpha=0.7, edgecolors='white', linewidth=0.5,
|
alpha=0.75, edgecolors='white', linewidth=0.6,
|
||||||
picker=True, zorder=3
|
picker=True, zorder=3
|
||||||
)
|
)
|
||||||
# 将选中点提升到顶层
|
# 将选中点提升到顶层
|
||||||
self._ax_scatter.scatter(
|
self._ax_scatter.scatter(
|
||||||
[x[idx]], [y[idx]],
|
[x[idx]], [y[idx]],
|
||||||
c='#E74C3C', s=100,
|
c='#E74C3C', s=110,
|
||||||
alpha=0.9, edgecolors='white', linewidth=1.5,
|
alpha=0.9, edgecolors='white', linewidth=1.5,
|
||||||
zorder=5
|
zorder=5
|
||||||
)
|
)
|
||||||
self._ax_scatter.set_xlabel(str(self._x_col), fontsize=10)
|
self._ax_scatter.set_xlabel("经度 / X", fontsize=11)
|
||||||
self._ax_scatter.set_ylabel(str(self._y_col), fontsize=10)
|
self._ax_scatter.set_ylabel("纬度 / Y", fontsize=11)
|
||||||
self._ax_scatter.set_title(f"采样点分布 (共 {len(self._df)} 个点)", fontsize=11, fontweight='bold')
|
self._ax_scatter.set_title(f"采样点空间分布 (共 {len(self._df)} 个点)", fontsize=14, fontweight='bold', pad=12)
|
||||||
self._ax_scatter.grid(True, alpha=0.3, linestyle='--')
|
self._ax_scatter.grid(True, alpha=0.2, linestyle='-', linewidth=0.5)
|
||||||
self._ax_scatter.set_facecolor('#F8F9FA')
|
self._ax_scatter.tick_params(labelsize=9)
|
||||||
|
|
||||||
# ── 绘制光谱曲线 ──
|
# ── 绘制光谱曲线 ──
|
||||||
self._ax_spectrum.clear()
|
self._ax_spectrum.clear()
|
||||||
|
self._ax_spectrum.set_facecolor('white')
|
||||||
if self._band_cols:
|
if self._band_cols:
|
||||||
wavelengths = []
|
wavelengths = []
|
||||||
reflectance = []
|
reflectance = []
|
||||||
@ -673,24 +687,25 @@ class Step4SamplingPanel(QWidget):
|
|||||||
wavelengths, reflectance = zip(*pairs) if pairs else ([], [])
|
wavelengths, reflectance = zip(*pairs) if pairs else ([], [])
|
||||||
self._ax_spectrum.plot(
|
self._ax_spectrum.plot(
|
||||||
wavelengths, reflectance,
|
wavelengths, reflectance,
|
||||||
color='#0078D7', lw=1.5, marker='.', markersize=3, alpha=0.8
|
color='#0078D7', lw=1.5, marker='.', markersize=3, alpha=0.85
|
||||||
)
|
)
|
||||||
self._ax_spectrum.fill_between(wavelengths, reflectance, alpha=0.1, color='#0078D7')
|
self._ax_spectrum.fill_between(wavelengths, reflectance, alpha=0.08, color='#0078D7')
|
||||||
self._ax_spectrum.set_xlabel("波长 (nm)", fontsize=10)
|
self._ax_spectrum.set_xlabel("波长 / 特征", fontsize=11)
|
||||||
self._ax_spectrum.set_ylabel("反射率", fontsize=10)
|
self._ax_spectrum.set_ylabel("反射率", fontsize=11)
|
||||||
self._ax_spectrum.set_title(f"样本 #{idx} 的光谱曲线 ({len(wavelengths)} 个波段)",
|
self._ax_spectrum.set_title(f"采样点 ID: {idx} 光谱曲线 ({len(wavelengths)} 个波段)",
|
||||||
fontsize=11, fontweight='bold')
|
fontsize=14, fontweight='bold', pad=12)
|
||||||
self._ax_spectrum.grid(True, alpha=0.3, linestyle='--')
|
self._ax_spectrum.grid(True, alpha=0.2, linestyle='-', linewidth=0.5)
|
||||||
|
self._ax_spectrum.tick_params(labelsize=9)
|
||||||
else:
|
else:
|
||||||
self._ax_spectrum.text(0.5, 0.5, "该样本无有效光谱数据",
|
self._ax_spectrum.text(0.5, 0.5, "该样本无有效光谱数据",
|
||||||
ha='center', va='center',
|
ha='center', va='center',
|
||||||
transform=self._ax_spectrum.transAxes,
|
transform=self._ax_spectrum.transAxes,
|
||||||
fontsize=12, color='#999999')
|
fontsize=13, color='#AAAAAA')
|
||||||
else:
|
else:
|
||||||
self._ax_spectrum.text(0.5, 0.5, "缺少光谱波段列\n无法绘制光谱",
|
self._ax_spectrum.text(0.5, 0.5, "缺少光谱波段列\n无法绘制光谱",
|
||||||
ha='center', va='center',
|
ha='center', va='center',
|
||||||
transform=self._ax_spectrum.transAxes,
|
transform=self._ax_spectrum.transAxes,
|
||||||
fontsize=12, color='#999999')
|
fontsize=13, color='#AAAAAA')
|
||||||
|
|
||||||
self._fig.tight_layout(pad=2.0)
|
self._fig.tight_layout(pad=2.0)
|
||||||
self._canvas.draw()
|
self._canvas.draw()
|
||||||
|
|||||||
Reference in New Issue
Block a user