doc: decode signals planning
This commit is contained in:
68
doc/plan/signals.md
Normal file
68
doc/plan/signals.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Plan: Decode wmedf signal data, expose via CLI and JSON export
|
||||
|
||||
## Context
|
||||
|
||||
The .wmedf parser currently extracts only the session start timestamp. The binary signal data (18 channels of continuous waveforms — pressure, respiratory flow, SpO2, heart rate, etc.) is ignored. This data is clinically critical: it enables visual confirmation of apnea types, desaturation tracking, and cardiac correlation.
|
||||
|
||||
## Binary format summary
|
||||
|
||||
- Standard EDF, 18 channels, 4864-byte header (256 global + 18×256 signal)
|
||||
- Signal headers use EDF interleaved layout (all labels, then all transducers, etc.)
|
||||
- Data records: 70 bytes each (35 × i16 LE), 18 seconds per record
|
||||
- Samples per record varies by channel: Pressure(5), RespFlow(10), SPRstatus(5), all others(1) = 35 total
|
||||
- Num records: derive from `(file_size - 4864) / 70` (header field unreliable)
|
||||
- Conversion: `physical = phys_min + (raw - dig_min) * (phys_max - phys_min) / (dig_max - dig_min)`
|
||||
|
||||
## Files to modify
|
||||
|
||||
- `crates/tidal-core/src/entities.rs` — move `sample_rate_hz` to `SignalChannel`, add new `SignalLabel` variants
|
||||
- `crates/tidal-devices/src/lowenstein/wmedf.rs` — full signal header + data record decoding
|
||||
- `crates/tidal-store/src/sqlite.rs` — use per-channel sample rate in read/write paths
|
||||
- `crates/tidal-cli/src/main.rs` — add `--signals` flag to `session` command
|
||||
- `crates/tidal-cli/src/export.rs` — add signal summaries to JSON export
|
||||
|
||||
## Step 1: Update entities
|
||||
|
||||
Move `sample_rate_hz` from `SignalBlock` to `SignalChannel`. Add `SignalLabel` variants: `EEPAPTarget`, `TotalLeakage`, `RSBI`, `AMV`, `SPRStatus`. Update `Display`/`FromStr`.
|
||||
|
||||
## Step 2: Update tidal-store for per-channel sample rate
|
||||
|
||||
- Write path: use `ch.sample_rate_hz` instead of `block.sample_rate_hz`
|
||||
- Read path: store rate into each `SignalChannel`, construct `SignalBlock { channels }` without block-level rate
|
||||
- Update tests
|
||||
|
||||
## Step 3: Implement wmedf signal decoder
|
||||
|
||||
In `wmedf.rs`:
|
||||
|
||||
1. Parse signal headers from the interleaved EDF layout (labels at 256, units at 1984, phys min/max, dig min/max, samples_per_record at 4144)
|
||||
2. Map EDF label strings to `SignalLabel` variants (e.g. "EEPAPsoll" → `EEPAPTarget`, "HeartFrequency" → `HeartRate`)
|
||||
3. Parse data records: iterate 70-byte chunks, read i16 LE values, distribute across channels by samples_per_record
|
||||
4. Convert digital → physical values per the EDF formula
|
||||
5. Compute per-channel sample_rate_hz: `samples_per_record / 18.0` (record duration)
|
||||
6. Build `SignalBlock` with populated `SignalChannel` entries
|
||||
|
||||
## Step 4: Add `--signals` to CLI session command
|
||||
|
||||
When `--signals` is set, load session with signals and display summary table:
|
||||
```
|
||||
Signals 18 channels
|
||||
Label Unit Samples Rate(Hz) Min Max Mean
|
||||
Pressure hPa 3630 0.278 6.0 12.3 8.4
|
||||
RespiratoryFlow l/min 7260 0.556 -42.0 55.3 1.2
|
||||
SpO2 % 726 0.056 88.0 97.0 93.2
|
||||
...
|
||||
```
|
||||
|
||||
## Step 5: Add signal summaries to JSON export
|
||||
|
||||
Add `--signals` flag to export command. When set, load sessions with signals and include per-channel summary (label, unit, sample_rate_hz, sample_count, min, max, mean) in JSON output. Raw samples excluded from JSON — too large.
|
||||
|
||||
## Verification
|
||||
|
||||
1. `cargo build` — no errors or warnings
|
||||
2. `cargo test` — all tests pass (including updated signal_blob_round_trip test)
|
||||
3. `rm ~/.local/share/tidal/tidal.db && tidal import ~/lowenstein/therapy_extracted --from 2026-03-26 --to 2026-03-28` — imports with signals
|
||||
4. `tidal session 300306-003344 --signals` — shows 18 channels with plausible values
|
||||
5. `tidal export --format json --from 2026-03-26 --to 2026-03-28 --signals` — JSON includes signal summaries
|
||||
6. Verify: Pressure values in hPa range (4-20), SpO2 in % range (80-100), HeartRate in bpm range (40-120)
|
||||
Reference in New Issue
Block a user