Repository navigation
fix: guard against ZeroDivisionError in Comparitor._calc_stats - #566
Conversation
|
Thanks for picking this up, the crash in #278 is still there on Could you rebase on When I applied the change to current That error comes from a few lines earlier in A few small things while you're there:
|
`compare_annotations` can match one test annotation to two reference annotations: ```python c = processing.compare_annotations(np.array([0, 2, 4, 5]), np.array([1, 5]), window_width=6) c.matching_sample_nums # [0, -1, 0, 1]: test annotation 0 is used twice c.fp, c.positive_predictivity # -1, 1.5 ``` When a reference annotation loses a contested test annotation to the next reference, `compare` falls back to the previous test annotation. It only checks that the *previous reference* didn't take it, so if that reference was unmatched, a test annotation matched earlier on can be matched again. **Fix:** keep track of the last matched test annotation. Matches are made in increasing order, so the fallback is used only if it comes after that one. This replaces the old check (which it covers). **Checking that nothing else changes:** - On 200,000 random small cases, the new code gives exactly the same matches as `main` whenever `main` doesn't match a test annotation twice (about 6% of the cases did). With the fix, none do. - On record 100 (gqrs and xqrs against the reference beats, two window sizes), the matches are identical. **Tests:** the example above, plus a randomized check that matches are unique, in order and within the window, and that `fp` is never negative. Both fail on `main`. `pytest -m "not network"` and the docs build pass. This is separate from #566, which handles empty inputs in `_calc_stats`.
When there are no reference annotations (tp + fn == 0) or no test annotations (n_test == 0), computing sensitivity and positive predictivity raises ZeroDivisionError. Return NaN instead, matching the convention used by sklearn.metrics for undefined ratios. Fixes MIT-LCP#278
Cover three boundary scenarios that previously raised ZeroDivisionError: - Empty reference, non-empty test → sensitivity=NaN, PPV=0.0 - Non-empty reference, empty test → sensitivity=0.0, PPV=NaN - Both empty → both NaN
np.array(range(0)) is a float array, which can't be used as an index, so an empty set of test annotations still failed with an IndexError before reaching the zero division check. Use np.arange instead, and add a changelog entry.
387e12c to
dec7750
Compare
|
Thanks for the fix! To get this merged, I've rebased it onto |
Summary
Guard against
ZeroDivisionErrorwhen comparing annotations with empty reference or test arrays.Bug
Comparitor._calc_stats()dividestpby(tp + fn)for sensitivity and byn_testfor positive predictivity without checking for zero denominators. When either annotation array is empty, this raisesZeroDivisionError.Fix
Return
float("nan")when the denominator is zero, matching the convention used bysklearn.metricsfor undefined ratios.Tests
Three module-level test functions covering all edge cases:
Fixes #278