Files
VesiscanClinicalAndroid/docs/ALGO_BRANCH_COMPARISON.md
dw.jang a89936c862 docs(algo): ALGO_BRANCH_COMPARISON §3-4 METHOD_D vs METHOD_D_PHANTOM 심층 비교
기존 §3 BV Estimation 은 브랜치 비교 관점만 · 두 method 자체를 나란히 놓고
상세 대조하는 섹션 없어서 §3-4 로 추가 (사용자 요청).

포함 (7 sub-section):
  3-4-1. 부피 공식 (Frustum+Cap vs 4/3πr³)
  3-4-2. 파이프라인 stage 비교 표 (11 stage · METHOD_D 만 있는 것 명시)
  3-4-3. 결과 특성 표 (정확도 · 계산 비용 · 재현성 · phantom vs 인체)
  3-4-4. 예시 계산 (phantom 300mL · 지름 83mm · 두 method 각각 산수)
  3-4-5. 언제 어느 method 써야 하나 (권장 매트릭스)
  3-4-6. 코드 진입점 요약 (dispatcher)
  3-4-7. 향후 개선 여지 (하이브리드 · ellipsoid 확장 등)

핵심 근거:
  · phantom 300mL 실측 → METHOD_D_PHANTOM 296mL (-1.3%) vs METHOD_D 250mL (-17%)
  · 원인: 큰 대칭 방광은 구 가정이 정확 · Frustum+cap 은 adaptive 로도 저추정
2026-08-13 14:42:35 +09:00

18 KiB
Raw Permalink Blame History

demo-final vs feature/cloud-mvp 알고리즘 브랜치 비교

마지막 업데이트: 2026-08-11 · 대상: Alignment · Detection · BV Estimation

배경

VesiScan-Basic Android 앱은 두 개의 활성 브랜치로 관리됨.

브랜치 용도 대상 방광 상태
demo-final 시연/데모 전용 · 안정판 phantom (구 모형 방광) 동결 시연
feature/cloud-mvp 실사용/개발 · 인체 임상 실제 인체 (타원 방광) 활성 개발

핵심 원칙: 두 브랜치 알고리즘 결과가 서로 다른 것이 정상 설계. phantom (구) 과 인체 (비대칭 타원) 은 기하가 근본 다르므로 · 같은 코드로 두 상황 모두 정확 계산 불가.

  • demo-final = 데모 시 팬텀에서 300ml 근처 값이 안정적으로 나오는 것이 목표. 구 공식 (V = 4/3πr³) 사용.
  • cloud-mvp = 인체 정확도 (Halir-Flusser + adaptive_large_bladder_relax + b_si_floor 등 Python parity).

또한 cloud-mvp 는 패키지 domain-driven 재배치를 완료: managers/* → piezo/* · alignment/* · common/util/*. 두 브랜치 동일 파일이 경로만 다르고 로직은 대부분 동일한 경우가 많음.


1. Alignment (정렬 · placement guide)

1-1. 기본 설정값

항목 demo-final feature/cloud-mvp
alignmentAlgo (default) V1 V1
placementGuideMode (default) SIMPLE (표시명 "Gradient") SIMPLE
V2 진입 조건 clinical alignment session 만 clinical alignment session 만
verticalHitRequired (V2) 3 3
VERTICAL_HIT_WINDOW / _MAJORITY 6 / 3 6 / 3
STABILIZE_LOST_WINDOW / _MAJORITY 4 / 3 4 / 3
V3 CenterAligner (2-Pass batch) ✅ 있음 ❌ 없음

1-2. 로직 차이

  • V1/V2 state machine 은 두 브랜치 100% 동일 (phase 진입 · hysteresis · CV 계산 · MOVE_UP/DOWN 방향 판정).
  • RollingAligner의 detectMultichannel 호출부:
    • demo-final: applyCross = false (piezophantomtest ea3f15c 이식 · 2026-07-06) → 정렬 위치 선택은 base 검출로만 수행 · 교차채널 보정이 nch 를 흔들지 못하게 격리 · BV 산출은 별도 경로에서 applyCross=true.
    • cloud-mvp: applyCross 파라미터 자체 제거 → 정렬 위치 판정에도 cross-channel 보정 결과 사용.
  • V3 CenterAligner (demo-final 전용): Pass 1 = 5 위치 각 20 cycle 스캔 → Rule A (ch3 필수 · 검출률 ≥ 80% · max nch · min bv_cv) 로 최적 위치 선택. Pass 2 = 재측정 검증. cloud-mvp 는 이 배치 알고리즘 자체가 없음.

1-3. 관련 파일

파일 demo-final cloud-mvp
PlacementGuideView ui/views/monitoring/PlacementGuideView.kt (2317 L) alignment/ui/PlacementGuideView.kt (2187 L)
AlignmentAdvisorV2 (+ RollingAligner) managers/AlignmentAdvisorV2.kt:677 (applyCross=false) alignment/AlignmentAdvisorV2.kt:680 (파라미터 제거)
AlignmentAdvisorV3 managers/AlignmentAdvisorV3.kt (신규) —
ImuAnalysis / ImuPostureClassifier managers/ alignment/

2. Detection (벽 검출)

2-1. 기본 설정값

항목 demo-final feature/cloud-mvp
detectionMethod (default) METHOD_C (V4.1 SphereFit walls) METHOD_D (Python for_app_share 1:1)
MethodDParams.otsuRatio 0.88 0.88
MethodDParams.oscfarWin 9 9
MethodDParams.promGamma / shoulderPromGamma 1.5 / 1.5 1.5 / 1.5
MethodDParams.minWallLumenRatio 1.16 1.16
MethodDParams.minPostRawRatio 1.08 1.08
MethodDParams.antDMax / dMax 18 / 10 18 / 10
Cross-channel stage 순서 ①→②→③ (3-stage) ①→①.5→②→③ (4-stage)
VDIP_POST_RECOVERY ❌ 없음 ✅ true (DIP_TOL=8.0mm · REACH_MARGIN=15.0mm)
NEIGHBOR_TOP_VALIDATE / INWARD_POST_SEARCH true / true true / true
applyCross 파라미터 ✅ 있음 (default true) ❌ 제거 (항상 적용)
topRecoverWallRatio 파라미터 ❌ 없음 ✅ 있음 (streaming relaxed pass 용)

2-2. 로직 차이

  • MethodDParams 는 모든 필드 100% 동일 (임계값 · 필터 파라미터 전부).

  • MethodDRunner 는 105 lines 차이 (443L vs 548L). 실질 로직 차이 3가지:

    1. applyVdipPostRecovery (cloud-mvp only · stage ①.5)
      • V-dip 심부후벽 복구. 중간 center 채널 후벽 z 가 양 이웃 모두보다 VDIP_DIP_TOL=8.0mm 얕고, 두 이웃이 서로 8.0mm 이내 일치 (=under-detected 심부후벽) 이면 consensus 깊이로 재탐색.
      • Gate (wall/lumen ratio + post_raw_ratio) 통과한 심부 peak 만 채택.
      • 원본: piezophantomtest c800f5d (2026-08-06).
    2. applyCross 파라미터
      • demo-final: detectMultichannel(..., applyCross: Boolean = true) 유지 → 정렬 / BV 경로 분리 가능.
      • cloud-mvp: 제거됨 → 두 경로 모두 cross-channel 적용된 결과 사용.
    3. topRecoverWallRatio 파라미터 (cloud-mvp only)
      • applyNeighborTopValidate Rule A (FN 복원) 재탐색 시 minWallLumenRatio gate override.
      • StreamingBladderEstimator relaxed pass (게이트 1.16 → 1.13) 용 hook.
  • detection default 가 다른 것 자체가 브랜치 성격의 표현: demo-final = phantom-검증된 V4.1 (안정 · 시연 유효), cloud-mvp = 임상용 METHOD_D (Python for_app_share 1:1).

2-3. 관련 파일

파일 demo-final cloud-mvp
MethodDRunner walldetect/MethodDRunner.kt (443 L) piezo/walldetect/MethodDRunner.kt (548 L)
MethodDParams walldetect/algo/methodd/MethodDParams.kt piezo/walldetect/algo/methodd/MethodDParams.kt (동일)
VDIP 신설 함수 — MethodDRunner.kt:214-306 (vdipDeepCandidate + applyVdipPostRecovery)

3. BV Estimation (부피 계산)

3-1. 기본 설정값

항목 demo-final feature/cloud-mvp
bvMethod (default) METHOD_D_PHANTOM (2026-08-11 신설 · 구 공식) METHOD_D (Halir + adaptive)
BvMethod enum {FRUSTUM, V41, METHOD_D, METHOD_D_PHANTOM} (4개) {FRUSTUM, V41, METHOD_D} (3개)
distancePerSample (dps) 1.968 mm/sample (2026-08-11 phantom rollback) 1.936 mm/sample (Python config_6ch.py:90)
lrRatioOverride (default) 1.0 1.0
lrRatioMin / lrRatioMax clip ❌ 없음 ✅ 0.5 / 1.5 (해부학적 clip)
estimateBv(walls, adaptive=true) 구현 ✅ 있음 (동일) ✅ 있음 (동일)
estimateBvPhantomSphere(walls) ✅ 있음 (신규 · 구 공식) ❌ 없음
Halíř–Flusser (EllipseFitSpecific) ✅ 있음 (로직 완전 동일) ✅ 있음
adaptive_large_bladder_relax (low_wide_endpoint) ✅ 있음 (동일) ✅ 있음
b_si_floor_ratio / _edge_min ✅ 있음 (동일) ✅ 있음
Subsample refined (Double ant/post) ✅ 있음 ✅ 있음
StreamingBladderEstimator ❌ 없음 ✅ 있음 (age-based strict/relaxed 병합)
useStreamingBv dev toggle ❌ 없음 ✅ 있음

3-2. 로직 차이

  • estimateBv(walls) 본체는 두 브랜치 100% 동일
    • evalOnce() → applyLumenInsetOne(0.15) → estimateBladderVolume6ch → Halíř–Flusser 타원 fit → 결과 검사 (capFrac < 0.20 && edge ≥ 0.48 && (edge ≥ 0.70 && hRel < 0.42)) → low_wide_endpoint 이면 urineInsetFrac=0.05 + bSiFloorRatio=0.85 로 재계산.
    • Python runners.estimate_bv 1:1.
  • estimateBvPhantomSphere(walls) — demo-final 전용 (2026-08-11 신설)
    • 위치: PiezoBVEstimator.kt:600
    • 로직: center CH0~3 각 채널의 (post − ant) × dps 를 지름으로 보고 평균 → V = 4/3·π·r³ (r = D/2). Halíř · adaptive · b_si_floor · lr_ratio 전부 우회.
    • 검증: D = 42 samples × 1.968 dps = 82.7 mm → r = 41.35 mm → V ≈ 296 ml (300 ml phantom 시연에서 재현 성공).
    • 인체 방광 (비대칭 타원) 에는 부적합 · phantom 전용.
  • distancePerSample 편차 (1.968 vs 1.936)
    • 두 브랜치 계산 결과가 다른 결정적 원인 중 하나.
    • dps 는 WdConfig.DPS_DEFAULT 도 함께 동기화 (V41 · Geometry · AnatomicalGate 모두 이 상수 사용) → 한 값만 바꾸면 두 경로 (6ch estimate vs V41/gate) dps 불일치 방지.
  • StreamingBladderEstimator (cloud-mvp only)
    • 파일: piezo/StreamingBladderEstimator.kt (신규).
    • 각 채널별 age (마지막 strict 검출 이후 trace 수) 유지 → strict 실패 채널을 최근 K trace 내 strict 이력 있으면 relaxed (게이트 1.13) 로만 복구 · 이력 없으면 완화 안 함 → 게이트 경계 flicker 억제.
    • MethodDRunner.detectMultichannel(topRecoverWallRatio=…) 로 게이트 override.
    • PiezoMonitoringView:406 에서 dev toggle 로 라우팅. 배뇨/탈착 시 reset().
  • lrRatioMin/Max clip [0.5, 1.5]
    • cloud-mvp 만 도입 (PiezoHW:164-165 · computeLrRatio 반환값 clip).
    • demo-final 은 computed lr 그대로 (실제로는 lrRatioOverride=1.0 강제 사용해서 clip 무의미).

3-3. 관련 파일

파일 demo-final cloud-mvp
PiezoBVEstimator managers/PiezoBVEstimator.kt (1174 L) piezo/PiezoBVEstimator.kt (1124 L)
EllipseFitSpecific managers/EllipseFitSpecific.kt piezo/EllipseFitSpecific.kt (package 다름)
GreenZoneConstants managers/GreenZoneConstants.kt:38, :59 common/util/GreenZoneConstants.kt:38, :69
BV 신설 함수 (sphere) PiezoBVEstimator.kt:600 estimateBvPhantomSphere —
Streaming BV — piezo/StreamingBladderEstimator.kt (신규)
BV 분기점 ui/views/monitoring/PiezoMonitoringView.kt:487-491 (METHOD_D_PHANTOM → estimateBvPhantomSphere) piezo/ui/PiezoMonitoringView.kt:406-418 (useStreamingBv → streamingBv.update(signals))

3-4. 심층 비교 · METHOD_D vs METHOD_D_PHANTOM

두 method 는 같은 detection walls 를 입력받지만 · 부피 계산 철학이 근본 다름.

3-4-1. 부피 공식

METHOD_D — 다각형 근사 + 타원 cap

BV = V_frustum + V_topCap + V_bottomCap
     ┌───────┬─────────┬──────────┐
     │ 6채널  │ Halir   │ Sphere   │
     │ frustum│ ellipse │ (fixed)  │
     │ 적분  │ fit    │          │
     └───────┴─────────┴──────────┘

방광을 6채널 벽 사이 다각형(frustum) + 상하 cap 으로 근사. adaptive_large_bladder_relax 로 큰 방광 처리 시 constraint 완화. Python runners.estimate_bv 1:1.

METHOD_D_PHANTOM — 순수 구

BV = (4/3) · π · r³
     r = mean(D_center 4채널) / 2
     D_ch = (post_ch - ant_ch) × dps

방광을 완전 대칭 구로 가정 · center CH0~CH3 지름 평균으로 반지름 산출. Cap · lr_ratio · Halir 다 우회.

3-4-2. 파이프라인 stage 비교

Stage METHOD_D METHOD_D_PHANTOM
1. walls 입력 List<WallWithSpan?> (subsample refined) List<WallWithSpan?> (동일)
2. lumen inset applyLumenInsetOne(0.15) — 벽 15% 안쪽 이동 ❌ 없음 (raw walls)
3. center wall repair gap 보간 · gap≥2 top drop ❌ 없음
4. lr_ratio lrRatioOverride ?: computeLrRatio() ❌ 없음 (구 = 1:1)
5. Frustum 계산 6채널 x-z 타원 · SI-sorted · frustum 적분 ❌ 없음
6. Top cap Halir-Flusser 타원 fit + ellipse_cap_height ❌ 없음
7. Bottom cap Sphere (bottomKind = "sphere") ❌ 없음 (전체가 구)
8. adaptive relax low_wide_endpoint 검사 → 재계산 ❌ 없음
9. b_si_floor 하한 b_si ≥ 0.85 × edge_min ❌ 없음
10. Post outlier post_outlier_filter=false (default) ❌ 없음
11. 최종 Σ frustum + top cap + bottom cap 4/3 π (D̄/2)³

3-4-3. 결과 특성

특성 METHOD_D METHOD_D_PHANTOM
정확도 (실제 방광) 높음 (Python parity · Δ~0mL 검증) 낮음 (구 가정)
정확도 (phantom 300mL) 250mL (adaptive 로도 -17%) 296mL (-1.3%) ✓
CH3 flick 민감도 낮음 (frustum 은 채널 몇 개 빠져도 ok) 높음 (평균에 직접 반영)
비대칭 방광 잘 대응 (frustum + LR ratio) 왜곡 심함 (구 가정)
작은 방광 (<100mL) 정확 정확 (구 가정 잘 맞음)
큰 방광 (>400mL) 정확 저추정 (구 부피 성장률 < 실제)
계산 비용 높음 (타원 fit · SVD · relax 재계산) 매우 낮음 (곱셈 몇 번)
결과 재현성 파이썬 소수점까지 일치 trivial · dps · walls 만 의존

3-4-4. 예시 계산 (phantom 300mL · 지름 83mm)

Method D walls 예시:

CH0: ant=15, post=57 → span 42
CH1: ant=13, post=59 → span 46
CH2: ant=14, post=57 → span 43
CH3: ant=16, post=55 → span 39
CH4/5: ant=18, post=44 (LR wings)

METHOD_D_PHANTOM 계산:

D̄ = mean(42, 46, 43, 39) × 1.968 = 42.5 × 1.968 = 83.64 mm
r  = 41.82 mm
V  = 4/3 · π · 41.82³ = 306,326 mm³ ≈ 306 mL ✓

METHOD_D 계산 (근사):

V_frustum = Σ frustum(z_i, z_{i+1}, S_i, S_{i+1})   (4채널 → 3 slice)
          ≈ 165 mL (본체)
V_top    (Halir + adaptive) ≈ 55 mL   (배꼽쪽 cap · b_si_floor 로 확장)
V_bottom (sphere)          ≈ 30 mL   (치골쪽 cap)
V_total  ≈ 250 mL   (-17% 저추정 · adaptive 로도 큰 phantom 처리 어려움)

3-4-5. 언제 어느 것 써야 하나

시나리오 권장 method 근거
Phantom 시연 (구·타원 방광 모형) METHOD_D_PHANTOM 구 가정 정확 · 300mL 재현
인체 실측 (임상) METHOD_D 비대칭 방광 · Halir + adaptive 필수
Alignment 위치 판정 detection method 만 사용 (BV 무관) walls 만 필요
BV parity 테스트 (Python 대조) METHOD_D bit-perfect 일치
CH3 검출 불안정 자세 METHOD_D frustum 이 채널 결손 관용
빠른 UI 반응 (계산 지연 최소) METHOD_D_PHANTOM O(1) 계산

3-4-6. 코드 진입점 요약 (demo-final)

// PiezoMonitoringView.kt:487-491
val bvResult = if (bvMethod == BvMethod.METHOD_D_PHANTOM) {
    estimateBvPhantomSphere(walls)   // PiezoBVEstimator.kt:600 · ~30 L
} else {
    estimateBv(walls)                 // PiezoBVEstimator.kt:595 · ~600 L
}
  • estimateBvPhantomSphere — 30 lines · 순수 계산 · state 없음
  • estimateBv — 600 lines + EllipseFitSpecific.kt (150 L) + adaptive wrapper

3-4-7. 향후 개선 여지 (선택)

  • 하이브리드 method: walls 대칭성 분산 계산 → 낮으면 PHANTOM · 높으면 METHOD_D 자동 선택
  • METHOD_D_PHANTOM 확장: 반지름 산출 시 CH1/CH2 만 사용 (CH0/CH3 는 flick 심함) 옵션
  • METHOD_D_PHANTOM_ELLIPSOID: 구 대신 반지름 2개 (SI + AP) 로 회전 타원체 · 근사 개선

4. 브랜치 전용 파일/기능 요약

demo-final only

  • managers/AlignmentAdvisorV3.kt (CenterAligner · Rule A + bvcv batch scan-select)
  • BvMethod.METHOD_D_PHANTOM enum value
  • fun estimateBvPhantomSphere(walls) (구 공식 · phantom 시연 전용)
  • MethodDRunner.detectMultichannel(..., applyCross = false) API 보존

cloud-mvp only

  • piezo/StreamingBladderEstimator.kt (age-based strict/relaxed 병합)
  • GreenZoneConstants.useStreamingBv dev toggle + custom-setter audit logging
  • PiezoHW.lrRatioMin / lrRatioMax clip + coerceIn in computeLrRatio
  • MethodDRunner.applyVdipPostRecovery + vdipDeepCandidate (V-dip 심부후벽 복구)
  • MethodDRunner.detectMultichannel(..., topRecoverWallRatio: Double?) API
  • PiezoHW.autoDetectPreset PhiRedactor 마스킹 (cybersecurity DC-02)
  • Custom-setter audit-logger wrappers on _detectionMethod / _bvMethod / _lrRatioOverride / _placementGuideMode / _alignmentAlgo / _useStreamingBv (cybersecurity UC-04)
  • piezo/ui/PiezoPersonalizationView.kt streaming BV dev toggle UI

공통 (구현 동일 · 위치만 다름)

  • Halíř–Flusser EllipseFitSpecific · estimateBv(walls) 본체 · adaptive_large_bladder_relax · b_si_floor · subsample refined · MethodDParams 전 필드 · V1/V2 alignment state machine 임계

5. 브랜치 default 조합 종합

축 demo-final cloud-mvp
정렬 V1 · Gradient (SIMPLE) V1 · Gradient (SIMPLE)
검출 METHOD_C (V4.1 SphereFit walls) METHOD_D (Python for_app_share)
BV METHOD_D_PHANTOM (구 공식 · V=4/3πr³) METHOD_D (Halir + adaptive)
dps 1.968 mm/sample 1.936 mm/sample
Streaming BV — dev toggle
Audit logging — 활성

6. 브랜치별 의사결정 기록 (핵심 커밋)

커밋 날짜 브랜치 변경
bcbc7b4 2026-07-02 demo-final 패키지 통일 (com.example → com.medithings) · BV 로직 안정판
d732150 2026-07-20 demo-final Halíř-Flusser ellipse fit 이식 (BV Δ 43→13mL)
3152783 2026-07-20 demo-final estimateBv wrapper + adaptive_large_bladder_relax + b_si_floor
430d9ad 2026-07-30 demo-final feature-folder refactor (147 파일 이동)
1c3748b 2026-08-07 demo-final vdip_post_recovery 이식 (MethodDRunner)
8cab1d0 2026-08-10 demo-final rollback 후 재조정 · detection=C + bv=METHOD_D
d054b3b 2026-08-11 demo-final dps 1.936 → 1.968 (phantom 스케일 재현)
d1d17f8 2026-08-11 demo-final METHOD_D_PHANTOM (구 공식) 신설 · demo default
6dfe5e6 2026-08-11 demo-final BleManager.disconnect() 즉시 UI 반영 fix

7. 향후 유지 원칙

  1. cloud-mvp 의 알고리즘 개선을 demo-final 로 무분별 이식하지 않기
    • Halir · adaptive 등은 인체 정확도 개선이지만 phantom 에서는 오히려 값 왜곡.
  2. demo-final 은 phantom 시연 재현성 최우선
    • 알고리즘 변경 시 300 ml phantom 결과가 296 ml 근처를 유지하는지 확인.
  3. 동시 이식이 필요한 fix (예: BLE 안정성 · UI 버그) 는 두 브랜치 각각 별도 커밋
    • cherry-pick 대신 각 브랜치에서 명시적으로 적용 후 커밋 메시지에 "demo-final 이식" / "cloud-mvp 이식" 명시.