Files
VesiscanClinicalAndroid/tools
dw.jang 60b630d3de docs: v7 (2026-07-10) 반영 — msp 제거, 6-stage alignment, mtb queue fix, labdb 자동 재시도
이번 세션 대량 변경 사항을 5개 문서에 반영. 각 문서마다 stale 이던
섹션을 갱신하거나 신규 섹션 추가.

USER_GUIDE.md
  - Sensor Alignment 를 V1 (3-stage) / V2 (6-stage) 로 재구성
  - V2 6-stage 표 + relaxed mode / soft hint 설명
  - GREEN 진입 5초 hold + 10-strike 리셋 완화 명시
  - "최적의 위치입니다!" 문구 반영

docs/BLE_PROTOCOL_REFERENCE.md
  - msp 명령 취소선 처리 + mim 신규 명령 문서화
  - Watchdog timeout 25초 연장 명시 (2.5)
  - §2.6 신규: firmware VBTFW0121 mls mode 0 freeze 취약점 +
    앱 측 3-layer 회피 (isMtbBusy / mtb 3초 timeout / 자동 재연결)

VesiScan_Android_Pipeline_Summary.md
  - v7 (2026-07-10) 섹션 신규 추가 — BLE / Alignment / UI / labdb /
    tools 5개 카테고리로 변경 사항 정리
  - 권장 펌웨어 표기 VBTFW0116 → VBTFW0120+ 로 갱신

labdb.md
  - §12b 신규: 앱 측 Auto Retry Policy — endMeasurement 자동 업로드
    조건 완화, LabdbAutoRetry object, UI 배너, 재시도 안전성

tools/README.md
  - labdb_upload.py 섹션 신규 — 사용법 / 폴더 구조 / 재실행 안전성 /
    buildPayload 로직 / 활용 예 정리

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-10 11:25:26 +09:00
..

tools/

VesiScan-Basic 측정 결과 분석 / 검증 툴.

analyze_csv.py — App CSV → Python pipeline 비교

App 이 측정 시 저장하는 CSV (Downloads/VesiScan_ADC/*.csv) 를 읽어, appshare 의 Python pipeline (for_app_share) 으로 BV 를 재계산하고 다음을 비교한다:

  • App-computed BV vs Python BV (per-scan, aggregate)
  • Method D wall detection rate
  • lr_ratio 분포
  • DPS / lr floor 등 알고리즘 변경 사항의 ablation

Setup

# 의존성
pip install numpy pandas matplotlib

# appshare repo 경로 (둘 중 하나)
export APPSHARE_DIR=/path/to/appshare/piezo-phantom-test
# 또는 명시: --appshare /path/...

Usage

# 기본 비교 (phantom 150 mL)
python tools/analyze_csv.py ~/Desktop/measure.csv --true 150

# Ablation — 5가지 알고리즘 config 비교 (어느 fix 가 임팩트 큰지)
python tools/analyze_csv.py measure.csv --true 150 --ablation

# 시각화 plot 저장
python tools/analyze_csv.py measure.csv --true 195 --plot ./out

# 특정 cycle 디테일 (per-channel walls + signals)
python tools/analyze_csv.py measure.csv --true 150 --cycle 42

출력 예시 (compare mode)

=== BV comparison ===
  APP (Kotlin): mean= 148.1± 4.2  trim10%= 148.5  bias=  -1.9 ( -1.3%)  CV= 2.9%  lr mean=1.154
       Python : mean=  92.7±13.4  trim10%=  91.1  bias= -57.3 (-38.2%)  CV=14.4%  lr mean=0.680

=== App ↔ Python diff ===
  mean= +55.03  std=15.83  range=[-45.3, +74.7]
  |diff| < 5 mL: 5/551 (0.9%)

Ablation Config 종류

코드 DPS lr_ratio 설명
A 1.936 =1.0 강제 OLD Kotlin equivalent (sim)
B 1.981 =1.0 강제 DPS fix 단독
C 1.981 Python 알고리즘 현재 b733d4f 결과
D 1.981 Python + floor 1.0 hybrid
E 1.936 Python 알고리즘 lr 단독 영향

CSV 포맷 (AdcCsvLogger 기준)

scan_id, timestamp, ..., volume_ml, lr_ratio, ..., channel, s0..s99

한 scan = 6 rows (CH0..CH5), 100 samples / row.

활용 예

  1. 임상 BV 검증: catheter 직후 측정 → --true <catheter_vol> 로 정확도 비교
  2. 알고리즘 변경 검증: 새 fix 후 같은 CSV 로 --ablation 돌려 회귀 여부 확인
  3. Device-to-device variance: 두 device 의 같은 phantom 측정 → CV 비교
  4. lr_ratio 패턴: human cohort 의 --plot 으로 lr 분포 시각화

labdb_upload.py — 세션 폴더 일괄 업로드

앱이 저장한 세션 폴더 (measurement_<name>.json 포함) 를 labdb REST API 로 일괄 업로드. 앱 안의 LabdbUploader.kt (buildPayload) 로직을 그대로 Python 으로 옮긴 것으로, 폰이 없는 상황에서 데스크톱에 백업한 데이터를 바로 서버로 넣을 때 사용.

Setup

# 별도 의존성 없음 (표준 라이브러리만 사용)
export LABDB_API_KEY=xbk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

apiKey 는 labdb admin 콘솔 또는 backend 담당자로부터 발급.

Usage

# 기본 — 폴더 안의 모든 세션 업로드
python tools/labdb_upload.py "C:/Users/장동우/Desktop/newdata"

# apiKey 를 명령줄로 전달
python tools/labdb_upload.py ./sessions --api-key xbk_live_xxx...

# dry-run — 전송하지 않고 payload 검증만
python tools/labdb_upload.py ./sessions --dry-run

# 이미 업로드된 폴더도 재전송 (labdb_upload.json 마커 무시)
python tools/labdb_upload.py ./sessions --force

# meta.data_type 없을 때 사용할 fallback (기본 "001")
python tools/labdb_upload.py ./sessions --data-type 002

폴더 구조 요구사항

각 세션 폴더는 앱이 만든 표준 형식:

<folder>/
  meta_<folder>.json
  measurement_<folder>.json   ← 이걸 payload 로 변환
  adc.csv
  imu.csv
  ble.log
  labdb_upload.json           ← 성공 시 생성 (sessionId, inserted 개수 등)
  labdb_upload_error.json     ← 실패 시 생성 (다음 실행 시 참고)

measurement.json 또는 measurement_<folder>.json 이 있으면 대상. 없으면 "measurement json not found" 로 실패.

재실행 안전성

  • 이미 업로드된 폴더 (labdb_upload.json 있음) 는 자동 skip
  • --force 로 강제 재전송 가능
  • 실패한 폴더는 다음 실행 시 자동 재시도

출력 예시

[OK  ] HUMAN-kai_VBT26040302_SITTING_ALIGN_0CM_2026-07-08_110903: uploaded: 130/130 (dup=0)
[OK  ] HUMAN-kai_VBT26040302_SITTING_ALIGN_1CM_2026-07-08_111049: uploaded: 3/3 (dup=0)
[FAIL] HUMAN-kai_VBT26050202_SITTING_ALIGN_2CM_2026-07-08_161928: upload fail: HTTP 401
[OK  ] ... (skip already uploaded)

summary: 19 uploaded, 0 skipped, 1 failed (total 20)

buildPayload 로직 (LabdbUploader.kt 와 동일)

  • testId: 폴더명 sanitize (^[A-Za-z0-9_-]{1,40}$). 40자 초과 시 앞 31자 + _ + 8자 SHA-1 prefix 로 축약 (uniqueness 유지).
  • dataType: meta.data_type 우선, 없으면 --data-type fallback.
  • records[]: measurement.json 의 각 cycle → labdb record 로 변환:
    • sensor.imu: 마지막 (가장 최근) IMU sample
    • sensor.imu_samples: 전체 시계열
    • channels[0..5]: peak / peakIdx / data 배열
    • alignment session 은 align_phase / align_score / align_hint 등 부가 필드.
  • params: posture / step / is_alignment / examiner / firmware / hardware / subject 등 meta 요약.

활용 예

  1. 개발용 백업 재전송: 폰이 없는 상황에서 데스크톱에 백업한 세션 폴더를 labdb 로 일괄 업로드.
  2. 자동 재시도 실패 복구: 앱의 LabdbAutoRetry 도 실패한 케이스 (예: apiKey 만료) → apiKey 갱신 후 스크립트로 일괄 재전송.
  3. 다른 폰 → labdb 이관: A 폰에서 측정 → Downloads/VesiScan_Sessions/ 폴더 → PC 로 복사 → 스크립트로 서버 반영.