fcdp 20261015__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fcdp-20261015/AGENTS.md +362 -0
- fcdp-20261015/CHANGELOG.md +62 -0
- fcdp-20261015/LICENSE +21 -0
- fcdp-20261015/MANIFEST.in +25 -0
- fcdp-20261015/PKG-INFO +411 -0
- fcdp-20261015/README.md +378 -0
- fcdp-20261015/_shared.py +3418 -0
- fcdp-20261015/cli.py +618 -0
- fcdp-20261015/computations.py +3503 -0
- fcdp-20261015/excel_export.py +952 -0
- fcdp-20261015/fcdp.egg-info/PKG-INFO +411 -0
- fcdp-20261015/fcdp.egg-info/SOURCES.txt +18 -0
- fcdp-20261015/fcdp.egg-info/dependency_links.txt +1 -0
- fcdp-20261015/fcdp.egg-info/entry_points.txt +3 -0
- fcdp-20261015/fcdp.egg-info/requires.txt +10 -0
- fcdp-20261015/fcdp.egg-info/top_level.txt +6 -0
- fcdp-20261015/gui.py +4118 -0
- fcdp-20261015/plotting.py +936 -0
- fcdp-20261015/pyproject.toml +84 -0
- fcdp-20261015/setup.cfg +4 -0
fcdp-20261015/AGENTS.md
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
# FCDP CLI Agent 使用指南
|
|
2
|
+
|
|
3
|
+
> **分发形态**:本文件在发布面以 **`AGENTS.md`** 为名(公开仓库根目录;pip 安装后位于 `<Python 前缀>/fcdp/AGENTS.md`,虚拟环境即 venv 根目录下的 `fcdp/`),开发仓库里的源文件是 `docs/Agent使用CLI指南.md`。开发仓库根的 `AGENTS.md` 是面向仓库维护的开发约定,与本文件内容不同。
|
|
4
|
+
> **受众**:由脚本 / agent 驱动的**无人值守调用**(不打开界面、不看日志面板)。
|
|
5
|
+
> **用户向文档是 `README.md`**(安装、界面、五条管线操作步骤);本指南只写 agent 需要、而用户不需要的内容:入口选择、机器判定通道、批量清单语义、配置隔离、故障对照与维护侧约定。
|
|
6
|
+
> **不重复的内容(都在开发仓库 `docs/` 下,路径本身不随本文件分发)**:输出对象逐字段语义见 `docs/output对象调用手册.md`;CLI 与 GUI 的差异细节见 `docs/历史归档/CLI与GUI处理差异报告.md`;发布面白名单与发布流程见 `docs/发布注意事项.md`。
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 0. TL;DR(可直接照抄)
|
|
11
|
+
|
|
12
|
+
```powershell
|
|
13
|
+
# 用固定 venv 的解释器绝对路径 + `-m cli`,不要依赖 PATH 上的 fcdp.exe
|
|
14
|
+
D:\venvs\fcdp\Scripts\python.exe -m cli --file D:\data\a.fcd -o D:\out\a.xlsx
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
| 要点 | 做法 |
|
|
18
|
+
|---|---|
|
|
19
|
+
| 入口 | `python -m cli`(稳,不依赖 PATH)或安装后的 `fcdp`;**永不用 `fcdp-gui`** |
|
|
20
|
+
| 参数 | `--file` / `-o` 显式写出且用绝对路径;**不写 `--mode`**(默认 `auto`,程序自己识别) |
|
|
21
|
+
| 判定成败 | 只看 `$LASTEXITCODE`(0/1/2);stdout 报告表仅作人眼核对,不要解析(见 3.2) |
|
|
22
|
+
| 要机器可读结果 | **不要解析终端文本**,改用 `run_pipeline()` 读 `outcome` / `total`(见第 6 节) |
|
|
23
|
+
| 批量 | `--manifest tasks.json`;task 不写 `mode`,每个 task 显式写 `output` |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. 入口与环境
|
|
28
|
+
|
|
29
|
+
### 1.1 允许 / 禁止
|
|
30
|
+
|
|
31
|
+
| 允许 | 禁止 | 原因 |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `fcdp --file ... -o ...` | `fcdp-gui` | Windows 下入口脚本是控制台程序,会弹窗并阻塞 |
|
|
34
|
+
| `python -m cli --file ...`(推荐) | `python gui.py` / 调用 `gui:main` | GUI 需要桌面环境,且是交互式入口 |
|
|
35
|
+
| `--config <绝对路径>` 显式指定配置 | 依赖 CWD 下的相对 `config.json` | 配置归属随安装形态变化(见 5.4) |
|
|
36
|
+
| `launch.py --check-only`(仅排障) | 用 `launch.py` 启动 GUI | 启动器只做定位/依赖预检/拉起界面 |
|
|
37
|
+
|
|
38
|
+
**固定解释器绝对路径是硬要求**:`PATH` 上的 `fcdp.exe` 可能属于另一个解释器或另一份源码,`import` 到的模块版本无法预期;源码目录(含 6 个同名模块)还会遮蔽 pip 安装的那份。写死 `D:\venvs\fcdp\Scripts\python.exe` 一类绝对路径可一次性消除这两类隐蔽故障。
|
|
39
|
+
|
|
40
|
+
### 1.2 运行环境
|
|
41
|
+
|
|
42
|
+
- Python **3.12+**,依赖 `pandas` / `numpy` / `scipy` / `matplotlib` / `openpyxl`(pip 安装自动装齐)。
|
|
43
|
+
- CLI 在导入期**强制 matplotlib `Agg` 后端**,无显示器(服务器 / SSH / 容器)可直接跑;不会创建图窗口。
|
|
44
|
+
- CLI **不联网**:版本检查与自更新只在 GUI 侧;自动化调用不产生任何对外请求。
|
|
45
|
+
- Windows 控制台编码:`cli.py` 自身已把 stdout / stderr 包成 UTF-8。**自己写的探针脚本**若要打印中文,用 `python -X utf8 script.py` 或先设 `$env:PYTHONIOENCODING='utf-8'`。
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. 单任务命令
|
|
50
|
+
|
|
51
|
+
### 2.1 语法
|
|
52
|
+
|
|
53
|
+
```powershell
|
|
54
|
+
fcdp --file <path>... [-o <输出.xlsx>] [--no-export] [选项...]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**`--mode` 是可选项,默认 `auto`(按文件内容自动识别管线),正常调用不要写它。** 只有自动识别出错时才手动指定模式去纠正。
|
|
58
|
+
|
|
59
|
+
```powershell
|
|
60
|
+
python -m cli --file D:\data\any.fcd # 单文件:IV / CO-ECSA / HUPD-ECSA 由内容识别
|
|
61
|
+
python -m cli --file D:\data\1.0bar-1.0%O2.DTA D:\data\1.0bar-2.0%O2.DTA # 整组 .DTA:按 TAG 列识别 O2 / EIS
|
|
62
|
+
python -m cli --file D:\data\any.fcd -o D:\out\any.xlsx --config D:\cfg\fcdp_agent.json
|
|
63
|
+
python -m cli --version # 只打印 FCDP <版本>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
程序按**文件内容**识别:`.fcd` → IV / CO-ECSA / HUPD-ECSA;`.DTA` → O2 或 EIS(读文件**第 2 行的 TAG 列**:`LSV` → O2,`EISPOT` → EIS;两者都不是则报「无法识别文件类型」)。**首个文件决定模式**,O2 组内混入异类文件会被按首个文件解析。
|
|
67
|
+
|
|
68
|
+
> `python -m cli` 要求 `cli` 可被导入:pip 安装形态直接可用;**源码副本形态**要先切到程序目录(或用 `PYTHONPATH` 指向它),否则会 `No module named 'cli'`(`launch.py` 内部就是显式前置程序目录来解决这点)。
|
|
69
|
+
|
|
70
|
+
### 2.2 参数全表
|
|
71
|
+
|
|
72
|
+
| 参数 | 说明 |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `--mode {iv,ecsa-co,ecsa-hupd,o2,eis,auto}` | 处理模式;**默认 `auto`(自动识别),正常不要写**;仅在自动识别出错时用来纠正 |
|
|
75
|
+
| `--file <path>...` | 输入文件;IV/ECSA/EIS **只取第一个**,O2 传整组 `.DTA` |
|
|
76
|
+
| `-o` / `--output <path>` | 输出 Excel;父目录会被自动创建 |
|
|
77
|
+
| `--manifest <json>` | 批量模式;**不能**与 `--mode` / `--file` 同用 |
|
|
78
|
+
| `--config <path>` | 显式配置文件;文件不存在 → 退出码 2(严格校验) |
|
|
79
|
+
| `--no-export` | 只计算不写盘 |
|
|
80
|
+
| `--cell-area <float>` | 电池面积 cm²;FCD 管线的默认值是「`cell_area_auto` 且文件有 `SurfaceArea` → 文件值,否则 config」 |
|
|
81
|
+
| `--ecsa-pt-usage <float>` | ECSA Pt 载量 mg/cm²(默认取 config `pt_loading`) |
|
|
82
|
+
| `--co-left-index` / `--co-right-index` | CO 端点索引;**两个都给**才关闭自动选点 |
|
|
83
|
+
| `--hupd-point-end` / `--hupd-direction {baseline above,baseline below}` | HUPD 基线终点与方向;给了 `--hupd-point-end` 即关闭自动选点 |
|
|
84
|
+
| `--h2-manual` / `--h2-slope` / `--h2-intercept` | IV 的 H2 crossover 手动拟合覆盖 |
|
|
85
|
+
| `--eis-hf-start` / `--eis-hf-end` / `--eis-lf-start` / `--eis-lf-end` | EIS 拟合段端点(**含入式**索引),覆盖自动段搜索 |
|
|
86
|
+
| `--version` | 打印 `FCDP <YYYYMMDD>` |
|
|
87
|
+
|
|
88
|
+
其余数值参数(均值点数、扫速、O2 电压区间 / 流量 / 温度、EIS 的 R² 阈值等)**没有 CLI 开关**,只能经配置文件提供(见 5.4)。
|
|
89
|
+
|
|
90
|
+
### 2.3 覆盖规则(容易踩的三条)
|
|
91
|
+
|
|
92
|
+
1. **显式参数 > 配置文件 > 内置默认**。同一次调用里 CLI 参数的优先级最高。
|
|
93
|
+
2. **默认就是自动识别,别手动指定 `--mode`**:程序按文件内容选管线(2.1)。手动指定只在自动识别确实出错时用;写错的 mode **不会**以退出码 2 快速失败 —— 与自动检测不符时只记一条 `模式覆盖` WARNING,然后**按 `--mode` 继续算**,等于拿错解析结果去算,通常在计算期以 `fail`(退出码 1)收场。
|
|
94
|
+
3. **`config.processing_mode` 非 `auto` 时会覆盖自动检测结果**:不写 `--mode` 也不等于「一定按文件内容走」。要保证按内容判定,配置文件里必须保持 `processing_mode = "auto"`。
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 3. 结果判定:三个通道
|
|
99
|
+
|
|
100
|
+
| 通道 | 内容 | 适合谁 |
|
|
101
|
+
|---|---|---|
|
|
102
|
+
| **退出码** | 0 / 1 / 2 | **agent 首选**,唯一稳定契约 |
|
|
103
|
+
| **输出对象** | `outcome` / `total` 四态 + 类型化结果 | 需要机器可读细节时(第 6 节) |
|
|
104
|
+
| stdout 报告表 | 人眼看的 `阶段/项目/状态` 表 | **不要解析**(见 3.2) |
|
|
105
|
+
| stderr 日志 | 全过程日志(含 LOG 级) | 排障取证,不作判定 |
|
|
106
|
+
|
|
107
|
+
### 3.1 退出码
|
|
108
|
+
|
|
109
|
+
| 码 | 含义 | 触发示例 |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| `0` | 成功(`total` 不是 `fail`) | 计算完成;个别项 `warn` / `skip` 也算成功 |
|
|
112
|
+
| `1` | 运行错误 | 文件读取失败、无法识别文件类型、管线致命失败、`total == 'fail'`、批量中有任务失败 |
|
|
113
|
+
| `2` | 参数错误 | `--config` 指向不存在的文件、`--manifest` 与 `--mode`/`--file` 同用、缺少 `--file`、未知 mode、清单缺 `tasks` |
|
|
114
|
+
|
|
115
|
+
**注意**:`warn` 不改变退出码。若业务上不接受 `warn`,必须走第 6 节读输出对象,不能只看退出码。
|
|
116
|
+
|
|
117
|
+
### 3.2 stdout 报告表(人眼用,勿解析)
|
|
118
|
+
|
|
119
|
+
管线结束后无条件打印(`--no-export` 时也打印,导出项显示 `skip`):
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
--- 导出报告 ---
|
|
123
|
+
阶段 项目 状态
|
|
124
|
+
预处理 活化移除 ok
|
|
125
|
+
计算 IV 段 ok
|
|
126
|
+
计算 阻抗谱段 skip
|
|
127
|
+
绘图 IV 图 skip
|
|
128
|
+
Excel导出 IV工作簿 skip
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**为什么不能解析**:表格用 `{字段:<宽度}` 按**字符数**填充,中文字符显示宽度是拉丁字符的两倍,列在终端里本来就不对齐;`阶段` 填充后正好占满 8 字符宽的行(如 `Excel导出`)与 `项目` 之间只剩 **1 个空格**,按「连续空白」切分会把两列并成一列。真要用文本,只能取**每行最后一个空白分隔 token 作状态**。
|
|
132
|
+
|
|
133
|
+
各 mode 的行集合是固定的(同一份投影也写进 Excel 的 `导出状态` sheet;**ECSA 两种模式不写该 sheet**,其导出只有 `raw_data` 一表):
|
|
134
|
+
|
|
135
|
+
| mode | 行(阶段 / 项目) |
|
|
136
|
+
|---|---|
|
|
137
|
+
| `iv` | 预处理/活化移除;计算/IV 段、阻抗谱段、MA 段、H2 段、电池面积、背压;绘图/IV 图;Excel导出/IV工作簿 |
|
|
138
|
+
| `ecsa-co` | 计算/片段解析、CO 数据准备、端点选择、CO ECSA;Excel导出/CO ECSA工作簿 |
|
|
139
|
+
| `ecsa-hupd` | 计算/片段解析、端点选择、HUPD 计算;Excel导出/HUPD ECSA工作簿 |
|
|
140
|
+
| `o2` | 解析/文件分组;计算/极限电流曲线、O2 阻力;绘图/O2 图;Excel导出/O2工作簿 |
|
|
141
|
+
| `eis` | 计算/EIS 段搜索/拟合、EIS 拟合 R²;Excel导出/EIS工作簿 |
|
|
142
|
+
|
|
143
|
+
### 3.3 stderr 日志
|
|
144
|
+
|
|
145
|
+
- 形如 `[2026-10-15 18:03:47] WARNING\t : 模式覆盖: ...`;级别为 `LOG / INFO / SUCCESS / WARNING / ERROR`(`ASK` 在 CLI 下自动同意)。
|
|
146
|
+
- **LOG 级日志只有 CLI 能看到**(GUI 日志面板会隐藏),所以排障时 stderr 的信息量大于界面。
|
|
147
|
+
- 单任务模式下 fatal 错误在 stderr 末尾以 `错误: <异常信息>` 出现;批量模式下失败任务汇总在 **stdout**(见第 5 节)。
|
|
148
|
+
|
|
149
|
+
> ⚠️ **stderr 不可原样外发**:日志会打印数据文件里内嵌的原始绝对路径、以及 `config.json` 里 `device_map` 映射出的设备名。对外张贴日志前先脱敏。
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 4. 输出路径与写盘语义
|
|
154
|
+
|
|
155
|
+
### 4.1 输出路径解析顺序
|
|
156
|
+
|
|
157
|
+
1. `-o` / `--output` 显式给定 → 用它(`--manifest` 下为 task 级 `output`);
|
|
158
|
+
2. 否则若 config 的 `result_path` 非空 → `result_path / {mode}_{文件夹名}_{时间戳}.xlsx`;
|
|
159
|
+
3. 否则 → 管线兜底到**首个输入文件所在目录**的自动命名文件。
|
|
160
|
+
|
|
161
|
+
`output_dir` / `-o` 的**父目录不存在会被自动创建**(`open_excel_writer` 是全部写盘路径的必经关口),不需要事先 mkdir。
|
|
162
|
+
|
|
163
|
+
### 4.2 自动命名规则
|
|
164
|
+
|
|
165
|
+
`{mode}_{文件夹名}_{YYYYMMDD_HHMMSS}.xlsx`,例如 `iv_H2数据_20261015_143000.xlsx`。其中「文件夹名」= 首个输入文件的父目录名;**父目录名长度 ≤ 5 字符时回退取祖父目录名**(例:`示例数据/iv/iv.fcd` 的文件夹名是 `示例数据` 而不是 `iv`)。
|
|
166
|
+
|
|
167
|
+
### 4.3 写盘语义(两条硬事实)
|
|
168
|
+
|
|
169
|
+
- **目标文件已存在时是「叠加」而不是「重建」**:写入器以 `mode='a'` + `if_sheet_exists='overlay'` 打开,同名 sheet 就地覆盖、**其他旧 sheet 与旧区域残留会保留**。自动化请**每次使用新的输出路径**(或先删除目标文件),否则会读到上一次运行的残留数据。
|
|
170
|
+
- **失败会回滚**:写盘包在 `excel_write_with_rollback` 里,异常时恢复原文件并清掉半成品;但文件被 Excel 打开占用等 I/O 错误本身仍会让该任务的导出项落到 `fail`/`warn`。
|
|
171
|
+
|
|
172
|
+
### 4.4 `--no-export`
|
|
173
|
+
|
|
174
|
+
只计算不写盘,且**不触碰 `result_path`、不建任何目录**;stdout 报告表照常打印(导出项为 `skip`)。适合先试算确认参数、再落盘的生产流程。
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 5. 批量模式 `--manifest`
|
|
179
|
+
|
|
180
|
+
### 5.1 清单格式
|
|
181
|
+
|
|
182
|
+
顶层键:`tasks`(**必填**,为空报错)、`output_dir`(选填,缺省为 config `result_path`,再缺省为当前目录;目录会自动创建)。顶层 `format` 键**已废弃**:出现时向 stderr 打一条警告,批量恒导出 Excel。
|
|
183
|
+
|
|
184
|
+
task 键与 `run_pipeline` 同名:`mode`(**选填,缺省 `auto`,同样不建议写**)/ `file`(字符串=单文件,数组=多文件,自动去重)/ `output` / `cell_area` / `ecsa_pt_usage` / `co_left_index` / `co_right_index` / `hupd_point_end` / `hupd_direction` / `h2_manual` / `h2_slope` / `h2_intercept` / `eis_hf_start` / `eis_hf_end` / `eis_lf_start` / `eis_lf_end`。**没有** `export_excel`(批量恒导出)、**没有** `config_path`(配置走命令行 `--config`)。
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"output_dir": "D:/out/batch_20261015",
|
|
189
|
+
"tasks": [
|
|
190
|
+
{ "file": "D:/data/iv.fcd", "output": "01_iv.xlsx" },
|
|
191
|
+
{ "file": "D:/data/co.fcd", "output": "02_co.xlsx" },
|
|
192
|
+
{ "file": ["D:/data/1.0bar-1.0%O2.DTA", "D:/data/1.0bar-2.0%O2.DTA"],
|
|
193
|
+
"output": "03_o2.xlsx" },
|
|
194
|
+
{ "file": "D:/data/eis.DTA", "output": "04_eis.xlsx" }
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### 5.2 路径语义(易错)
|
|
200
|
+
|
|
201
|
+
- **清单内的相对路径一律相对「调用 CLI 时的当前工作目录」解析**,不是清单文件所在目录 —— `output_dir` 与每个 task 的 `file` 都是如此。agent 请统一用绝对路径。
|
|
202
|
+
- task 的 `output` 是**文件名**:它会被拼到 `output_dir` 下并**强制改后缀为 `.xlsx`**;若给的是绝对路径,`Path` 拼接语义会让它**逃出 `output_dir`**(可用,但要自己保证可写)。
|
|
203
|
+
- 未给 `output` 时自动命名 `{mode}_{文件夹名}_{时间戳}_{i+1}.xlsx`(`i` 从 0 起,恒带序号)。
|
|
204
|
+
|
|
205
|
+
### 5.3 执行与报告语义
|
|
206
|
+
|
|
207
|
+
- **串行执行,单任务失败不影响后续**;任务内部异常被捕获并记为该任务失败。
|
|
208
|
+
- 成败判据:`output_obj.total != 'fail'` 记为成功。
|
|
209
|
+
- stdout 末尾打印汇总,**只列失败任务**:
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
--- 批量处理完成 ---
|
|
213
|
+
总计: 4 任务 | 成功: 2 | 失败: 2
|
|
214
|
+
失败任务:
|
|
215
|
+
[1] auto D:/data/does_not_exist.DTA: 无法识别 DTA 文件类型: does_not_exist.DTA
|
|
216
|
+
[2] auto ?: 缺少 file 字段
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
- **成功任务的输出路径不会打印**。要可靠拿到产物,**给每个 task 写显式 `output`**,或自行按 5.2 的命名规则推导。
|
|
220
|
+
- 失败明细里的 `mode` 是**清单里写的值**(没写就是 `auto`),**不是识别结果**;要按管线归因,请拿 `task_index` 回原始清单对 `file`,或改用第 6 节的程序化调用。
|
|
221
|
+
- 退出码:全部成功 → `0`;有失败 → `1`;清单文件不存在 / 缺 `tasks` / 与 `--mode`、`--file` 同用 → `2`。
|
|
222
|
+
|
|
223
|
+
### 5.4 配置隔离(批量与单任务都适用)
|
|
224
|
+
|
|
225
|
+
- 用 `--config D:\cfg\fcdp_agent.json` 指向**专用配置**,不要让 CLI 落到默认位置(pip 安装是 `%LOCALAPPDATA%\FCDP\config.json`,源码副本是程序目录的 `config.json`)。
|
|
226
|
+
- `--config` 严格校验:文件不存在直接退出码 2。**注意不一致是既定契约**——程序化 `run_pipeline(config_path=...)` 与 `build_config(json_path=...)` 在文件不存在时仍回退默认值(只加 stderr 警告)。CLI 侧请依赖严格校验,程序化侧请自行检查。
|
|
227
|
+
- 默认位置那份配置可能带 `result_path`(开发机上常见),会让「不写 `-o`」的调用把结果写到工作区外。**永远显式 `-o`**。
|
|
228
|
+
- 需要跑「干净参数」的对照实验时,用一份最小 JSON(只写要改的键)即可,未写的键取内置默认。
|
|
229
|
+
|
|
230
|
+
### 5.5 并发
|
|
231
|
+
|
|
232
|
+
批量是串行的;若要并行,请**每个进程写各自独立的 `output_dir` 或显式 `output`**。自动命名的时间戳只到秒,且序号只在单次运行内唯一,两个并发进程很容易撞名。
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 6. 需要机器可读结果时:`run_pipeline()`
|
|
237
|
+
|
|
238
|
+
终端文本是给人看的。要在同一进程里拿结构化结果,直接调 `cli.run_pipeline()`:
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
from pathlib import Path
|
|
242
|
+
from cli import run_pipeline
|
|
243
|
+
|
|
244
|
+
out = run_pipeline(
|
|
245
|
+
mode='auto', # 必填形参;传 'auto' 让程序按内容识别(正常不要写死管线)
|
|
246
|
+
file=Path(r'D:\data\iv.fcd'),
|
|
247
|
+
output=Path(r'D:\out\iv.xlsx'), # 显式给,别依赖默认
|
|
248
|
+
export_excel=True,
|
|
249
|
+
config_path=Path(r'D:\cfg\fcdp_agent.json'),
|
|
250
|
+
)
|
|
251
|
+
print(out.total, out.outcome) # ok / warn / fail / skip 的组合
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
关键契约(完整版见函数 docstring 的「返回契约」一节):
|
|
255
|
+
|
|
256
|
+
- **返回**:按 `mode` 对应的单一 `output_obj`(传 `'auto'` 时按识别结果;`iv`→`IvPipelineOutput`,`ecsa-co`→`CoEcsaPipelineOutput`,`ecsa-hupd`→`HupdEcsaPipelineOutput`,`o2`→`OxygenPipelineOutput`,`eis`→`EisPipelineOutput`)。
|
|
257
|
+
- **状态词表**:`ok / skip / warn / fail`(严重度 `skip < ok < warn < fail`),`total` 取最高档;判定整线失败看 `total == 'fail'`。
|
|
258
|
+
- **部分失败不抛异常**:有 `warn` / `fail` 时仍返回对象,如实反映在 `outcome` / `total`。
|
|
259
|
+
- **致命错误直接抛**(`ValueError` / `RuntimeError` / `OSError`),此时没有返回值,需自行 `try`。
|
|
260
|
+
- **`output_path` 是「期望路径」**:即使 `export_excel=False` 没写盘,该字段仍是期望值;只有导出失败才置 `None`。**不要用它判断文件是否存在**。
|
|
261
|
+
- **`results` 可能含 `None`**(HUPD 某个 cycle 自动选点失败时占位),消费前判空。
|
|
262
|
+
- **图句柄已被剥离**(返回前关闭并置 `None`),结果对象可直接 pickle;但 pickle 只适合本程序产出、且读取端需能 import **同版本**源码。
|
|
263
|
+
- 逐字段语义(各结果类的字段含义、单位、常见读错点)见开发仓库 `docs/output对象调用手册.md`(不随本文件分发)。
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 7. 推荐做法(checklist)
|
|
268
|
+
|
|
269
|
+
**显式化**
|
|
270
|
+
|
|
271
|
+
- [ ] 解释器用固定 venv 的**绝对路径** + `-m cli`;不依赖 `PATH`。
|
|
272
|
+
- [ ] **不写 `--mode`**(默认 `auto`),并确认配置里 `processing_mode = "auto"`;`--file` / `-o` / `--config` 显式且用绝对路径。
|
|
273
|
+
- [ ] 每个任务/每次运行使用**新的输出文件名**(避免 4.3 的叠加语义)。
|
|
274
|
+
- [ ] 批量里给每个 task 写 `output`(否则拿不到产物路径,见 5.3)。
|
|
275
|
+
|
|
276
|
+
**先验后跑**
|
|
277
|
+
|
|
278
|
+
- [ ] 新数据先用 `--no-export` 试算:确认 mode 识别正确、报告表无 `fail`,再落盘。
|
|
279
|
+
- [ ] 大批量前先跑 1 个任务冒烟,确认输出目录可写、产物可打开。
|
|
280
|
+
- [ ] 不接受的 `warn` 要在第 6 节的对象里显式检查,别只看退出码。
|
|
281
|
+
|
|
282
|
+
**判定与重试**
|
|
283
|
+
|
|
284
|
+
- [ ] 只信退出码与输出对象;**不解析** stdout 表格、**不匹配**中文日志文本(措辞会随版本变)。
|
|
285
|
+
- [ ] 退出码 `1` 多为数据问题(重试无用,需换数据或改参数);`2` 是命令问题(改命令行即可重试)。
|
|
286
|
+
- [ ] 失败任务的错误信息在批量模式下位于 **stdout** 的「失败任务」段;单任务模式在 **stderr** 的 `错误: ...` 行。
|
|
287
|
+
|
|
288
|
+
**隔离与隐私**
|
|
289
|
+
|
|
290
|
+
- [ ] 用专用 `--config`,不要依赖 CWD 或用户目录里的那份。
|
|
291
|
+
- [ ] 不把 stderr 原文外发(含数据文件内嵌路径与设备映射结果)。
|
|
292
|
+
- [ ] 并发时每个进程独立输出目录。
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## 8. 故障对照表
|
|
297
|
+
|
|
298
|
+
| 现象 | 退出码 | 原因 / 处理 |
|
|
299
|
+
|---|---|---|
|
|
300
|
+
| `错误: 文件读取失败: xxx.fcd` | 1 | 路径错 / 文件损坏;核对 `--file` 绝对路径 |
|
|
301
|
+
| `错误: 无法识别 DTA 文件类型: xxx.DTA` | 1 | `.DTA` 不是 O2/EIS 结构;核对来源或改用 `.fcd` |
|
|
302
|
+
| `错误: <管线>: 处理失败 - ...` | 1 | 计算期致命失败(数据不足 / 拟合无解);换数据或调整参数 |
|
|
303
|
+
| 手动写了 `--mode` 且与文件不符 | 1 | 覆盖只记 WARNING(2.3);**去掉 `--mode`** 让它自动识别 |
|
|
304
|
+
| 手动把非 EIS 文件按 EIS 处理 | 1 | 强制 mode 后由管线优雅失败,不会退 2(去掉 `--mode` 即可) |
|
|
305
|
+
| `cli.py: error: --config 指定的配置文件不存在` | 2 | 提供存在的配置,或去掉 `--config` |
|
|
306
|
+
| `cli.py: error: --manifest 不能与 --mode/--file 同时使用` | 2 | 二选一 |
|
|
307
|
+
| `cli.py: error: 请指定 --file` | 2 | 单任务模式必须有 `--file` |
|
|
308
|
+
| 清单 `tasks` 缺失或为空 | 2 | 修正 JSON |
|
|
309
|
+
| `ModuleNotFoundError: No module named 'cli'` / 依赖缺失 | **1**(解释器未捕获异常) | 解释器不对或依赖未装:改用装好依赖的那个解释器绝对路径。此时退出码与「运行错误」同为 1,**靠 stderr 的 traceback 区分** |
|
|
310
|
+
| Excel 导出项 `fail` / 文件被占用 | 1(`total=fail`) | 关闭正在打开该文件的 Excel,或换输出路径 |
|
|
311
|
+
| O2 单压力点数据 | 1(`total=fail`) | 数据限制(无法拟合氧传输阻力),非程序缺陷 |
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## 9. 维护侧附加信息(在本仓库内工作/改代码时)
|
|
316
|
+
|
|
317
|
+
### 9.1 发布面与目录
|
|
318
|
+
|
|
319
|
+
- **本文件是发布面文件**:发布名 `AGENTS.md`(公开仓库根 + wheel 的 `<Python 前缀>/fcdp/AGENTS.md`),开发仓库源是 `docs/Agent使用CLI指南.md`;白名单与全部自检命令见开发仓库 `docs/发布注意事项.md` 的「零」。因此正文里**不得出现设备 SN、本机路径、内网凭据**(`python -m release_surface content` 会按发布名 `AGENTS.md` 扫本文件),也**不要放指向 `docs/` 的相对链接** —— 改名后相对路径会断,指向开发仓库材料时只用代码字体写路径(本文件已按此约定写)。
|
|
320
|
+
- **改标题必须同步内容锚点**:`release_surface.PUBLIC_REPO_CONTENT_ANCHORS['AGENTS.md']` 要与本文件**首个非空行**逐字一致(当前 = 上面的一级标题),否则 `release_surface repo` / `content` 会判失败 —— 这道闸门也是"别把开发仓库那份同名 `AGENTS.md` 复制过去"的机械保证。
|
|
321
|
+
- **复制规则**:复制到公开仓库时按 `release_surface.PUBLIC_REPO_SOURCES` 的映射**改名复制内容**(公开仓库里没有 `docs/`,不是 `git mv`);**构建只在公开仓库工作副本执行**(在开发仓库构建会把同名开发约定打进 sdist)。
|
|
322
|
+
- `docs/` 其余内容、`tests/`、`示例数据/`、`config.json`、`requirements-dev.txt`、开发约定用的根 `AGENTS.md` 一律不进公开仓库与任何分发包;公开仓库是逐名白名单(18 个文件),多一个即失败。
|
|
323
|
+
|
|
324
|
+
### 9.2 自检命令
|
|
325
|
+
|
|
326
|
+
```powershell
|
|
327
|
+
python -m release_surface repo --complete # 开发仓库侧: 白名单文件齐备(AGENTS.md 按映射查 docs/ 源)
|
|
328
|
+
python -m release_surface content # 内容黑名单: 设备 SN / 本机路径 / 下线渠道痕迹 + 改名条目锚点
|
|
329
|
+
python -m release_surface wheel # 构建后: wheel 结构白名单(含三份发布面文档)
|
|
330
|
+
python -m release_surface sdist # 构建后: sdist 结构白名单
|
|
331
|
+
python -m release_surface pyproject # py-modules 与白名单逐项一致
|
|
332
|
+
python -m release_surface tag-check # tag 与 __version__ 一致(静态读取)
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### 9.3 测试分层(开发仓库)
|
|
336
|
+
|
|
337
|
+
```powershell
|
|
338
|
+
python -m pytest tests/ -k p0 -q --tb=short # 纯计算, 秒级, 改 CLI 参数前先跑
|
|
339
|
+
python -m pytest tests/test_p3_cli.py -q --tb=short # CLI 子进程层(退出码 / 参数校验 / manifest)
|
|
340
|
+
python -m pytest tests/ -n 2 --dist loadfile -q --tb=short # 全量并行(约 1 分钟)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
- **测试导出路径硬约定**:写 Excel/JSON 的用例必须显式指定导出路径并落在工作区内(用 `conftest.py` 的 `export_dir` fixture),不得依赖 `config.result_path`(工作区外)或输入文件同级的自动命名(会污染 `示例数据/`)。
|
|
344
|
+
- 示例数据在 `示例数据/`(`iv/`、`ECSA/`、`O2/`、`H+` 等子目录),被 `.gitignore` 忽略、只在开发机存在;缺数据导致的失败属环境问题,不是回归。
|
|
345
|
+
- `cli.py` 在 `_compile_check` 的 6 模块覆盖范围内;`launch.py` / `release_surface.py` 不在,改动后自行 `python -m py_compile launch.py release_surface.py`。
|
|
346
|
+
|
|
347
|
+
### 9.4 改 CLI 时要同步的面
|
|
348
|
+
|
|
349
|
+
| 改动 | 必须同步 |
|
|
350
|
+
|---|---|
|
|
351
|
+
| 新增/改名参数 | `cli.py` argparse、README 的「命令行(CLI)用法」段、本指南第 2/4 节、`tests/test_p3_cli.py` |
|
|
352
|
+
| 退出码语义 | README、本指南第 3.1 节、`tests/test_p3_cli.py` |
|
|
353
|
+
| manifest 键 | cli.py `_run_manifest`、`run_pipeline` 签名、README 示例、本指南第 5 节 |
|
|
354
|
+
| 自动命名规则 | `_shared.build_output_filename`(GUI/CLI/manifest 三处共用),README 与 docstring |
|
|
355
|
+
| 发布面文件增删 / 改名 | `release_surface.py` 的 `PUBLIC_REPO_FILES`(改名条目还要 `PUBLIC_REPO_SOURCES` + `PUBLIC_REPO_CONTENT_ANCHORS`)、`pyproject.toml` 的 `data-files`、`MANIFEST.in`、`python -m release_surface doc-block` 重生成清单块、`docs/发布注意事项.md`「零」 |
|
|
356
|
+
|
|
357
|
+
### 9.5 未提供的能力(不要找)
|
|
358
|
+
|
|
359
|
+
- 没有 JSON / stdout 结构化输出,没有 `--format`、`--quiet`、`--dry-run`(试算用 `--no-export`)。
|
|
360
|
+
- 没有断点续跑、并发、任务依赖;批量只有串行 + 失败继续。
|
|
361
|
+
- 没有 GUI 那样的图上交互精修:CLI 只能通过索引参数(`--co-left-index` 等)给端点。建议先用 `auto` 跑一次,从输出对象/日志读取自动选点结果,再据此微调索引。
|
|
362
|
+
- CLI 不做版本检查、不装依赖、不动配置文件(写配置只有 GUI 配置编辑器一处)。
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
本项目遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 风格,版本号为 `YYYYMMDD` 日期式。
|
|
4
|
+
|
|
5
|
+
本文件随程序一起提供:pip 安装后在 Python 安装位置下的 `fcdp\` 目录里(虚拟环境即 venv 根目录下的 `fcdp\`),源码副本就在程序目录里;程序内「检查更新 → 查看更新说明」可直接打开。
|
|
6
|
+
|
|
7
|
+
## [20261015] - 2026-10-15
|
|
8
|
+
|
|
9
|
+
### 新增
|
|
10
|
+
|
|
11
|
+
- **程序内检查更新与一键升级**:「帮助 → 检查更新」在启动后自动检查一次(可用配置项 `auto_check_update` 关闭),也可随时手动检查。发现新版本后可点「立即更新」,程序随即退出并在后台完成升级;**升级不会自动重启,请手动重新打开**,下次启动会弹一次结果(成功或失败原因)。升级失败不影响当前版本继续使用。
|
|
12
|
+
- **桌面启动器 `launch.py`**:双击即用,自动定位程序、检查依赖并启动界面;找不到程序或缺依赖时给出可照抄的命令。它不联网、不检测版本、不改任何配置。
|
|
13
|
+
- **说明文档随包提供**:`README.md`、`CHANGELOG.md` 与面向 AI / 自动化调用的 `AGENTS.md`(CLI 使用指南)现在随安装包一起分发,装在 `<Python 前缀>\fcdp\` 下;「关于程序 → 程序介绍」与「检查更新 → 查看更新说明」能直接打开本机的说明与变更日志。
|
|
14
|
+
|
|
15
|
+
### 变更
|
|
16
|
+
|
|
17
|
+
- **分发方式只有 pip 一条**:`pip install fcdp` 是唯一官方渠道;不再提供 exe、zip、源码压缩包等任何打包副本。从源码仓库 clone 仍可运行,但不提供维护,也不能在程序内升级(请重新拉取源码)。
|
|
18
|
+
- **配置文件位置按安装方式决定**:pip 安装读写 `%LOCALAPPDATA%\FCDP\config.json`;源码副本读写程序目录下的 `config.json`(首次保存时生成)。升级不会覆盖你的配置。
|
|
19
|
+
- **帮助菜单**改为三项:「关于程序」(内含程序介绍 / 许可协议)、「检查更新」、「版本信息」。
|
|
20
|
+
- **命令行**:`--config` 指定的配置文件不存在时直接报错退出(退出码 2),不再静默改用默认配置。
|
|
21
|
+
|
|
22
|
+
### 修复
|
|
23
|
+
|
|
24
|
+
- 升级路径更可靠:只读安装目录、网络中断、装完读不到版本号等情况都会如实反馈并给出退路,不会静默失败。
|
|
25
|
+
- 安装形态判断更准确:源码副本与 pip 安装不再互相串用配置文件。
|
|
26
|
+
|
|
27
|
+
### 说明
|
|
28
|
+
|
|
29
|
+
- 仅 Windows 为官方支持平台,需 Python 3.12 及以上。
|
|
30
|
+
|
|
31
|
+
## [20260814] - 2026-08-14
|
|
32
|
+
|
|
33
|
+
正式发布版(首个模块化重构版本)。
|
|
34
|
+
|
|
35
|
+
### 新增
|
|
36
|
+
|
|
37
|
+
- **EIS 阻抗谱处理**:读取 Gamry `.DTA`,绘制 Nyquist 图,自动搜索高/低频拟合段并计算膜内质子传导阻力。
|
|
38
|
+
- **命令行模式**:无界面完成计算与导出,支持批量任务清单(`--manifest`);退出码区分成功(0)/ 运行错误(1)/ 参数错误(2)。
|
|
39
|
+
- 五条管线齐备:IV(含 H2 渗透、MA)、ECSA(CO-stripping / HUPD)、O2 氧传输阻力、EIS 阻抗谱。
|
|
40
|
+
|
|
41
|
+
### 变更
|
|
42
|
+
|
|
43
|
+
- **程序重构为模块化结构**(此前是单文件):启动更快、功能之间互不影响,界面与计算结果保持一致。
|
|
44
|
+
- 导出文件统一自动命名:`{模式}_{数据文件夹名}_{时间戳}.xlsx`。
|
|
45
|
+
- O2 的电池面积一律取配置值(`.DTA` 文件里的面积字段不采用)。
|
|
46
|
+
|
|
47
|
+
### 修复
|
|
48
|
+
|
|
49
|
+
- IV 起始位置、H2 拟合容差、阻抗重复点、O2 限流定位、ECSA 自动选点等一批计算问题修正。
|
|
50
|
+
- Excel 写入失败(文件被占用、无写权限等)时的提示与回滚更可靠。
|
|
51
|
+
|
|
52
|
+
### 移除
|
|
53
|
+
|
|
54
|
+
- 旧的 JSON 输入通道(`fcdp.json` / `fcdp_debug.json`)。
|
|
55
|
+
- 免安装打包脚本(分发方式改为 pip)。
|
|
56
|
+
|
|
57
|
+
## 说明
|
|
58
|
+
|
|
59
|
+
- 查看当前版本:程序内「帮助 → 版本信息」,或命令行 `fcdp --version`。
|
|
60
|
+
- 安装与升级:`pip install fcdp` / `pip install -U fcdp`。
|
|
61
|
+
- 详细使用说明见随包的 `README.md`(程序内「关于程序 → 程序介绍」)。
|
|
62
|
+
- 本文件自 `20260814` 起记录;更早的版本已不再维护。
|
fcdp-20261015/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yan Jiajun
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# 随 wheel/sdist 携带根级数据文件。
|
|
2
|
+
# 与 pyproject.toml 的 include-package-data = true 配合:
|
|
3
|
+
# 扁平 py_modules 结构无法用 package-data 键携带根目录文件 (package-data 键须为包名)。
|
|
4
|
+
#
|
|
5
|
+
# 注意: 不再 include config.json。配置文件一律不随任何分发包发布 (见
|
|
6
|
+
# docs/历史归档/发布与分发设计依据_归档_2026-10-15.md 8.2 节 B2): 开发者本地那份含设备 SN 与本地路径,
|
|
7
|
+
# 用户侧则在内置默认值基础上由程序在首次保存配置时生成。
|
|
8
|
+
|
|
9
|
+
# sdist 不含测试: 需要测试的人用 git 仓库, 不必要在 PyPI 的源码包里带第二份副本。
|
|
10
|
+
# (setuptools 默认会把 tests/ 收进 sdist, 故这里显式 prune。)
|
|
11
|
+
prune tests
|
|
12
|
+
|
|
13
|
+
# sdist 也不含发布面自检脚本 (它只随公开仓库提供, 见 docs/发布注意事项.md「零、发布面总览」)。
|
|
14
|
+
exclude release_surface.py
|
|
15
|
+
|
|
16
|
+
# CHANGELOG.md 必须随 sdist 携带: pyproject 的 [tool.setuptools.data-files] 把它装进 wheel,
|
|
17
|
+
# 而从 sdist 构建 wheel 时该文件要在源码树里存在, 否则 `pip install <sdist>` 装出来的包里没有它。
|
|
18
|
+
# (README.md 是 [project].readme, setuptools 默认 glob 已包含, 无需在此重复。)
|
|
19
|
+
include CHANGELOG.md
|
|
20
|
+
|
|
21
|
+
# AGENTS.md (agent CLI 指南) 同理: data-files 也要它, 少一份 wheel 自检即失败。
|
|
22
|
+
# 注意它的**来源**: 公开仓库里根目录的 AGENTS.md 由 docs/Agent使用CLI指南.md 复制改名而来
|
|
23
|
+
# (映射见 release_surface.PUBLIC_REPO_SOURCES); 开发仓库根也有一份同名文件, 那是开发约定,
|
|
24
|
+
# 因此**构建一律在公开仓库工作副本执行** —— 在开发仓库构建会把开发约定打进 sdist。
|
|
25
|
+
include AGENTS.md
|