Files
VesiscanClinicalAndroid/docs/ALGO_BRANCH_COMPARISON.md
T
dw.jang e414a41a6d docs(algo): ALGO-04 demo-final vs feature/cloud-mvp 브랜치 비교 문서
3축 (Alignment / Detection / BV) 로직 상세 비교.

핵심 정리:
  · demo-final = phantom (구) 시연 전용 · V=4/3πr³ · dps=1.968 · METHOD_D_PHANTOM
  · cloud-mvp   = 인체 (타원) 실사용 · Halir+adaptive · dps=1.936 · METHOD_D
  · 두 브랜치 값이 다른 것이 정상 설계 (기하가 다름).

각 축별 default 표 · 로직 diff 요약 · 관련 파일 경로 (line 번호 포함).
브랜치 전용 파일 (demo: AlignmentAdvisorV3 · estimateBvPhantomSphere ·
cloud: StreamingBladderEstimator · VDIP post recovery · audit-logger).
향후 유지 원칙 (무분별 이식 금지 · phantom 재현성 우선).

Docmost 업로드: https://docmost.medithings.net/s/vesiscan/p/IZyb46bKVH
2026-08-11 16:42:12 +09:00

215 lines
13 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.
# 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)`) |
---
## 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 이식" 명시.