SR-ARPOD/Plots/plot_config.py
2026-04-01 22:48:53 +08:00

140 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
顶级期刊图表全局配置。
所有绘图脚本通过 `from plot_config import apply_style, COLORS, ...` 导入。
风格参考:中国宇航学报 / Automatica / IEEE TAC 等期刊惯例。
- 字体Times New Roman正文+ STSong中文
- LaTeX 渲染数学符号
- 输出格式PDF矢量+ 300 dpi PNG备用
"""
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
# ── 颜色方案 ────────────────────────────────────────────────────
# 使用色觉友好配色 (adapted from Tol's qualitative palette)
COLORS = {
'blue': '#4477AA',
'cyan': '#66CCEE',
'green': '#228833',
'yellow': '#CCBB44',
'red': '#EE6677',
'purple': '#AA3377',
'grey': '#BBBBBB',
'black': '#000000',
}
# 用于消融实验对比的离散色板
ABLATION_COLORS = [COLORS['blue'], COLORS['red'], COLORS['green'],
COLORS['yellow'], COLORS['purple']]
# 控制通道颜色
CTRL_COLORS = {
'x': COLORS['red'],
'y': COLORS['blue'],
'z': COLORS['green'],
}
# ── 图幅尺寸 ────────────────────────────────────────────────────
# 中国期刊单栏约 8 cm (3.15 in),双栏约 16 cm (6.3 in)
SINGLE_COL = 3.5 # inches
DOUBLE_COL = 7.0 # inches
GOLDEN = (1 + np.sqrt(5)) / 2
def figsize(cols=1, aspect=None):
"""返回 (width, height) 英寸cols=1 单栏, cols=2 双栏。"""
w = SINGLE_COL if cols == 1 else DOUBLE_COL
if aspect is None:
aspect = 1.0 / GOLDEN
return (w, w * aspect)
# ── 全局样式 ─────────────────────────────────────────────────────
def apply_style():
"""应用顶级期刊全局 matplotlib 样式。"""
# 尝试加载中文字体(如可用)
import matplotlib.font_manager as fm
_cjk_fonts = ['SimSun', 'STSong', 'Songti SC', 'Noto Serif CJK SC']
_found_cjk = None
for fn in _cjk_fonts:
if any(fn.lower() in f.name.lower() for f in fm.fontManager.ttflist):
_found_cjk = fn
break
serif_list = ['Times New Roman']
if _found_cjk:
serif_list.append(_found_cjk)
plt.rcParams.update({
# 字体:使用 serif + 中文后备字体
'font.family': 'serif',
'font.serif': serif_list,
'font.sans-serif': ['Arial', 'Microsoft YaHei', 'SimHei'],
'font.size': 8,
'axes.titlesize': 9,
'axes.labelsize': 8,
'xtick.labelsize': 7,
'ytick.labelsize': 7,
'legend.fontsize': 7,
# LaTeX
'text.usetex': False, # 使用 mathtext 避免依赖 LaTeX
'mathtext.fontset': 'cm',
'axes.unicode_minus': False, # 防止负号显示问题
# 线条
'lines.linewidth': 1.0,
'lines.markersize': 3,
'patch.linewidth': 0.5,
# 坐标轴
'axes.linewidth': 0.6,
'axes.grid': False,
'axes.spines.top': False,
'axes.spines.right': False,
# 刻度
'xtick.direction': 'in',
'ytick.direction': 'in',
'xtick.major.width': 0.5,
'ytick.major.width': 0.5,
'xtick.major.size': 3,
'ytick.major.size': 3,
'xtick.minor.visible': False,
'ytick.minor.visible': False,
# 图例
'legend.frameon': True,
'legend.framealpha': 0.9,
'legend.edgecolor': '0.8',
'legend.borderpad': 0.3,
'legend.handlelength': 1.5,
# 保存
'savefig.dpi': 300,
'savefig.bbox': 'tight',
'savefig.pad_inches': 0.02,
# 图形
'figure.dpi': 150,
'figure.constrained_layout.use': True,
})
def save_fig(fig, name, out_dir='Plots'):
"""同时保存 PDF矢量和 PNG位图"""
import os
os.makedirs(out_dir, exist_ok=True)
fig.savefig(os.path.join(out_dir, f'{name}.pdf'), format='pdf')
fig.savefig(os.path.join(out_dir, f'{name}.png'), format='png', dpi=300)
print(f" ✓ saved {name}.pdf / .png → {out_dir}/")
def add_subfig_label(ax, label, x=-0.12, y=1.08):
"""在子图左上角添加 (a), (b) 等标签。"""
ax.text(x, y, f'({label})', transform=ax.transAxes,
fontsize=9, fontweight='bold', va='top', ha='right')