From 8eb1ebe8755a8373eb26c2eeb7baa0ab7b2a3abf Mon Sep 17 00:00:00 2001 From: Kkkakania <200867803+Kkkakania@users.noreply.github.com> Date: Fri, 19 Jun 2026 23:14:20 +0800 Subject: [PATCH] Add CSV workflow example --- README.md | 3 + docs/quick_start.md | 3 + examples/csv-workflow/README.md | 54 +++++++++++++ examples/csv-workflow/plot_csv_workflow.m | 43 +++++++++++ examples/csv-workflow/plot_csv_workflow.py | 75 +++++++++++++++++++ examples/csv-workflow/sample_measurements.csv | 13 ++++ .../csv-workflow/submission_check_report.md | 33 ++++++++ 7 files changed, 224 insertions(+) create mode 100644 examples/csv-workflow/README.md create mode 100644 examples/csv-workflow/plot_csv_workflow.m create mode 100644 examples/csv-workflow/plot_csv_workflow.py create mode 100644 examples/csv-workflow/sample_measurements.csv create mode 100644 examples/csv-workflow/submission_check_report.md diff --git a/README.md b/README.md index 71955e1..07245d4 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,9 @@ fig = make_figure(x=x, y=y, title='V-t 实测') fig.savefig('out.pdf') ``` +从 CSV 到投稿前图件自查的完整示例见 +[`examples/csv-workflow`](examples/csv-workflow/)。 + ## 暗色模式(v1.5) ```python diff --git a/docs/quick_start.md b/docs/quick_start.md index 78120f7..47e8c81 100644 --- a/docs/quick_start.md +++ b/docs/quick_start.md @@ -48,6 +48,9 @@ x, y = load_xy('measurement.csv', x_col='time', y_col='voltage') fig = make_figure(x=x, y=y, title='V-t 实测') ``` +从合成 CSV 数据生成 PNG/PDF 并填写投稿前图件检查报告的完整流程见 +[`examples/csv-workflow`](../examples/csv-workflow/)。 + **情况 C:MATLAB 端用 Excel** ```matlab diff --git a/examples/csv-workflow/README.md b/examples/csv-workflow/README.md new file mode 100644 index 0000000..7973a83 --- /dev/null +++ b/examples/csv-workflow/README.md @@ -0,0 +1,54 @@ +# CSV 到论文图工作流示例 + +这个示例展示如何从一个干净的 CSV 文件生成投稿前可自查的科研图件。它面向研究生、实验室同学和需要把 Excel/CSV 数据转成论文图的人。 + +示例边界: + +- 数据是合成的,不对应真实实验。 +- 脚本只演示图件呈现、导出和检查流程。 +- 不处理论文内容判断,不修改实验结论,不替代期刊、学校或导师要求。 +- 输出图默认写到本地 `out/` 目录;不要把私有数据或本地路径提交进仓库。 + +## 文件 + +| 文件 | 用途 | +|---|---| +| `sample_measurements.csv` | 合成测量数据,包含时间、电压、电流、温度 | +| `plot_csv_workflow.py` | Python 版本,从 CSV 生成双面板图并导出 PNG/PDF | +| `plot_csv_workflow.m` | MATLAB 版本,使用同一份 CSV 生成相同结构图 | +| `submission_check_report.md` | 投稿前图件检查报告模板示例 | + +## Python 使用 + +```bash +python examples/csv-workflow/plot_csv_workflow.py \ + --csv examples/csv-workflow/sample_measurements.csv \ + --out-dir /tmp/csv-workflow-out +``` + +生成: + +- `/tmp/csv-workflow-out/csv_workflow_voltage_current.png` +- `/tmp/csv-workflow-out/csv_workflow_voltage_current.pdf` + +## MATLAB 使用 + +```matlab +plot_csv_workflow( ... + 'examples/csv-workflow/sample_measurements.csv', ... + '/tmp/csv-workflow-out') +``` + +如果在 Windows 上运行,把输出路径换成自己的临时目录。 + +## 自查建议 + +生成图后,按 `submission_check_report.md` 记录: + +- 坐标轴单位是否完整。 +- 字号、线宽、marker 是否足够清楚。 +- PNG 和 PDF 放大后是否清晰。 +- 图例是否遮挡数据。 +- 导出文件名是否不含本地隐私路径。 + +这个流程可以反哺 `matlab-figure-ci` 的检查报告,也可以作为“图件投稿前检查资料包”的公开 clean-room 示例。 diff --git a/examples/csv-workflow/plot_csv_workflow.m b/examples/csv-workflow/plot_csv_workflow.m new file mode 100644 index 0000000..31538c9 --- /dev/null +++ b/examples/csv-workflow/plot_csv_workflow.m @@ -0,0 +1,43 @@ +function fig = plot_csv_workflow(csvPath,outDir) +%PLOT_CSV_WORKFLOW Render a clean-room CSV measurement example. +% fig = PLOT_CSV_WORKFLOW(csvPath,outDir) reads a CSV file with the +% columns time_s, voltage_v, current_a, and temperature_c, then exports a +% two-panel voltage/current figure to PNG and PDF. + +if nargin < 1 || isempty(csvPath) + csvPath = fullfile(fileparts(mfilename('fullpath')),'sample_measurements.csv'); +end +if nargin < 2 || isempty(outDir) + outDir = fullfile(pwd,'out'); +end +if ~exist(outDir,'dir') + mkdir(outDir); +end + +T = readtable(csvPath); + +fig = figure('Color','w','Units','centimeters','Position',[2 2 8.9 10.7]); +tiledlayout(fig,2,1,'TileSpacing','compact','Padding','compact'); + +nexttile; +plot(T.time_s,T.voltage_v,'-o','Color',[0 114 178]/255,'LineWidth',1.2,'MarkerSize',4); +ylabel('Voltage (V)'); +legend('Voltage','Location','southeast','Box','off'); +grid on; +text(0.02,0.92,'(a)','Units','normalized','FontWeight','bold'); +set(gca,'FontName','Arial','FontSize',8,'LineWidth',0.75); + +nexttile; +plot(T.time_s,T.current_a,'-s','Color',[230 159 0]/255,'LineWidth',1.2,'MarkerSize',4); +xlabel('Time (s)'); +ylabel('Current (A)'); +legend('Current','Location','southeast','Box','off'); +grid on; +text(0.02,0.92,'(b)','Units','normalized','FontWeight','bold'); +set(gca,'FontName','Arial','FontSize',8,'LineWidth',0.75); + +pngPath = fullfile(outDir,'csv_workflow_voltage_current.png'); +pdfPath = fullfile(outDir,'csv_workflow_voltage_current.pdf'); +exportgraphics(fig,pngPath,'Resolution',300); +exportgraphics(fig,pdfPath,'ContentType','vector'); +end diff --git a/examples/csv-workflow/plot_csv_workflow.py b/examples/csv-workflow/plot_csv_workflow.py new file mode 100644 index 0000000..f74d451 --- /dev/null +++ b/examples/csv-workflow/plot_csv_workflow.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +"""Render a clean-room CSV measurement example as a publication-style figure.""" +from __future__ import annotations + +import argparse +import csv +from pathlib import Path + +import matplotlib + +matplotlib.use("Agg") +import matplotlib.pyplot as plt + + +def load_measurements(csv_path: Path) -> dict[str, list[float]]: + data = { + "time_s": [], + "voltage_v": [], + "current_a": [], + "temperature_c": [], + } + with csv_path.open(newline="", encoding="utf-8") as handle: + reader = csv.DictReader(handle) + for row in reader: + for key in data: + data[key].append(float(row[key])) + return data + + +def make_figure(data: dict[str, list[float]]) -> plt.Figure: + plt.rcParams.update({ + "font.family": "DejaVu Sans", + "font.size": 8, + "axes.linewidth": 0.8, + "lines.linewidth": 1.4, + }) + + fig, axes = plt.subplots(2, 1, figsize=(3.5, 4.2), sharex=True, constrained_layout=True) + time_s = data["time_s"] + + axes[0].plot(time_s, data["voltage_v"], marker="o", color="#0072B2", label="Voltage") + axes[0].set_ylabel("Voltage (V)") + axes[0].legend(frameon=False, loc="lower right") + axes[0].grid(True, color="#DDDDDD", linewidth=0.6) + axes[0].text(0.02, 0.92, "(a)", transform=axes[0].transAxes, fontweight="bold") + + axes[1].plot(time_s, data["current_a"], marker="s", color="#E69F00", label="Current") + axes[1].set_xlabel("Time (s)") + axes[1].set_ylabel("Current (A)") + axes[1].legend(frameon=False, loc="lower right") + axes[1].grid(True, color="#DDDDDD", linewidth=0.6) + axes[1].text(0.02, 0.92, "(b)", transform=axes[1].transAxes, fontweight="bold") + + return fig + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--csv", type=Path, default=Path(__file__).with_name("sample_measurements.csv")) + parser.add_argument("--out-dir", type=Path, default=Path("out")) + args = parser.parse_args() + + args.out_dir.mkdir(parents=True, exist_ok=True) + data = load_measurements(args.csv) + fig = make_figure(data) + + stem = "csv_workflow_voltage_current" + fig.savefig(args.out_dir / f"{stem}.png", dpi=300) + fig.savefig(args.out_dir / f"{stem}.pdf") + plt.close(fig) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/examples/csv-workflow/sample_measurements.csv b/examples/csv-workflow/sample_measurements.csv new file mode 100644 index 0000000..2a611d5 --- /dev/null +++ b/examples/csv-workflow/sample_measurements.csv @@ -0,0 +1,13 @@ +time_s,voltage_v,current_a,temperature_c +0,2.95,0.118,24.8 +1,3.02,0.121,24.9 +2,3.08,0.126,25.0 +3,3.13,0.130,25.2 +4,3.17,0.132,25.4 +5,3.20,0.135,25.6 +6,3.23,0.137,25.7 +7,3.25,0.138,25.9 +8,3.27,0.139,26.1 +9,3.28,0.140,26.2 +10,3.29,0.140,26.4 +11,3.30,0.141,26.5 diff --git a/examples/csv-workflow/submission_check_report.md b/examples/csv-workflow/submission_check_report.md new file mode 100644 index 0000000..db7dd0f --- /dev/null +++ b/examples/csv-workflow/submission_check_report.md @@ -0,0 +1,33 @@ +# CSV 工作流投稿前检查报告 + +## 1. 基本信息 + +| 项目 | 内容 | +|---|---| +| 数据来源 | `sample_measurements.csv`,合成数据 | +| 图件脚本 | `plot_csv_workflow.py` / `plot_csv_workflow.m` | +| 图件类型 | 双面板时间序列图 | +| 输出格式 | PNG + PDF | +| 目标用途 | 投稿前自查示例 | + +## 2. 图件检查 + +| 检查项 | 状态 | 说明 | +|---|---|---| +| 坐标轴单位 | 通过 | 时间、电压、电流均有单位 | +| 字体一致性 | 通过 | 使用统一字体和字号 | +| 线宽与 marker | 通过 | 主线和 marker 在小尺寸下仍可读 | +| 配色 | 通过 | 蓝/橙组合,灰度下仍有差异 | +| 图例位置 | 通过 | 图例位于右下角,不遮挡主要趋势 | +| 导出格式 | 通过 | 同时导出 PNG 和 PDF | +| 数据边界 | 通过 | 使用合成数据,不含私有路径 | + +## 3. 可改进项 + +- 如果用于真实论文,应按目标期刊要求调整单栏或双栏宽度。 +- 如果曲线数量增加,应增加线型或 marker 区分,不要只依赖颜色。 +- 如果 CSV 来自真实实验,应保留数据处理脚本和版本记录。 + +## 4. 结论 + +该示例适合作为 CSV 到投稿前图件自查的 clean-room 最小流程。真实项目仍需要作者按期刊、导师或课题组要求复核。