Skip to content

Fix ITD crash on signals with mismatched extrema counts#49

Open
deekshaNVIDIA wants to merge 1 commit into
wwhenxuan:mainfrom
deekshaNVIDIA:fix/itd-baseline-extract-crash
Open

Fix ITD crash on signals with mismatched extrema counts#49
deekshaNVIDIA wants to merge 1 commit into
wwhenxuan:mainfrom
deekshaNVIDIA:fix/itd-baseline-extract-crash

Conversation

@deekshaNVIDIA
Copy link
Copy Markdown
Contributor

Summary

Fixes #29 — ITD's itd_baseline_extract method crashed with a ValueError when processing signals where the number of local maxima and minima differed after boundary padding.

Root Cause

Lines 106-107 used np.append to flatten (index, value) pairs into 1D arrays:

LK1 = np.append(idx_min.reshape(-1, 1), LK1.reshape(-1, 1))  # flat 1D, length = 2*len(idx_min)
LK2 = np.append(idx_max.reshape(-1, 1), LK2.reshape(-1, 1))  # flat 1D, length = 2*len(idx_max)
LK = np.vstack((LK1, LK2)).T  # CRASH: requires equal lengths

After the boundary condition adjustments (lines 74-88), idx_min and idx_max could have different lengths (e.g., 14 vs 12 as reported), making np.vstack fail with:

ValueError: all the input array dimensions except for the concatenation axis must match exactly,
but along dimension 1, the array at index 0 has size 14 and the array at index 1 has size 12

Changes

pysdkit/_itd/itd.py:

  • Use np.column_stack to build proper (position, value) 2D arrays for LK1 and LK2 control points, then np.vstack to merge them — works regardless of differing array lengths
  • Fix boundary padding to use the actual signal value at the mirrored position (x[idx]) instead of reusing the first/last value from the wrong envelope
  • Add guard for signals with no extrema (pure trends), returning the signal as baseline with zero rotation component
  • Handle division-by-zero in piecewise slope computation when consecutive extrema have equal signal values
  • Use np.concatenate with explicit int casting for index arrays to prevent float indexing errors
  • Remove debug print statements

pysdkit/tests/test_itd.py (new):

  • Add comprehensive test suite with 7 test cases:
    • Built-in test signals (3 cases)
    • __call__ interface
    • Signal reconstruction accuracy verification
    • Near-monotonic signal (the crash case from issue Issue with ITD method #29)
    • Pure trend signal (no extrema)
    • Asymmetric extrema counts (different number of maxima vs minima)
    • String representation

Test Plan

  • All 9 new ITD tests pass
  • All 25 existing EMD/CEEMDAN tests still pass (regression check)
  • Reconstruction error < 1e-10 for all signal types
  • Near-monotonic signals no longer crash
  • Pure trends handled gracefully
  • Signals with unequal maxima/minima counts work correctly

The itd_baseline_extract method crashed with a ValueError when
the number of local maxima and minima differed after boundary
padding, because np.vstack required equal-length arrays.

Root cause: Lines 106-107 used np.append to flatten (index, value)
pairs into 1D arrays, then np.vstack((LK1, LK2)) assumed both
had the same length. After the boundary conditions on lines 74-88
could add different counts to idx_max vs idx_min, the arrays
diverged in length causing the crash.

Changes in itd.py:
- Use np.column_stack to build proper (position, value) 2D arrays
  for LK1 and LK2, then np.vstack to merge them. This works
  regardless of whether the arrays have different lengths.
- Fix boundary padding to use the actual signal value at the
  mirrored position (x[idx]) instead of reusing the first/last
  extremum value from the wrong envelope.
- Add guard for signals with no extrema (pure trends), returning
  the signal as baseline with zero rotation component.
- Handle division-by-zero in the piecewise slope computation when
  consecutive extrema have equal signal values.
- Use np.concatenate with explicit int casting for index arrays to
  prevent float indexing errors.
- Remove debug print statements.

New file test_itd.py:
- Add comprehensive test suite covering built-in signals,
  near-monotonic signals (the crash case), asymmetric extrema,
  pure trends, reconstruction accuracy, and the __call__ interface.
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.

Issue with ITD method

1 participant