feat(align): nch=4 위치가 3곳 이상이면 cap_frac 최소 대신 가운데를 고른다 — 방광 끝 위치 선택으로 BV 과소 추정

알고리즘 팀(2026-10-07): nch=4 인 위치가 여럿이라는 것은 방광이 빔 커버 범위보다 크다는
뜻이다. 그때 cap_frac 최소 규칙은 외삽을 최소화하는 자리를 찾으려 하지만, 방광 끝에 가까운
위치일수록 cap_frac 이 오히려 작게 계산된다 — 한쪽 cap 은 끝 채널이 방광을 스쳐 작아지고,
반대쪽 cap 은 높이 상한에 걸려 그만큼 커지지 못한다. 그 결과 끝 위치가 뽑히고 BV 가 과소
추정됐다.

규칙 ①′: 후보(ch3 게이트 통과) 중 nch=4 가 3곳 이상이면 cm 순 가운데, 짝수면 가운데 둘 중
아래쪽(치골 쪽, 작은 cm). 2곳까지는 종전 규칙(nch 최대 → cap_frac 최소 → 낮은 cm) 그대로.

이 가지는 Python select_supine_anchor 에 아직 없다. 레퍼런스 케이스 200개에는 이 가지를 타는
케이스가 없어(확인) 대조가 그대로 유효하고, 패리티 시험이 그 가정을 검사한다. 새 가지는
AnchorSelectionCenterRuleTest 7건이 잠근다. 어느 가지로 골랐는지 AnchorDecision.rule 로
돌려주고, 요약·labdb 601 params 에 select_rule 로 남긴다 — nch4_center 세션은
selection_verified_against_reference=false. 정렬 완료 안내 문구에도 "채널 4/4 위치 N곳 —
가운데" 를 덧붙인다(화면은 종전대로 "치골 위 N cm" 만 보여 준다).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 16:49:02 +09:00
parent a6b19b3dcc
commit 1592a1454e
6 changed files with 160 additions and 8 deletions
+2 -1
View File
@@ -190,12 +190,13 @@ IMU 는 2026-09-21 이후 업로드분부터 `sensor.imu` 로 들어옵니다(
| `ch3_hit_min` | number | CH3 검출률 하한 (0.8) |
| `final_offset_cm` | int | best 에 더하는 오프셋 — **0** (2026-10-01~), 그 전 세션은 1 |
| `best_cm` | int / null | 알고리즘이 고른 최적 위치 |
| `select_rule` | string | 어느 가지로 골랐나 (2026-10-07~): `max_nch_min_cap` 종전 3단 규칙 · `nch4_center` nch=4 후보 3곳 이상 → 가운데 · `none` 후보 없음 |
| `anchor_cm` | int / null | 실제 부착 위치 = `best_cm + final_offset_cm` (2026-10-01~ 는 best 그 자리) |
| `action` | string | `STOP` / `REATTACH` / … |
| `stop_reason` | string / null | 탐색 종료 사유 |
| `max_nch` | int | 관측된 최대 검출 채널 수 |
| `patient_unnamed` | bool | 환자명 없이 잰 데이터인가(폴더가 `unnamed_*`) |
| `selection_verified_against_reference` | bool | 앱 판정이 Python 레퍼런스와 대조 완료인가 |
| `selection_verified_against_reference` | bool | 앱 판정이 Python 레퍼런스와 대조 완료인가 — `nch4_center` 가지는 Python 에 아직 없어 **false** |
| `positions` | array | 위치별 지표 — 아래 |
| `lateral` | object | 좌우 정렬 결과 — 아래 |
| `anchor_basis` | string / null | 이 위치로 임상을 진행한 근거. 600 의 같은 필드와 같은 값입니다. **null = 정렬만 하고 임상으로 넘어가지 않음** |