Skip to content

Make waveform beat detection and motion QC robust#30

Draft
sslnevefocusrite wants to merge 1 commit into
DigitalHolography:mainfrom
sslnevefocusrite:agent/robust-waveform-detection
Draft

Make waveform beat detection and motion QC robust#30
sslnevefocusrite wants to merge 1 commit into
DigitalHolography:mainfrom
sslnevefocusrite:agent/robust-waveform-detection

Conversation

@sslnevefocusrite

Copy link
Copy Markdown

Summary

  • preserve the historical high-confidence systolic detector as pass 1, then conservatively recover one supported upstroke only inside an approximately two-period gap
  • refresh waveform detection even when a precomputed DopplerView analysis is present
  • validate candidate intervals jointly across artery and vein using period ratio, raw-to-band-limited residual, and paired template consistency
  • re-extract accepted global and segment waveforms from the original signal so rejected long intervals cannot affect interpolation length
  • keep all existing waveform formulas unchanged while feeding heart rate, velocity summaries, and waveform-shape metrics the same accepted-beat population
  • add auditable QualityControl/Beat outputs, configurable thresholds, documentation, and a generic local benchmark command

Why

A missed systolic boundary currently merges two cycles into one long beat. Motion spikes or dips can also become the apparent maximum, minimum, or derivative extremum. Both errors propagate beyond heart rate into RI, PI, timing, width, slope, cumulative, spectral, and whole-shape endpoints.

The recovery pass is deliberately local: it does not lower the detector threshold over the whole trace. A candidate must be close to the expected midpoint and pass independent height and prominence gates. Recovered boundaries remain explicitly flagged.

Beat QC produces one shared mask for artery and vein. Rejected intervals are then extracted again rather than sliced from an already-interpolated tensor; this prevents an unresolved double beat from setting n_fft for all accepted beats. The analysis namespace retains candidate segmentation for diagnosis, while final Artery/VelocityPerBeat, Vein/VelocityPerBeat, and beat-period datasets contain accepted beats only.

Validation

  • python -m unittest discover -s test -v: 74 tests pass
  • Ruff passes on every changed Python file
  • synthetic coverage includes clean invariance, attenuated-beat recovery, true-pause and weak-midpoint safety, irregular rhythm, affine scaling, spike/dip rejection, broad paired deformation, one-vessel paired rejection, non-contiguous interval extraction, segment alignment, all-rejected failure, and the rejected-long-interval n_fft regression
  • recovered segmentation matches oracle segmentation for every current scalar waveform endpoint in both vessels and both raw/band-limited modes
  • generalized local regression: three supported missed boundaries recovered, four artifact beats rejected, and four clean controls remained exact no-ops across 156 artery/vein × raw/band-limited scalar summaries
  • 100 seeded stress runs: 100/100 attenuated beats recovered within two samples, 0/100 false recoveries across true pauses, 0/100 clean QC false-positive runs, and 0/100 injected artifact misses

Local regression data and case-specific identifiers are not included in this branch. The tracked benchmark tool accepts an external fixture directory and optional external expectation manifest.

Run locally

python -m venv .venv
.\.venv\Scripts\activate
pip install -e .
python -m unittest discover -s test -v
python tools\benchmark_waveform_robustness.py C:\path\to\local\fixtures

Deliberate limits

  • recovery handles one missing boundary, not multiple consecutive misses
  • a beat-shaped motion upslope at exactly the expected phase cannot be distinguished by timing alone; downstream residual/template QC remains required
  • false primary detections are handled through interval/QC rejection rather than boundary deletion
  • too few clean reference beats disables template rejection; residual and duration checks still apply
  • if every interval is rejected, the pipeline raises a clear error instead of silently falling back to contaminated beats

Closes #28

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make beat segmentation and waveform extrema robust to missed peaks and motion artifacts

1 participant