Repository navigation
Commit 534e522
authored
Skip already-rejected peaks in XQRS backsearch (#596)
When backsearch runs and finds nothing, `last_qrs_peak_num` stays put.
On the next peak backsearch runs again over the same range plus one more
peak, and so on. A long stretch with no QRS complexes (lead off, flat
line, low-amplitude noise) is therefore rescanned at every peak, which
is quadratic in the length of the stretch. I think this is what #352 is
seeing: most records are fine, the ones with a long bad section take
hours.
Record 100 with a gap of low-amplitude noise inserted:
| gap | before | after |
|---|---|---|
| 10 min | 1.7 s | 0.4 s |
| 40 min | 23.4 s | 1.3 s |
The fix remembers the last peak a backsearch checked and starts the next
one after it. A peak's backsearch result only depends on `qrs_thr`,
`last_qrs_ind` and the signal, which only change in `_update_qrs`, and
`_update_qrs` always moves `last_qrs_peak_num` up to the current peak.
So the skipped peaks would have been rejected again, and the detector
ends up in exactly the same state.
Testing:
- New test: inserts a 2-minute noise gap into record 100 and checks
backsearch never checks the same peak twice, and that beats on both
sides are found. Fails on the old code.
- Compared old vs new on 300 random cases (sample-data records with
inserted noise gaps, flat sections and amplitude changes; random
`hr_init`, `ref_period`, `t_inspect_period`, with and without learning).
`qrs_inds`, `backsearch_qrs_inds` and all running parameters were
identical.
- I also wrote a short Lean proof of the "same state after every peak"
argument: https://github.com/TheNetherWatcher/wfdb-backsearch-proof. The
detector is modelled abstractly there, so it relies on the three
properties above, which I checked by reading the code.
Fixes the slowdown in #352.3 files changed
Lines changed: 40 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
23 | 26 | | |
24 | 27 | | |
25 | 28 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
610 | 610 | | |
611 | 611 | | |
612 | 612 | | |
613 | | - | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
614 | 618 | | |
615 | 619 | | |
616 | 620 | | |
617 | 621 | | |
| 622 | + | |
618 | 623 | | |
619 | 624 | | |
620 | 625 | | |
| |||
635 | 640 | | |
636 | 641 | | |
637 | 642 | | |
| 643 | + | |
| 644 | + | |
638 | 645 | | |
639 | 646 | | |
640 | 647 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
192 | 192 | | |
193 | 193 | | |
194 | 194 | | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
195 | 224 | | |
196 | 225 | | |
197 | 226 | | |
| |||
0 commit comments