Skip to content

Latest commit

 

History

History
254 lines (213 loc) · 7.22 KB

File metadata and controls

254 lines (213 loc) · 7.22 KB

参数详解与组合用例 · Reference

一、风格规范(已固化在 _BASE_RC)

参数 说明
axes.linewidth 0.75 pt 边框
lines.linewidth 1.2 pt 数据曲线
xtick/ytick.direction in 内向刻度
xtick.top / ytick.right True 四边都有刻度
xtick/ytick.minor.visible True 自动开启次刻度
axes.grid False 不带网格(Bode 例外)
legend.frameon False 图例无边框
pdf.fonttype 42 TrueType 嵌入,避免 PDF 乱码
mathtext.fontset stix 数学符号字体
savefig.dpi 600 印刷分辨率

二、profile 详细参数

profile figsize (in) font.size label legend linewidth
single / single_cn (3.5, 2.6) 8 9 7 1.2
double / double_cn (7.16, 3.0) 8 9 7 1.2
slide / slide_cn (8.0, 5.0) 14 16 13 1.8
poster / poster_cn (10.0, 7.0) 18 20 16 2.2

_cn profile 仅在字体族首位插入中文字体,其余参数与对应英文 profile 一致。

三、典型组合用例

1. 振动信号 + FFT(论文标准图)

import numpy as np
import academic_plot as ap

fs = 1667
t = np.arange(0, 0.5, 1/fs)
vib = np.loadtxt("vibration.csv")

fig, axes = ap.new_figure("double", n_rows=1, n_cols=2)
ap.plot_time_series(t * 1000, vib,
                    xlabel="Time (ms)",
                    ylabel=r"Acc. (m/s$^2$)",
                    ax=axes[0])
ap.plot_spectrum(vib, fs, xlim=(0, 300),
                 ylabel=r"Amp. (m/s$^2$)",
                 ax=axes[1])
ap.add_subplot_label(axes[0], "(a)")
ap.add_subplot_label(axes[1], "(b)")
fig.tight_layout()
ap.save_figure(fig, "fig2_vibration.png")

2. 不同负载下的力响应(多曲线)

loads = [0.5, 1.0, 2.0, 5.0]
fig, ax = ap.plot_multi_curves(
    t, [response[load] for load in loads],
    labels=[f"{lo} kg" for lo in loads],
    xlabel="Time (s)",
    ylabel="Force (N)",
    markers=["o", "s", "^", "D"],
    markevery=20,
    legend_loc="best",
    legend_ncol=2,
)
ap.save_figure(fig, "fig3_force.png")

3. 电压 + 温度同步监测(双 Y 轴)

fig, (ax1, ax2) = ap.plot_dual_axis(
    t_min, voltage, temperature,
    xlabel="Time (min)",
    ylabel1="Voltage (V)",
    ylabel2=r"Temperature ($^\circ$C)",
    label1="Battery",
    label2="Cell temp.",
    legend_loc="center right",
)
ax1.axvspan(20, 30, alpha=0.15, color="gray")
ax1.text(25, 4.1, "Charge phase", ha="center", fontsize=7)
ap.save_figure(fig, "fig4_battery.png")

4. 标定曲线 + 误差棒

fig, ax = ap.plot_errorbar(
    x_load, y_voltage, yerr=y_std,
    xlabel="Applied Force (N)",
    ylabel="Output Voltage (mV)",
    label="Measured",
)
x_fit = np.linspace(x_load.min(), x_load.max(), 200)
y_fit = slope * x_fit + intercept
ax.plot(x_fit, y_fit, "--", color=ap.COLORS[2],
        label=f"Linear fit ($R^2$={r2:.4f})")
ax.legend()
ap.save_figure(fig, "fig5_calibration.png")

5. 频响 Bode 图

fig, (ax_m, ax_p) = ap.plot_bode(
    freq, mag_db, phase_deg,
    label="Measured",
)
ax_m.semilogx(freq, mag_db_theory, "--", color=ap.COLORS[2], label="1st-order")
ax_m.legend()
ap.save_figure(fig, "fig6_bode.png")

6. 时频图 / 振动热图

from scipy.signal import spectrogram
f, t, Sxx = spectrogram(vib, fs=fs, nperseg=256)

fig, ax = ap.plot_heatmap(
    10 * np.log10(Sxx + 1e-12),
    xlabel="Time (s)",
    ylabel="Frequency (Hz)",
    cbar_label="PSD (dB)",
    extent=(t.min(), t.max(), f.min(), f.max()),
    cmap="viridis",
)
ax.set_ylim(0, 300)
ap.save_figure(fig, "fig7_stft.png")

7. 中文论文综合图

ap.apply_style("double_cn")
fig, axes = ap.new_figure("double_cn", n_rows=2, n_cols=2)

axes[0, 0].plot(t * 1000, vib, color=ap.COLORS[1])
axes[0, 0].set_xlabel("时间 (ms)")
axes[0, 0].set_ylabel(r"加速度 (m/s$^2$)")
ap.add_subplot_label(axes[0, 0], "(a)")

# ... 其他子图
fig.suptitle("某型号传感器综合测试", fontproperties=ap.CJK_FONT, fontsize=10)
fig.tight_layout()
ap.save_figure(fig, "fig_cn_综合.png")

四、常用进阶技巧

子图共享坐标轴

fig, axes = ap.new_figure("double", n_rows=2, n_cols=1, sharex=True)
fig.subplots_adjust(hspace=0.08)

插入小图(inset)

from mpl_toolkits.axes_grid1.inset_locator import inset_axes
axins = inset_axes(ax, width="35%", height="35%", loc="upper right",
                   borderpad=1)
axins.plot(t_zoom, y_zoom, color=ap.COLORS[1])
axins.tick_params(labelsize=6)

双 Y 轴对齐零点

ax1_min, ax1_max = ax1.get_ylim()
ax2_min, ax2_max = ax2.get_ylim()
ratio = ax1_min / (ax1_min - ax1_max) if ax1_min < 0 else 0
ax2.set_ylim(ax2_max * ratio / (ratio - 1), ax2_max)

标注峰值

peak_idx = np.argmax(spec)
ax.annotate(f"{freq[peak_idx]:.1f} Hz",
            xy=(freq[peak_idx], spec[peak_idx]),
            xytext=(20, -20), textcoords="offset points",
            fontsize=7,
            arrowprops=dict(arrowstyle="->", lw=0.5, color="gray"))

灰度备份图(部分期刊要求)

gray_colors = ["#000000", "#444444", "#888888", "#bbbbbb"]
fig, ax = ap.plot_multi_curves(
    x, ys, labels,
    linestyles=["-", "--", "-.", ":"],
)
for line, c in zip(ax.lines, gray_colors):
    line.set_color(c)
ap.save_figure(fig, "fig_gray.png")

五、与 LaTeX 配合

\begin{figure}[tb]
  \centering
  \includegraphics[width=\columnwidth]{fig2_vibration.pdf}
  \caption{Vibration signal in time and frequency domains.}
  \label{fig:vibration}
\end{figure}

注意:

  • 用 PDF 不用 PNG(矢量缩放无损)
  • \columnwidth 自动匹配单栏 / 双栏,画图时按 "single" / "double" profile 出 1:1 尺寸,不要额外缩放
  • 字号已按 8 pt 设计,与 IEEE 期刊正文 10 pt 协调

六、中文论文 / 期刊配图建议

国内核心期刊(仪器仪表学报、机械工程学报、电子学报、振动工程学报等)的常见要求:

要求 academic-plot 对应
字号 7-9 号 _cn profile 默认 8 pt
中英文同时存在 自动 fallback(中文字体优先,英文 Helvetica)
单位用英文(s, Hz, V, dB 等) 直接写 "频率 (Hz)" 即可
数学符号用 mathtext r"$10^{-3}$"r"$\mu$m"
子图编号 (a) (b) (c) add_subplot_label(ax, "(a)")
图注用宋体 默认黑体;如需宋体在 apply_style 后手动覆盖 font.sans-serif
黑白印刷需识别 linestyles 区分曲线,颜色作辅助

如某期刊明确要求宋体:

import matplotlib as mpl
ap.apply_style("single_cn")
mpl.rcParams["font.sans-serif"] = ["Songti SC", "STSong"] + mpl.rcParams["font.sans-serif"]

七、调试

需要:matplotlib >= 3.5numpyscipy(仅 spectrogram 等用到)。 查看当前生效:

import matplotlib as mpl
print(mpl.rcParams["axes.prop_cycle"])
print(mpl.rcParams["figure.figsize"])
print(mpl.rcParams["font.sans-serif"])

中文不显示 / 显示方块:

import academic_plot as ap
print(ap.has_cjk_font())
print(ap.list_cjk_fonts())
# Linux: sudo apt install fonts-noto-cjk