Files
CADx-4/research-wiki/任务书/03-医生核对包.md
T
iomgaa 14d6f8e153 docs: 任务书 03 医生核对包;TIC 拟合约束文献核查记录
来源:负责人 2026-10-17 要求把 29 例处理结果整理成医生能看的格式并做成长期入口(表格 CSV、文字 PDF、视频不压缩、不向医生提问、问题清单只写现象);文献核查为负责人要求的质量门依据核对,结论待医生看过后再定。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:09:34 -04:00

155 lines
12 KiB
Markdown
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.
# 任务书 03:医生核对包
## 目标
把一次构建(`library/` + `answers/`)和它装入的那次 CEUS 运行,整理成医生不用写代码就能看懂的一个文件夹:表格一律 CSV,文字一律 PDF,图和视频原样。负责人把文件夹打成压缩包、用 U 盘拷给医生,请医生核对我们的处理结果。
这是一项**长期功能**:以后医生每交一版数据,跑完 `ceus_quant` 和 `build`,再跑一次本入口,就得到新的核对包。所以按正式模块写,带测试和 guide,不写成一次性脚本。
来源:负责人 2026-10-17「我们把处理完的结果……整理一份給医生看看」「不需要问医生问题」「文本文件尽可能 pdf,表格尽可能 csv」「需要作为一项长期的功能……有一个入口能执行这个」;视频不压缩(「本来视频就模糊,你压缩不是更模糊」);病例目录用医生的病例号、问题清单只写现象、没进库的病例只在表里出现(负责人 2026-10-17 认可)。
## 不做什么
- 不向医生提问,不做反馈表。
- 问题清单只写程序观察到的现象,不写原因推测、不写我们查过的文献、不写建议。
- 不改 CEUS 算法、不改质量门、不改资料库的内容。质量门的去留等医生看过之后再定(文献核查记录在 `research-wiki/scratch/2026-10-17-TIC拟合约束文献核查/`,本任务不用读)。
- 不压缩视频,不缩放、不重新编码任何图片和视频。
## 核对包的内容
```
runs/review_pack/<运行号>/
snapshot/ 快照(不给医生,打包时由负责人去掉;见下文)
医生核对包_<构建号>/ 负责人整个打包的就是这个目录
说明.pdf
问题清单.csv
病例总表.csv
标准答案/
化名对照.csv
诊断.csv
跳过病例.csv
报告复核句.csv
病例/
<病例号>/ 只有进了资料库的病例,目录名用医生的病例号(如 P001)
临床信息.csv
超声报告.pdf
MR报告.pdf
关键图.png
关键帧/<槽位>_第<秒>秒.png 例如 B0_第1.6秒.png;秒数保留一位小数;没定位的槽位没有文件
TIC曲线.png
TIC结果.csv
回放视频.mp4
```
逐项要求:
- **CSV**:UTF-8 带 BOM(Excel 双击打开中文不乱码),列名用中文。缺失值留空,不写 null、NaN。
- **`病例总表.csv`**:这次构建涉及的全部病例一例一行(进库的加跳过的;40 例交付包就是 40 行),按病例号排序。列:病例号、视频号、化名(没进库的留空)、是否进入资料库、没进的原因(检查编号和说明)、CEUS 定量是否成功、CEUS 失败在第几步、7 个槽位各一列(取到写视频时间秒数,没取到写「未取到」,CEUS 失败或没装 CEUS 时留空)。
- **`问题清单.csv`**:列为病例号、视频号、环节、问题。按病例号排序,一个病例可以多行。来源和写法见下文「问题清单的来源」。
- **`标准答案/`**:答案库的 4 张表照原样转成上面的 CSV 规格,列名不改。诊断编码和其他编码列照原值写;说明文件里写明编码含义(诊断 1 IPMN、2 SPN、3 MCN、4 SCN,出自交付包表头;其他编码列写「未解码」,解码开关见 `build.yaml`)。
- **`临床信息.csv`**:资料库临床一路的字段,一行;列名用交付包原列名。
- **`超声报告.pdf`、`MR报告.pdf`**:资料库里的报告原文(就是 AI 专家看到的那段,结论段已被程序去掉),PDF 第一行写「病例号 Pxxx 超声描述(结论段已去除)」之类的标题,正文照抄不改字。
- **`关键图.png`、`关键帧/`**:从资料库拷贝(已去附加数据的那份),逐字节不变,只改文件名。
- **`TIC曲线.png`、`回放视频.mp4`**:从 CEUS 运行目录逐字节拷贝。
- **`TIC结果.csv`**:把资料库的 `tic.json` 摊平成「项目、值」两列的长表:四条曲线各自的拟合是否成功和 R²、灌注指标逐项、紫圈曲线是否可用、7 个槽位的状态与时间或原因。项目名用中文加原字段名,例如「病灶整体曲线 拟合成功(roi_all.success)」。
- 没装 CEUS 结果的构建(`ceus_run` 为 null)也能出包:没有关键帧、TIC 曲线、TIC 结果、回放视频,病例总表里 CEUS 各列留空,说明文件写明这次没有 CEUS 结果。
### 问题清单的来源
每条都能追到某个已有文件里的某个值,不另做判断:
| 环节 | 来源 | 写法 |
| --- | --- | --- |
| 装配资料库 | 答案库的跳过清单 | 检查说明 + 涉及的文件、列和值,原样写 |
| CEUS 第 N 步 | CEUS 运行的 `failed.csv` | 「第 N 步失败:」+ 原因原文 |
| TIC 拟合 | `tic.json` 里病灶整体、病灶去暗区两条曲线 `success` 为 false | 「病灶整体曲线未完成拟合」(去暗区同理);原因码(如 `parameter_on_boundary`)照写在括号里,并在说明文件里逐个解释每个原因码的意思 |
| 关键帧 | `tic.json` 里没定位的槽位 | 「B0 未取到:」+ `reason` 原文 |
| 紫圈 | `pan_curve_usable` 为 false | 「紫圈曲线不可用」 |
报告复核句(`标准答案/报告复核句.csv`)不进问题清单,单独成表。
### 说明.pdf
源文件是仓库里的一份版本化 Markdown 模板(放在 `src/cadx/review/` 下,随代码走),出包时填入这次的构建号、CEUS 运行号、病例计数,再转成 PDF。至少写清:
1. 这个包是什么、从哪次交付数据处理来(构建号、CEUS 运行号、生成日期);包里含患者资料,只在临床方与我们之间传递。
2. 目录结构,每个文件是什么。
3. 每张 CSV 每一列的意思。
4. 我们的处理流程,用医生能懂的话分步讲(读交付包和检查 → CEUS 的第 1–9 步各做什么 → 装进资料库),问题清单里「环节」一列的每种取值对应哪一步。
5. 7 个关键帧各代表什么时刻、怎么取(B0、D1–D4 来自拟合曲线,F1、F2 按推注时间取),以及「未取到」的几种原因。
6. TIC 曲线图怎么看:每条线是什么(图上标注是英文,在这里逐个对照成中文)、竖线是什么。
7. 化名是什么、为什么有;报告里的结论段为什么被去掉(AI 专家不能看到医生的诊断倾向);资料库只放「所见」。
8. 编码列的含义(诊断编码,以及「未解码」的列)。
9. 跳过病例为什么整例跳过、每例只记第一项没过的检查。
转换工具:`pandoc` 把 Markdown 转成 docx,再用 `soffice --headless --convert-to pdf` 转 PDF(本机都有,中文字体用已装的 Noto CJK)。报告 PDF 用同一条路。两个工具的版本记进快照。工具缺失直接报错。
## 怎么实现
### 模块
新建组织层模块 **review**(`src/cadx/review/`),藏住「核对包长什么样」这个决定:目录布局、每个文件的格式、问题清单的来源与写法、说明模板。
- 依赖:library(按化名读出各路)、answers(读 4 张表)、runs(读快照、读 CEUS 运行,见下)。不依赖 build、delivery、ceus。
- 它读的是已经构建好的 `library/` 和 `answers/`,不碰交付包。病例总表里的 40 例 = 答案库的化名对照 + 跳过清单。
- 只有 library 能引用 PIL:review 拷图片只按字节拷,不打开图片。
**CEUS 运行目录的读取挪进 runs。** 现在 build 的 `_ceus.py` 自己读 `runs/ceus/<运行号>/` 的布局(`failed.csv`、`summary.json`、关键帧),review 也要读。按 `结构.md` 第三部分「出现第二个使用者再收进模块」,把**读 CEUS 运行目录**(打开运行、读 `failed.csv`、按视频号找结果目录和其中的文件)收进 runs,build 和 review 都经 runs 读。tic.json 挑哪些字段仍只在 build 里列(可见性的唯一决定处不动)。挪完 build 的行为不变,原有测试照过。
### 入口
`scripts/review_pack.py --config config/review_pack.yaml`。配置(字段定义在 review,全部必填):
- `library_dir`、`answers_dir`:某次构建的资料库和答案库目录,两者目录名(构建号)必须相同,不同就报错;
- `output_root`:`runs/review_pack`。
CEUS 运行从资料库 `manifest.json` 的 CEUS 来源字段读,不另配。
运行目录先写 `.partial`,跑完改名,已存在报错(规则同前两份任务书)。快照记 git 状态、配置原文、构建号、CEUS 运行号、pandoc 和 soffice 版本。快照放在 `医生核对包_<构建号>/` 外面,负责人只打包里面那个目录。
终端只打印计数:病例数、问题清单行数(按环节分)、PDF 份数、拷贝的视频总大小、耗时。不打印病例号。
### 规模
| 部分 | 预期行数 |
| --- | --- |
| review(含说明模板以外的代码) | 300–500 |
| `scripts/review_pack.py` | ≤ 80 |
| runs 增量(读 CEUS 运行) | ≤ 150,build 相应减少 |
## 测试
预期值照本任务书写,不从实现里推。用现有的假交付包和假 CEUS 运行(`tests/fake_delivery.py`、`tests/fake_ceus_run.py`)构建一次,再出包:
- 目录结构与上面一致;进库病例每例一个目录、名为病例号;跳过的病例没有目录、在病例总表和问题清单里有。
- 每张 CSV 以 BOM 开头、列名与本任务书一致、缺失值为空串。
- 问题清单:每种来源至少各造一例,断言行数和「环节」「问题」原文。
- 关键图、关键帧、TIC 曲线、回放视频与源文件逐字节相同;关键帧文件名的秒数等于 `tic.json` 里的 `video_time_s` 保留一位小数。
- `TIC结果.csv` 的值与 `tic.json` 逐项相同。
- `ceus_run` 为 null 的构建也能出包,CEUS 相关文件都不存在。
- 资料库与答案库构建号不同时报错。
- 说明和报告 PDF 生成成功、非空(这条依赖 pandoc 和 soffice,照常进 `make check`;如果让 `make check` 多出 30 秒以上,在报告里写明耗时,不自行加标记跳过)。
- build 原有测试全部照过(CEUS 运行读取挪进 runs 之后)。
## 真跑
用当前真实构建 `20261016-094248-1de88a5-dirty` 出一次包。报告:运行号、病例数、问题清单按环节分的行数、包的总大小、耗时;挑 1 个病例目录和 `说明.pdf` 的路径供负责人目视检查。不在报告里写病例号以外的任何病例内容。
## 文档
- 新写 `research-wiki/guides/医生核对包.md`:什么时候跑、怎么跑、产物在哪、打包前去掉 `snapshot/`。过一轮「硕士生阅读」。
- `结构.md`:第三部分加 review(组织层,可依赖 library、answers、runs),依赖表和 import-linter 契约同步;第四部分加核对包一节(指向本任务书和 guide,不抄布局);第五部分配置表加 `review_pack.yaml`;第六部分加规模;第八部分加对外接口。
- `WORK_LOG.md`。
## 审阅
「其余部分」那一档,写完派一个全新上下文的子 Agent 审一轮:只给本任务书、`结构.md` 第三到第五部分和 diff。重点:问题清单有没有漏掉某个来源、有没有写进推测性的话;拷贝是否逐字节;CEUS 运行读取挪进 runs 后 build 行为是否不变;review 有没有写进 `library/` 或 `answers/`(不许)。Codex 连不上就跳过。
## 报告
1. 提交号;各部分行数。
2. `make check` 完整输出。
3. 真跑结果(见上)。
4. 审阅意见和处理。
5. 和本任务书、`结构.md`、`AGENTS.md` 不一致的地方,以及为什么。