From f391f404b4d9c203b7ba92a91728ce53e655f459 Mon Sep 17 00:00:00 2001 From: jjangddu Date: Fri, 24 Apr 2026 16:50:31 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20Settings=EC=97=90=20Low=20Echo=20Thresh?= =?UTF-8?q?old=20+=20Distance/Sample=20=EC=8A=AC=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=8D=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Low Echo Threshold: 800~2000 슬라이더 (기본 1150, 주황색) → GreenZoneConstants.lowEchoAmp 런타임 변경 → CH4/CH5 threshold 조절로 lateral 감지 개선 2. Distance/Sample: 1.5~2.5mm 슬라이더 (기본 1.771, 초록색) → PiezoHW.distancePerSample 런타임 변경 → 기기별 캘리브레이션 가능 3. 도넛차트 ml 실시간 표시: estimatedVolume → lastVolumeMl 직접 표시 → 측정 즉시 정확한 ml 반영 (기존: 레벨 변환 후 재계산으로 지연) Co-Authored-By: Claude Opus 4.6 (1M context) --- .../managers/GreenZoneConstants.kt | 2 +- .../managers/PiezoBVEstimator.kt | 4 +- .../views/monitoring/PiezoMonitoringView.kt | 48 +++++++++++++++++-- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/example/medilightv2android/managers/GreenZoneConstants.kt b/app/src/main/java/com/example/medilightv2android/managers/GreenZoneConstants.kt index f18a003..5cc8e1a 100644 --- a/app/src/main/java/com/example/medilightv2android/managers/GreenZoneConstants.kt +++ b/app/src/main/java/com/example/medilightv2android/managers/GreenZoneConstants.kt @@ -38,7 +38,7 @@ object GreenZoneConstants { * UrinAI의 liquidThrLoose(raw 기준)와 다름 — 여기는 TVD+SG 적용 후 신호 기준. * Python 원본: 1150 (low_echo_detection_method_b.py LOW_ECHO_AMP, 6ch 버전) * 영향: PiezoEchoAnalyzer → low-echo span 탐지, 벽 찾기의 기반 */ - const val lowEchoAmp: Float = 1150f + var lowEchoAmp: Float = 1150f /** 구조 이진화 임계값: raw < 이 값 → 액체(liquid), ≥ → 조직(tissue). * 낮출수록 엄격 (더 확실한 액체만 인정), 높일수록 관대. diff --git a/app/src/main/java/com/example/medilightv2android/managers/PiezoBVEstimator.kt b/app/src/main/java/com/example/medilightv2android/managers/PiezoBVEstimator.kt index 635ea73..ee7ea5a 100644 --- a/app/src/main/java/com/example/medilightv2android/managers/PiezoBVEstimator.kt +++ b/app/src/main/java/com/example/medilightv2android/managers/PiezoBVEstimator.kt @@ -90,8 +90,8 @@ object PiezoHW { val degree: DoubleArray get() = centerCh.map { degreeAll[it] }.toDoubleArray() val degreeLR: DoubleArray get() = centerCh.map { degreeLRAll[it] }.toDoubleArray() - /** Acoustic calibration */ - const val distancePerSample: Double = 1.771 // mm/sample + /** Acoustic calibration (런타임 조절 가능) */ + var distancePerSample: Double = 1.771 // mm/sample const val delayOffsetMm: Double = 6.85 /** Volume model */ diff --git a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt index bfd84eb..75ee193 100644 --- a/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt +++ b/app/src/main/java/com/example/medilightv2android/ui/views/monitoring/PiezoMonitoringView.kt @@ -42,6 +42,8 @@ import com.example.medilightv2android.ble.BleManager import com.example.medilightv2android.ble.PiezoChannelData import com.example.medilightv2android.managers.PiezoEchoAnalyzer import com.example.medilightv2android.managers.PiezoConstants +import com.example.medilightv2android.managers.GreenZoneConstants +import com.example.medilightv2android.managers.PiezoHW import com.example.medilightv2android.managers.estimateBladderVolume6ch import com.example.medilightv2android.models.BladderLevel import com.example.medilightv2android.models.UrgencyLevel @@ -624,7 +626,8 @@ fun PiezoMonitoringView(appState: AppState) { colors = CardDefaults.cardColors(containerColor = MlCardBackground), modifier = Modifier.shadow(8.dp, RoundedCornerShape(16.dp), spotColor = Color.Black.copy(alpha = 0.06f)) ) { - Column(modifier = Modifier.padding(20.dp)) { + Column(modifier = Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { + // Catheterization Threshold Row(verticalAlignment = Alignment.CenterVertically) { Text("Catheterization Threshold", fontSize = 14.sp, fontWeight = FontWeight.SemiBold) Spacer(modifier = Modifier.weight(1f)) @@ -637,8 +640,47 @@ fun PiezoMonitoringView(appState: AppState) { steps = 8, colors = SliderDefaults.colors(thumbColor = MlPrimary, activeTrackColor = MlPrimary) ) + HorizontalDivider() - Spacer(modifier = Modifier.height(8.dp)) + + // Low Echo Threshold + var currentThreshold by remember { mutableStateOf(GreenZoneConstants.lowEchoAmp) } + Row(verticalAlignment = Alignment.CenterVertically) { + Text("Low Echo Threshold", fontSize = 14.sp, fontWeight = FontWeight.SemiBold) + Spacer(modifier = Modifier.weight(1f)) + Text("${"%.0f".format(currentThreshold)}", fontSize = 14.sp, fontWeight = FontWeight.Bold, color = Color(0xFFFF9500)) + } + Slider( + value = currentThreshold, + onValueChange = { + currentThreshold = it + GreenZoneConstants.lowEchoAmp = it + }, + valueRange = 800f..2000f, + colors = SliderDefaults.colors(thumbColor = Color(0xFFFF9500), activeTrackColor = Color(0xFFFF9500)) + ) + + HorizontalDivider() + + // Distance Per Sample + var currentDps by remember { mutableStateOf(PiezoHW.distancePerSample.toFloat()) } + Row(verticalAlignment = Alignment.CenterVertically) { + Text("Distance/Sample", fontSize = 14.sp, fontWeight = FontWeight.SemiBold) + Spacer(modifier = Modifier.weight(1f)) + Text("${"%.3f".format(currentDps)} mm", fontSize = 14.sp, fontWeight = FontWeight.Bold, color = Color(0xFF4CAF50)) + } + Slider( + value = currentDps, + onValueChange = { + currentDps = it + PiezoHW.distancePerSample = it.toDouble() + }, + valueRange = 1.5f..2.5f, + colors = SliderDefaults.colors(thumbColor = Color(0xFF4CAF50), activeTrackColor = Color(0xFF4CAF50)) + ) + + HorizontalDivider() + Row { Text("Max Volume", fontSize = 14.sp, fontWeight = FontWeight.SemiBold) Spacer(modifier = Modifier.weight(1f)) @@ -673,7 +715,7 @@ fun PiezoMonitoringView(appState: AppState) { BladdyRiveView(urgency = urgency, size = if (isCompact) 70.dp else 100.dp) Spacer(modifier = Modifier.height(4.dp)) Text( - "${appState.estimatedVolume} ml", + if (lastVolumeMl > 0) "${"%.0f".format(lastVolumeMl)} ml" else "${appState.estimatedVolume} ml", fontSize = 16.sp, fontWeight = FontWeight.Bold, color = urgency.accentColor,