解釋中心
操作手冊 · 第 16 頁 · 公開可重現性邊界已標示

從零到 synthetic smoke:公開步驟與真實資料邊界

本頁保存 2026-08-05/06 的內部機器執行收據;不是任何人 clone 公開 GitHub 後都能在 10 分鐘完成的承諾。 tracked tiny synthetic fixture 可驗證 clone→build→run→schema;但 HCC1395 BAM、hg38 FASTA 與 VCF 未包含在公開 Git objects,因此 synthetic PASS不能升格成真實資料或生物結果重現。

公開重現狀態:SYNTHETIC_SMOKE_SUPPORTED / REAL_DATA_PREFLIGHT_REQUIRED `tests/fixtures/tiny_public/`追蹤 synthetic FASTA/VCF/SAM與schema;runner建立BAM/index及receipt。 這只驗證軟體接線,scope固定為DEMO。真實資料仍需使用者自備、授權、index與site preflight。
開始之前:先確認機器狀態 執行時間與容量都依硬體、mount 與輸入而異。跑真實資料前,先以 site profile/doctor 確認 CPU、 $DATA_ROOT mount、可用容量、輸入索引與 tool hash;本頁不承諾固定 runtime。
1
編譯 C++(runtime 依環境而異)

● 一定要先做這步。Git 不發布受版控的 build output;請依 release manifest checkout immutable commit,再在 repo 外 clean build。

git clone https://github.com/liaoyoyo/InterSubMod.git
cd InterSubMod
HANDOFF_COMMIT="<IMMUTABLE_HANDOFF_COMMIT_SHA>"
git checkout --detach "$HANDOFF_COMMIT"
test "$(git rev-parse HEAD)" = "$HANDOFF_COMMIT"
test -z "$(git status --porcelain)"

REPO_ROOT="$(pwd -P)"
BUILD_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/ism-build.XXXXXXXX")"
# repo 外的全新 Release build;不產生受版控 build output
cmake -S "$REPO_ROOT" -B "$BUILD_ROOT" -DCMAKE_BUILD_TYPE=Release
cmake --build "$BUILD_ROOT" -j$(nproc)
test -z "$(git -C "$REPO_ROOT" status --porcelain)"

執行檔數量與名稱是 commit-specific;由該次 clean-build receipt 動態保存,不手抄固定六個:

find "$BUILD_ROOT/bin" -maxdepth 1 -type f -perm -u+x -printf '%f\n' | sort
test -x "$BUILD_ROOT/bin/inter_sub_mod"
test -x "$BUILD_ROOT/bin/run_tests"
2
確認編譯結果是好的(不宣稱固定 runtime)
"$BUILD_ROOT/bin/run_tests"
ctest --test-dir "$BUILD_ROOT" --output-on-failure

本輪實跑的真實輸出:

[==========] <N> tests from <S> test suites ran.
[  PASSED  ] <N> tests.

$ echo $?
0

動態 N/N 通過,0 failure 如果這裡有任何失敗,先不要往下走 —— 後面跑出來的數字都不可信。

3
準備 Python 環境
# 建立與 hosted acceptance 相同的 hash-locked Python 3.10 環境
PYTHON_ENV="$(mktemp -d "${TMPDIR:-/tmp}/ism-python.XXXXXXXX")/venv"
python3.10 -m venv "$PYTHON_ENV"
"$PYTHON_ENV/bin/python" -m pip install --require-hashes \
  --requirement "$REPO_ROOT/requirements-ci.lock"
export PATH="$PYTHON_ENV/bin:$PATH"
● Python 版本是 hard requirement Public acceptance workflow 與 hash-locked CI 使用 Python 3.10:
指令版本用途
python3.103.10site tooling、portable workflow、fixture validation 與嚴格區域切割
先跑 python3.10 --version;缺少 3.10 應 fail closed,不把 import/dataclass 錯誤誤判成研究程式缺陷。 一般研究繪圖可另依 requirements.txt 建環境,但那不是 handoff acceptance receipt 的環境。
4
Public tiny synthetic E2E(DEMO)

DEMO tracked synthetic FASTA/VCF/SAM會在新暫存目錄轉成BAM/index,完成build→run→schema validation。 這不是生物資料、benchmark或science validation。

"$REPO_ROOT/scripts/handoff/run_tiny_public_e2e.sh" --repo-root "$REPO_ROOT" --jobs 4
TINY_E2E_RESULT {"all_pass": true, ...,
  "tree_semantics": "read_dendrogram_from_methylation_distance_not_cellular_lineage"}

驗收:exit 0、all_pass=true;scope固定為 DEMO,不寫入science validation ledger。

進階:自備/內部真實資料(internal-data example)

INTERNAL-ONLY 下列三個輸入路徑未隨公開 GitHub 發布; 只有已取得資料與授權的環境才能執行;歷史 HCC1395 receipt 不是一般 runtime promise。

# 將 placeholder 換成本機 profile;絕對路徑只維護於 untracked machine profile/registry
SITE_PROFILE="<SITE_PROFILE>"
"$REPO_ROOT/scripts/site/doctor" --profile "$SITE_PROFILE" --mode real-preflight
eval "$("$REPO_ROOT/scripts/site/site_profile.py" shell \
  --profile "$SITE_PROFILE" --sample HCC1395)"
SP="${TMPDIR:-/tmp}/ism_demo" && mkdir -p "$SP"

# 準備只含第一筆 biallelic SNV 的 smoke-test VCF
bcftools view -h "$SOMATIC_VCF" > "$SP/one_snv.vcf"
bcftools view -m2 -M2 -v snps -H "$SOMATIC_VCF" | head -n 1 >> "$SP/one_snv.vcf"
test "$(bcftools view -H "$SP/one_snv.vcf" | wc -l)" -eq 1

# 跑(只給三個必填參數)
"$BUILD_ROOT/bin/inter_sub_mod" \
  --tumor-bam  "$TUMOR_BAM" \
  --reference  "$REFERENCE" \
  --vcf        "$SP/one_snv.vcf" \
  --output-dir "$SP/out_min"

2026-08-06 內部環境的歷史實跑輸出(只屬具名輸入 receipt,不作 runtime 驗收值):

Total regions: 1 / Successful: 1 / Failed: 0
Total reads processed: 85
Forward strand (+): 40 / Reverse strand (-): 45
Total CpG sites found: 11
Metric: NHD / Total valid read pairs: 3443 / Total invalid pairs: 127
兩個預設值和說明文件不一樣,先知道比較好 --threads 說明寫預設 1,實際是 16(資源估算會差 16 倍)。
未指定 --distance-metric 時 effective CLI default 是 NHD;明示 NHD、 BERNOULLI 或重複多值都會保留。多值時只有第一個 metric 驅動 clustering,後續只多輸出 distance matrix,因此順序會改變 tree/cluster。
公開 fixture 契約已追蹤;CI 必須持續驗證 tests/fixtures/tiny_public/ 已固定 synthetic reference contig/座標、VCF header、MM/ML 與 HP/PS tag 條件、schema 與授權;runner 在暫存目錄建立 BAM/index。每次仍須由 exact-commit clean clone 保存 exit code、stdout 摘要、輸入/輸出 checksum,且 receipt 固定標為 DEMO/synthetic smoke,不能升格 science validation。
5
看結果
find $SP/out_min -type f | head -20

輸出分兩層。先看這三個檔:

檔案看什麼
<region>/metadata.txt這個位點抓到幾條 read、幾個 CpG、矩陣多大 —— 先確認數字合理。
<region>/reads/reads.tsv每條 read 的單倍型標籤與支持突變型/正常型。
significance_summary.csvrun 層總表,下游分析幾乎只吃這一份。
● 讀輸出檔時的三個必知
1. methylation.csv 第一欄是列號不是 read 名,要對回 read 得查 reads.tsv。
2. linkage_matrix.csv 副檔名是 csv 但實際是 tab 分隔 —— pd.read_csv() 預設會整列讀成單欄而且不報錯,要寫 sep='\t'。
3. tree.nwk 的葉子是 read 不是 clone —— 這是甲基化相似度的分群樹,不是亞群演化樹。
6
驗證歷史 35,332-site 方法文件(限此 scope)
cd docs/methodology/_assets/20260627_subclone_4axis_teaching/scripts
python3 verify_pipeline_numbers.py

這支只重算歷史 35,332-site pipeline 的 TP/FP 與共現分類數字。它不驗證 2026-07-24 exact-PS、LongLineage、storage、程式碼/測試計數或本頁 Step 4 的公開可重現性。歷史實跑輸出:

sSNV 總數 35,332(TP 30,490 / FP 4,842)              ✓
共現連上 21,554 · 訊號不足 5,458 · 孤立 8,320        (加總 = 35,332 ✓)

對得上,只代表該歷史方法文件的受管數字與它所讀取的 artifacts 一致;其他 claim family 必須各用 authority manifest、receipt 與專用 validator 驗證。

07全流程速查

圖 1 · 六個步驟與各自的驗收點
操作六步驟流程 六個步驟依序為:編譯、跑測試、裝 Python 依賴、tracked tiny DEMO 試跑、檢視輸出、驗證歷史 35,332-site 文件;tiny fixture 存在於 Git,但 synthetic smoke 只驗證接線,不是 science validation。 1 編譯 cmake + build 依環境而異 2 跑測試 run_tests 0 failure 3 Python 依賴 requirements-ci.lock Python 3.10 + hashes 4 tiny DEMO tracked fixture synthetic smoke only 5 看輸出 metadata / reads significance_summary 6 歷史 scope 驗證 verify_pipeline_numbers.py 每一步的驗收條件(不過就停下來,別往下走) 1 編譯 → clean-build receipt 動態記錄 executable inventory 2 測試 → 動態 N/N、0 failure、退出碼 0 3 依賴 → import pysam 不報錯 4 tiny DEMO → fixture PASS;只驗接線,非科學驗證 5 輸出 → region 目錄下有 methylation 與 distance 6 驗證 → 只涵蓋歷史 35,332-site 受管數字 任何一步的退出碼不是 0,或數字對不上 —— 先解決再繼續,否則後面的結果都不可信。

08常見狀況排除

症狀原因與解法
程式直接停,說找不到參考基因組 參考 FASTA 缺 .fai 索引是硬性錯誤。跑 samtools faidx 建索引。
Python 腳本 import 就崩,錯誤指向 dataclass Python 版本問題,不是程式壞了。改用 /usr/bin/python3.10。
CI 判定 --help 失敗 --help 的退出碼是 1 不是 0(與參數錯誤共用同一路徑)。改寫檢查方式。
某支腳本跑了但什麼都沒發生 可能是函式庫不是入口(如 ism_heatmap_std.py)。看它有沒有 argparse。
讀 CSV 後整列變成一欄 linkage_matrix.csv 實際是 tab 分隔。加 sep='\t'。
跨 run 比較時欄位對不上 目前稽核版本的 significance_summary.csv 有 199 欄,並含 VerificationSchemaVersion=2 與 RegionStratificationSchemaVersion=1 兩個元件 schema;沒有單一 whole-file layout version。解析時須用欄名,並同時驗證必要欄位集合與兩個 component versions。
工作站 HTML 開很久/瀏覽器很卡 單檔可達 188 MB。示範時先開最小的那個(約 14.6 MB)。
LongLineage 說 KernelBlocked 這是預期行為不是故障。正式入口刻意 fail-closed,見 LongLineage 分冊。