diff --git a/agents/data/split_policy_v0.md b/agents/data/split_policy_v0.md index fc137d4..c5507c7 100644 --- a/agents/data/split_policy_v0.md +++ b/agents/data/split_policy_v0.md @@ -89,7 +89,7 @@ TCGA biotab의 결측 토큰: `[not available] / [not applicable] / [unknown] / | **ER status (IHC)** | binary (Positive/Negative). 결측 → 해당 환자를 **ER task에서 제외** (전체 제거 아님). | | **PR status (IHC)** | 동일 (binary, 결측 시 PR task 제외). | | **HER2 status (IHC)** | binary. `equivocal`(IHC 2+, FISH 미확정)은 **결측 처리** → HER2 task 제외 (소음 라벨 차단). | -| **PAM50 (4-class)** | LumA/LumB/HER2-E/Basal. Normal-like는 **제외** (형태학 신호 빈약, Tafavvoghi 정렬). PAM50은 biotab clinical_patient에 없음 → **별도 소스(TCGA-BRCA 2012 / cBioPortal)에서 환자 단위 join** 후 채움. | +| **PAM50 (4-class)** | LumA/LumB/HER2-E/Basal. Normal-like는 **제외** (형태학 신호 빈약, Tafavvoghi 정렬). PAM50은 biotab clinical_patient에 없음 → **별도 소스에서 환자 단위 join** 후 채움. 정본 소스 = `tcga_brca_pam50_computed.csv`(Parker 2009 nearest-centroid 계산본, §10.1) — cBioPortal curated study가 아니다. | **중요: 결측은 task별(per-target)로 행을 마스킹**하되 split 배정에는 영향을 주지 않는다. 즉 split은 환자 전체 집합에 대해 **한 번** 결정되고, 각 phenotype head는 자기 라벨이 있는 환자 부분집합에서만 학습/평가한다 → split 정의가 target마다 달라지는 것을 방지 (재현성). @@ -151,7 +151,7 @@ split 정의(JSON: case_id → fold) → sha256 → split_hash - [ ] **site-disjoint == True** : 어떤 `tss_code`도 둘 이상 fold에 없음. - [ ] **CPTAC 격리** : CPTAC 케이스가 TCGA train/val에 0건. - [ ] **site-classifier probe AUC 보고** : FM 임베딩으로 submitting-site 예측 (one-vs-rest AUROC). Howard 기준선(0.964–0.998) 대비 residual site leakage 강도를 **숫자로** 리포트 (Exp2-A). 높을수록 site-aware split의 정당성이 강해짐. -- [ ] **라벨 정의 단일 소스** : ER/PR/HER2 = biotab IHC, PAM50 = 단일 외부 소스 고정 (train/test 간 정의 드리프트 차단). +- [ ] **라벨 정의 단일 소스** : ER/PR/HER2 = biotab IHC, PAM50 = `tcga_brca_pam50_computed.csv`(Parker 2009 계산본) 단일 고정 (train/test 간 정의 드리프트 차단). 소스 확정 근거·정정 경위는 §10.1. - [ ] **temporal/parametric 채널 명시** : FM(UNI/CONCH)의 parametric 지식은 통제 불가 채널로 잔존 → de Jong 2025 (FM이 medical-center 시그니처 인코딩) 인용하고 floor로 site-probe AUC를 보고. stain normalization은 보조일 뿐 단독 방어 아님 (Howard #4). --- @@ -217,4 +217,14 @@ Critic cross-sign 완료(2026-07-13): split_policy_v0 + split_hash **5995f29d397 ## 10. Leader 결정 반영 (2026-06-10, kkkim) - **Subset = 전체 1010 (full BRCA cohort)** — Paper A 범위를 1010으로 확정. ⚠️ CLAUDE.md "~150 subset" 금지조항(line 220/239) override → 거버넌스 갱신 필요. site-disjoint split 검정력 확보. -- **PAM50 소스 = cBioPortal TCGA-BRCA PAM50** (1순위, 분류기 정의 Parker 2009 인용); 커버리지 부족 시 TCGA RNA-seq + genefu(Parker centroids) fallback. → §4·§7 라벨 정책에 반영. +- ~~**PAM50 소스 = cBioPortal TCGA-BRCA PAM50** (1순위, 분류기 정의 Parker 2009 인용); 커버리지 부족 시 TCGA RNA-seq + genefu(Parker centroids) fallback.~~ → **2026-08-20 Leader 결정으로 대체됨(아래 §10.1).** + +## 10.1 PAM50 소스 정정 (2026-08-20, kkkim — BIOP02-74) + +위 06-10 결정문("cBioPortal 1순위, 커버리지 부족 시에만 fallback")은 **실사용과 어긋나 있었다**. 기록을 지우지 않고 정정 경위를 남긴다. + +- **실제 정본 소스 = `agents/data/manifests/tcga_brca_pam50_computed.csv`** — cBioPortal의 curated study가 아니라 **Parker 2009 nearest-centroid classifier로 발현에서 계산한 라벨**이다(Parker et al. 2009, JCO, DOI `10.1200/JCO.2008.18.1370`). 근거: `tcga_brca_pam50_computed_PROVENANCE.md`(BIOP02-49 후속, kkkim 2026-07-10) — `tcga_brca_manifest.csv`의 pam50 보유 case **1009/1009(100%)**가 이 파일과 일치해 소스가 확정됨. +- **06-10 문구가 어긋났던 이유**: fallback은 "cBioPortal 커버리지 부족 시"에만 승인됐는데, 실측 커버리지는 부족하지 않았다 — 대조 소스 `brca_tcga_pan_can_atlas_2018`(`SUBTYPE`, PATIENT-level)이 manifest PAM50 코호트를 덮는 비율 **981/1009 = 97.2%**(`cbio_coverage_of_manifest_cohort_pct`). 즉 fallback 발동 조건이 충족된 적이 없는데 fallback 쪽이 전 코호트에 쓰이고 있었다(BIOP02-74에서 실측, `pam50_source_reconcile.py` / `pam50_source_reconcile_biop02-74.json`). +- **결정(kkkim, Jira 11999)**: **Parker 계산본을 정본으로 유지한다.** cBioPortal로 전환하지 않는다. 이유 — (a) Paper A/C 분석이 이미 이 라벨로 수행·검증됐고(manifest 100% 일치 + PROVENANCE), 전환은 전면 재실행이자 근거 없는 골대이동이다. (b) Parker centroid는 PAM50의 정본 분류기라 인용 가능하다. +- **57.0% 불일치(514/902)는 오류가 아니라 파생 차이다** — 로컬 발현-계산본 vs curated atlas. 불일치는 무작위가 아니라 문헌상 알려진 두 경계에 집중된다(local=LumB↔cBio=LumA 141명, local=Normal↔cBio=LumA 101명). **투명성 항목으로 Methods에 보고**한다(어느 쪽이 틀렸다는 뜻이 아니다). +- **잔여 gap(비차단)**: 이 CSV를 만든 계산 스크립트와 입력 발현 행렬(study_id·버전)은 아직 레포에 없다 — 완전 재현용 후속 과제(PROVENANCE "남은 gap", braveji `594ef6b`에서도 비블로커로 확인). diff --git a/guide/paper_a_methods_data_draft.md b/guide/paper_a_methods_data_draft.md index a1944d4..17c832a 100644 --- a/guide/paper_a_methods_data_draft.md +++ b/guide/paper_a_methods_data_draft.md @@ -51,29 +51,37 @@ biotab. **Corrected 2026-08-20** (BIOP02-49's provenance follow-up, `tcga_brca_p PROVENANCE.md`, landed on `main` after this draft was first written): the committed TCGA PAM50 calls are **not** a cBioPortal-sourced file — they are a locally-computed nearest-centroid classification (Parker et al. 2009 method, confidence range 0.808–0.925) run against expression -data outside this repo. `split_policy_v0.md` §10 names cBioPortal TCGA-BRCA PAM50 as the -*primary* source with the local/genefu computation as a *fallback for coverage gaps* — the -manifest as committed uses the fallback for the entire cohort, not cBioPortal. For CPTAC, PAM50 +data outside this repo. `split_policy_v0.md` §10 originally named cBioPortal TCGA-BRCA PAM50 as +the *primary* source with the local computation as a *fallback for coverage gaps*, which did not +describe what the manifest actually does; that policy text has since been corrected to name the +computed calls as the source of record (§10.1, data-owner decision 2026-08-20). For CPTAC, PAM50 comes from the same `brca_cptac_2020` release as the other endpoints; class naming was normalized across cohorts (CPTAC's `Her2` → `HER2`) so both use identical class labels. -**Open item — PAM50 source pinned, but policy vs. practice needs a data-owner decision.** +**Resolved 2026-08-20 — source pinned and the data-owner has ruled.** Re-verified 2026-08-20 with the exact cBioPortal source pinned: study `brca_tcga_pan_can_atlas_2018`, -attribute `SUBTYPE` (PATIENT-level, values prefixed `BRCA_`), coverage **981/1,010 patients -(97.1%)**. Against this source, the committed (local/genefu) PAM50 calls match at **57.0%** +attribute `SUBTYPE` (PATIENT-level, values prefixed `BRCA_`), covering **981 of the 1,009 +patients carrying a manifest PAM50 call (97.2%)**. Against this source, the committed +(local/genefu) PAM50 calls match at **57.0%** (514/902 overlapping labeled patients) — confirms BIOP02-49's original finding, now with the comparison source's `study_id`/attribute fully citable. Mismatches concentrate in two known-hard boundaries, not random noise: local=LumB vs. cBioPortal=LumA (141 patients) and local=Normal vs. cBioPortal=LumA (101 patients) — consistent with the literature's documented LumA/LumB boundary instability and Normal-like call instability across PAM50 implementations, not evidence either -source is simply wrong. **The open question for the data-owner (kkkim):** §10 authorizes the -local/genefu fallback only when cBioPortal coverage is short, but cBioPortal coverage here is -97.1% — high, not short. Should the manifest switch to cBioPortal PAM50 as primary per the -letter of §10, or is there a documented reason (e.g. cBioPortal's curated calls trailing a TCGA -reprocessing batch) the local computation was used as primary in practice? Either answer is -fine, but the repo should say which and why before this is cited as "single source, version- -pinned" per `split_policy_v0.md` §7. Does not affect the split (§D.4), which is defined over the -full patient set independent of any single label's availability. Reproducible via +source is simply wrong. **Data-owner decision (kkkim, 2026-08-20):** the surfaced conflict was +that §10 authorized the local/genefu computation only as a fallback for short cBioPortal +coverage, yet coverage is 97.2% — high, not short — while the manifest used the computed calls +across the whole cohort. **The Parker-2009 computed calls stay as the source of record; the +manifest does not switch to cBioPortal.** Rationale: the Paper A/C analyses were already run and +verified against these labels (manifest agrees 1,009/1,009 with the committed source file), and +re-deriving them would be an unmotivated moving of the goalposts; the Parker centroid classifier +is the canonical PAM50 method and is directly citable. The 57.0% figure is therefore reported +here as a transparency item, not as an unresolved defect, and `split_policy_v0.md` §10 has been +corrected to name actual practice (see its §10.1). One non-blocking gap remains: the script and +input expression matrix that produced the computed calls are not in this repo, so the labels are +not yet end-to-end reproducible — follow-up per the provenance note. Does not affect the split +(§D.4), which is defined over the full patient set independent of any single label's +availability. Reproducible via `agents/data/scripts/pam50_source_reconcile.py`, output `agents/data/manifests/pam50_source_reconcile_biop02-74.json`. @@ -140,9 +148,16 @@ data version that produced it. *상태: 초안 v0.1. 모델/학습/평가 절(M.1–M.9)은 sjpark 초안([guide/paper_a_methods_modeling_draft.md](paper_a_methods_modeling_draft.md))과 상호 연결 — 특히 M.2(tiling/embedding), M.5(split 수치)가 이 문서를 "Data Methods"로 지칭하고 있어 정합 확인 완료. braveji가 M.7에서 지적한 mean-embed≠pixel-mean 용어 문제(-72 코멘트 11387 ①)는 이 문서 범위 밖(모델링 절 소관).* -*미해결 항목(투고 전 kkkim 결정 필요, 2026-08-20 갱신): PAM50 cBioPortal 대조 소스의 study_id는 -이제 고정됨(`brca_tcga_pan_can_atlas_2018`, `SUBTYPE` 속성, 커버리지 981/1010=97.2%). 남은 건 -study_id 미고정이 아니라 **정책(§10: cBioPortal 1순위·genefu는 커버리지 부족시 fallback) vs -실제 사용(전체 코호트가 genefu)의 불일치** — 커버리지가 97.2%로 "부족"이 아닌데 fallback이 -1순위처럼 쓰이고 있음. kkkim 결정 필요(§D.3 "Open item" 참조, 재현 -스크립트=`agents/data/scripts/pam50_source_reconcile.py`).* +*해소됨(2026-08-20 kkkim 결정, Jira 11999): PAM50 대조 소스의 study_id 고정 +(`brca_tcga_pan_can_atlas_2018`, `SUBTYPE` 속성, manifest PAM50 코호트 커버리지 981/1009=97.2%)에 이어, 그 과정에서 +드러난 **정책 vs 실사용 불일치**(§10은 cBioPortal 1순위·genefu는 커버리지 부족시 fallback이라 +했으나 커버리지가 97.2%로 "부족"이 아닌데 전 코호트가 계산본을 사용)도 결론이 났다. **결정: +Parker 2009 계산본(`tcga_brca_pam50_computed.csv`)을 정본으로 유지**하고 cBioPortal로 전환하지 +않는다 — 분석이 이미 이 라벨로 검증됐고(manifest 1009/1009 일치) Parker centroid는 PAM50 정본 +분류기이기 때문. 57.0% 불일치는 오류가 아니라 로컬 계산본 vs curated atlas의 파생 차이이며 위 +Methods 본문에 투명성 항목으로 보고했다. `split_policy_v0.md` §10 문구도 실사용에 맞게 정정 +(§10.1 신설). 재현 스크립트=`agents/data/scripts/pam50_source_reconcile.py`.* + +*잔여(비차단): 계산본을 생성한 스크립트와 입력 발현 행렬(study_id·버전)이 레포에 없어 완전 +재현은 아직 불가 — PROVENANCE "남은 gap"의 후속 과제이며 braveji가 `594ef6b`에서 비블로커로 +확인했다.*