CBT_project/AGENTS.md
Xiao Furen 332226f843 Add pixi.toml configuration for project dependencies and tasks
- Created a new pixi.toml file to manage project dependencies and tasks.
- Defined workspace metadata including authors, channels, name, platforms, and version.
- Specified tasks for preprocessing, PSO, DE, and other scripts.
- Listed dependencies for Python and various libraries with specific versions.
- Configured additional PyPI options for PyTorch installation from a custom index.
2026-10-19 20:34:28 +08:00

80 lines
No EOL
7.4 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.

# AGENTS.md
本文件提供 AI 編碼代理(Kilo / Claude 等)在 `CBT_project` 內工作時的指引。
## 專案概述
CBT(Cortical Bone Trajectory,皮質骨軌跡):在腰椎 CT(L1–L5)上自動規劃椎弓根螺絲(pedicle screw)軌跡。將螺絲建模為圓柱體,以 PSO / DE / Nelder-Mead 最佳化在骨頭 mask 上評分(皮質骨接觸、椎體 VBODY 獎勵、tip 處罰、入口端 0.5mm 豁免),取得最佳位置/角度/尺寸後再映回 native CT 空間。
## 執行環境
- Python 環境:**pixi**(conda env `cbt` 已棄用)。環境在 `.pixi/envs/default/`,python 3.14;`pixi.toml` 定義全部依賴與 tasks。VS Code 已設定 `python.defaultInterpreterPath` 指向 pixi env。
- `xfr_*.py` 的 shebang 為 `#!/usr/bin/env python`,需先 `pixi shell` / `pixi run`(或 VS Code 選到 pixi interpreter)才有對的 python。
- 重建環境:`pixi install`(torch 走 `extra-index-urls` 的 pytorch cu126 index,版本 pin 在 `pixi.toml`)。
- 主要依賴(皆 pypi):`torch`(CUDA,GPU 最佳化)、`SimpleITK`、`scipy`、`scikit-learn`、`numpy`、`nibabel`、`tinydb`、`pyswarm`、`matplotlib`。conda 端只有 python。
- **無測試、無 lint 設定**。驗證方式:跑小批量 volume、檢查 logs/ 與結果 CSV、以及螺絲柱 in-label 比例(xfr_cbt_native 的 docstring 有驗收標準)。
## 資料位置(皆在 repo 之外,勿把大檔 commit 進 repo)
| 用途 | 路徑 |
|---|---|
| 原始 CT / label(CTSpine1K) | `/mnt/1220/Public/dataset/Spine/CTSpine1K/{data,label}/`(子資料夾:`colon`(=conlon)、`COVID-19`、`HNSCC-3DCT-RT_neck`、`liver`(=Liver)) |
| 標準化輸出(current) | `/mnt/1248/open2/cyrou/CBT/Seg/Resample/standardized-xfr-3/` |
| 最終輸出(cbt.nii.gz、X 光投影) | `/mnt/1248/open/cyrou/Output/` |
| 元資料庫(TinyDB) | repo 根目錄 `xfr_image_metadata.json`(table `images`,key = volume `name`) |
| 進度 / 日誌 / 結果 | `progress.json`、`logs/`、`results/`(皆已被 gitignore) |
`xfr_*.py` 頂部有 hardcode 的資料路徑(`standardized_dir`、`data_root`、`label_root`、`Output_dir`);跑別世代資料時改這些常數,不要假設 CLI 可覆蓋。
## 目錄結構
```
core/ 圓柱生成(torch)、中心線相交、評分、objective、optimizer(PSO/DE/NM)
imaging/ nifti_io、preprocessing、resample、affine、orientation、segmentation、transforms
visualization/ res_bone_figure(四視角螺絲圖)、res_plot_3d、res_cyl_nifti(存 NIfTI)、res_cyl_to_CT(overlay)
config/ constant.py(LABEL_MAP、螺絲尺寸、OVERLAP_THRESH、DEFAULT_SPACING)、device.py
utils/ helpers.py(retry_robust、unique filepath、save_with_unique_name)
xfr_*.py 現世代管線入口腳本(見下)
run_*.py 舊世代多 GPU 批次 / benchmark 腳本(base_dir 不同,較少使用)
references/ 文獻 PDF(唯讀參考,勿改)
experiment.ipynb 實驗 notebook
```
## 管線流程與入口腳本
入口腳本都有對應 pixi task:`pixi run <task> -- <args>`(task 清單在 `pixi.toml [tasks]`:`preprocess`、`pso`、`de`、`check-spinous`、`rerender-spinous`、`cbt-native`、`record-planes`、`plot-level`)。以下直接列腳本名,加 `./` 前缀在 pixi 環境內亦可執行。
1. **預處理**:`xfr_preprocess.py [--max-images N] [--output-dir DIR]`
裁切各 level、重取樣到 0.5mm、方向正規化(best_symmetry_plane / best_upper_endplate_plane),輸出 `<vol>/crop/` 與各 level 的 mask,並把仿射鏈寫進 `<vol>/transform.json`。
跳過條件:z spacing > 4mm、lumbar label < 2、椎弓根寬度 > 18mm(clip 並標 `_clipped`)。
2. **最佳化**:`xfr_pso.py [volume_id [level]] [--screw-shape cone|cylinder]`(DE 版:`xfr_de.py`)
每 level 左/右各跑一支 PSO,輸出螺絲參數與 `render_bone_figure` 四視角圖、CSV。
3. **驗證**:`xfr_check_spinous.py`、`xfr_rerender_spinous.py`(棘突檢查/重繪)。
4. **映回 native**:`xfr_cbt_native.py <run_id> [volumes...] [--date D]`
用 `transform.json` 正向鏈把螺絲映回 native CT,輸出 `cbt.nii.gz`(label 1–10 = L1L…L5R)與 x-ap/x-lat/z-ap/z-lat 投影圖。
5. **輔助**:`xfr_record_planes.py`(記錄平面入 transform.json)、`xfr_inverse_transform.py`(單一 mask 逆向映射)、`xfr_orig_labels.py`(原始 label 對齊)、`xfr_reprocess_ap.py`(AP 方向修正)、`xfr_plot_level.py`(單 level 圖)、`xfr_migrate_crop.py`(舊佈局遷移到 crop/)。
## 程式慣例(重要)
- **註解 / docstring 用繁體中文**,識別符號用英文。新增碼保持同風格。
- **座標系**:numpy 體積為 `(Z, Y, X)`;螺絲參數 `pos = [z, y, x, az°, alt°, d_mm, L_mm]`(xfr 變體為 `[z, x, az°, alt°, d, L]`,y 由 `y_indices` surface 推導,見 `core/optimizer.py::get_first_nonzero_y`)。spacing 為 `[sx, sy, sz]`,預設 0.5 isotropic。
- **Objective API**:新碼一律用 `core/objective.py` 的 `OptimizationContext` + `make_objective_function[_xfr]`。**禁止依賴 module globals**(`set_global_context` / `objective_function` 是 legacy 兼容路徑,保留勿擴充)。
- **螺絲尺寸離散化**:`snap_to_discrete_values`(`config.constant.ALLOWED_DIAMETERS/ALLOWED_LENGTHS`);xfr 管線用 `snap_to_discrete_values_xfr`(`core/cylinder.py` 的 `points` 允許 (d, L) 組合表)。xfr 還做 0.9/0.1 混合(`diameter_loss = .9*discrete + .1*raw`)。
- **transform.json 是 native 映射的單一事實來源**(`imaging.transforms.original_to_source`)。fallback 重算路徑僅供舊世代 volume;改映射邏輯時先讀 `xfr_cbt_native.py` docstring 的驗證紀錄。
- **元資料庫是 TinyDB**:用 `xfr_preprocess.py::_upsert_by_name` 一類的 upsert 寫入;勿手改 JSON 結構(legacy 遷移邏輯對結構敏感,見 `_migrate_legacy_metadata`)。
- **NFS 瞬時錯誤**:輸出樹在 NFS 上,`os.makedirs`/寫檔可能短暫 ENOENT/EEXIST。沿用 `utils.helpers.retry_robust` 或 `core/optimizer.py::_makedirs_retry` 的重試模式;勿裸 `os.makedirs` 建輸出目錄。
- **日誌**:腳本寫 `logs/xfr_<script>_<timestamp>.log`;logger 名稱與腳本一致。
- **不覆蓋輸出**:存檔用 `utils.helpers.get_unique_filepath` / `save_with_unique_name`(自動 `_1`, `_2` 後綴)。
- 檔案命名含螺絲參數時,長度進檔名不帶小數(35.0→35)、直徑保留一位小數(`utils.helpers._fmt_length`)。
## 多 GPU / 批次
`run_all_cases.py --gpu N --total_gpus M`:病人依 index % total_gpus 分配;`run_benchmark.py` / `run_de.py` / `run_pso.py` 為 benchmark 腳本,結果 CSV 在 `optimization_benchmark_results_*.csv`。舊腳本的 `base_dir` 指向 `/home/cyrou/...`(可能已遷移),跑前確認路徑。
## 修改注意事項
- `references/` 唯讀。
- `xfr_image_metadata.json`、`progress.json`、`logs/`、`results/`、`.kilo/` 已 gitignore,勿 commit。
- `core/scoring.py`、`imaging/orientation.py` 有 xfr 版本(`cl_score_torch_xfr`、`segment_spinous_process` 等)與原版並存;改評分邏輯時確認呼叫方用哪個版本(objective 目前用 `_xfr`)。
- 改 `LABEL_MAP` 或 level 集合時,同步檢查 `xfr_cbt_native.py` 的 label 值定義(L1L=1 … L5R=10)。
- GPU 不可用時多數 torch 路徑會 fallback CPU,但速度極慢;跑完整最佳化前確認 CUDA 可用。