8eee3550f3
요약은 같은 cm 의 마지막 시도만 남겨(재측정은 최신값) 첫 측정 때 본 CH3 가 몇 trace 였는지 알 수 없다. LABDB_CYCLES_DIR 의 cycle CSV(scratch 스크립트가 labdb 601 JSON 에서 뽑는다)를 AnchorGuide.measure 에 넣어 파일마다 nch · ch3Mean · hit/traces · cap_frac 을 찍는다. 환경변수가 없으면 건너뛴다 — CI 와 무관. 2026-10-14 P9 sitting "1·2cm 에서 ch2·ch3" 질의에 처음 썼다. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
55 lines
2.7 KiB
Kotlin
55 lines
2.7 KiB
Kotlin
package com.medithings.vesiscan.managers
|
|
|
|
import org.junit.Assume.assumeTrue
|
|
import org.junit.Test
|
|
import java.io.File
|
|
|
|
/**
|
|
* 진단용 — labdb 601 원시 파형을 앱과 **똑같은 판정**([AnchorGuide.measure])에 다시 넣어
|
|
* 시도별 nch · CH3 · 검출 trace 수를 찍는다. 요약(`positions`)은 같은 cm 의 **마지막 시도**만
|
|
* 남기므로(재측정은 최신값), 첫 측정 때 화면에서 본 CH3 가 실제로 몇 trace 였는지는 이걸로만
|
|
* 알 수 있다(2026-10-14, P9 sitting "1·2cm 에서 ch2·ch3 보였다" 질의).
|
|
*
|
|
* 입력: 환경변수 `LABDB_CYCLES_DIR` 의 `*.csv` (cycle,channel,s0.. · 헤더 없음 —
|
|
* scratchpad/labdb_export_cycles.py 가 만든다). 파일명 `…__{cm}cm_{phase}_a{attempt}.csv`.
|
|
* HW 프리셋은 `LABDB_HW_PRESET`(기본 R300). 환경변수가 없으면 건너뛴다 — CI 와 무관하다.
|
|
*/
|
|
class LabdbTraceDumpTest {
|
|
|
|
private fun loadCycles(f: File): List<List<DoubleArray>> {
|
|
val byCycle = sortedMapOf<Int, MutableMap<Int, DoubleArray>>()
|
|
f.readLines().filter { it.isNotBlank() }.forEach { line ->
|
|
val p = line.split(',')
|
|
byCycle.getOrPut(p[0].toInt()) { sortedMapOf() }[p[1].toInt()] =
|
|
DoubleArray(p.size - 2) { p[it + 2].toDouble() }
|
|
}
|
|
return byCycle.values.map { chans -> chans.toSortedMap().values.toList() }
|
|
}
|
|
|
|
@Test
|
|
fun dumpPerAttemptTraces() {
|
|
val dir = System.getenv("LABDB_CYCLES_DIR")?.let(::File)
|
|
assumeTrue("LABDB_CYCLES_DIR 없음 — 진단 전용", dir != null && dir.isDirectory)
|
|
val presetName = System.getenv("LABDB_HW_PRESET") ?: "R300"
|
|
val saved = PiezoHW.activePreset
|
|
PiezoHW.activePreset = PiezoHW.DevicePreset.valueOf(presetName)
|
|
try {
|
|
val re = Regex("""__(-?\d+)cm_([a-z_]+)_a(\d+)\.csv$""")
|
|
println("TRACEDUMP preset=$presetName")
|
|
println("TRACEDUMP file | cycles | traces | nch | ch3Mean | ch3Hit/traces | ch3Rate | capFrac | nchTraceMean")
|
|
dir!!.listFiles { f -> f.name.endsWith(".csv") }!!.sortedBy { it.name }.forEach { f ->
|
|
val m = re.find(f.name) ?: return@forEach
|
|
val cm = m.groupValues[1].toInt()
|
|
val cycles = loadCycles(f)
|
|
val rec = AnchorGuide().measure(cycles, cm)
|
|
println(
|
|
"TRACEDUMP ${f.name} | ${cycles.size} | ${rec.nTrace} | ${rec.nch} | ${if (rec.ch3Mean) "O" else "X"} | " +
|
|
"${rec.ch3Hit}/${rec.nTrace} | ${"%.2f".format(rec.ch3Rate)} | ${"%.3f".format(rec.capFrac)} | ${"%.2f".format(rec.nchTrace)}",
|
|
)
|
|
}
|
|
} finally {
|
|
PiezoHW.activePreset = saved
|
|
}
|
|
}
|
|
}
|