Skip to content

Fix critical bugs: NumPy 1.24+ compatibility, division by zero, and alert detection#4

Merged
dfeen87 merged 3 commits into
mainfrom
copilot/fix-bugs-in-code-review
Feb 14, 2026
Merged

Fix critical bugs: NumPy 1.24+ compatibility, division by zero, and alert detection#4
dfeen87 merged 3 commits into
mainfrom
copilot/fix-bugs-in-code-review

Conversation

Copilot AI commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Code review identified 5 bugs causing runtime failures, incorrect behavior, and version incompatibility.

Changes

NumPy 1.24+ compatibility (core/features.py)

  • Replace np.math.factorial() (removed in NumPy 1.24) with math.factorial()

Division by zero guards (core/features.py)

  • Spectral centroid: return 0.0 when PSD sum is zero instead of NaN
  • Permutation entropy: validate signal length before embedding (return 0.0 with warning for insufficient data)

Numerical stability (core/preprocessing.py)

  • Increase epsilon from 1e-10 to 1e-6 in quality check normalized std calculation

Alert detection fix (core/gate.py)

  • Variable mutation bug: offset_idx reassignment in zip loop didn't propagate
  • Use separate end_idx variable to correctly track adjusted alert window bounds
# Before: offset_idx mutation lost
for onset_idx, offset_idx in zip(onset_indices, offset_indices):
    if gate_series[offset_idx] == 0 and offset_idx > onset_idx:
        offset_idx -= 1  # Local reassignment, doesn't affect subsequent usage
    duration = timestamps[offset_idx] - timestamps[onset_idx]  # Uses original value

# After: explicit tracking variable
for onset_idx, offset_idx in zip(onset_indices, offset_indices):
    end_idx = offset_idx
    if gate_series[end_idx] == 0 and end_idx > onset_idx:
        end_idx -= 1
    duration = timestamps[end_idx] - timestamps[onset_idx]  # Uses corrected value

All 101 tests passing. Zero security vulnerabilities (CodeQL).


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits February 13, 2026 19:53
… issues

Co-authored-by: dfeen87 <158860247+dfeen87@users.noreply.github.com>
…ilent signals

Co-authored-by: dfeen87 <158860247+dfeen87@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix bugs identified during code review Fix critical bugs: NumPy 1.24+ compatibility, division by zero, and alert detection Feb 13, 2026
Copilot AI requested a review from dfeen87 February 13, 2026 19:59
@dfeen87
dfeen87 marked this pull request as ready for review February 14, 2026 11:14
Copilot AI review requested due to automatic review settings February 14, 2026 11:14
@dfeen87
dfeen87 merged commit a209f5b into main Feb 14, 2026
4 checks passed
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes several edge-case/runtime issues in the signal feature extraction and alerting pipeline, including NumPy 1.24+ compatibility and guards against invalid numerical results.

Changes:

  • Update permutation_entropy normalization to use math.factorial (NumPy 1.24+ compatibility) and add a “too short signal” guard.
  • Prevent division-by-zero/NaN in compute_spectral_centroid when the PSD sum is zero.
  • Increase the epsilon used in quality_check’s normalized std computation for improved numerical stability, and adjust alert-window indexing logic in detect_alert_events.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
core/features.py Adds guards for spectral centroid / permutation entropy edge cases and replaces deprecated NumPy factorial usage.
core/preprocessing.py Adjusts epsilon in quality normalization to reduce numerical instability.
core/gate.py Refactors alert end-index handling to make the inclusive end bound explicit.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core/features.py
Comment on lines +373 to +381
# Check if signal is too short for the embedding
min_length = order + delay * (order - 1)
if n < min_length:
warnings.warn(
f"Signal too short (n={n}) for permutation entropy with order={order}, "
f"delay={delay}. Minimum length required: {min_length}. Returning 0.0."
)
return 0.0

Copilot AI Feb 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new “signal too short” early-return path (including warning emission) isn’t covered by tests. Consider adding a unit test that passes a too-short sig for a given order/delay, asserts the function returns 0.0, and uses pytest.warns to verify the warning is raised.

Copilot uses AI. Check for mistakes.
Comment thread core/features.py
Comment on lines +373 to +374
# Check if signal is too short for the embedding
min_length = order + delay * (order - 1)

Copilot AI Feb 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

min_length is computed as order + delay * (order - 1), which is stricter than what the embedding loop actually requires (range(n - delay*(order-1))). This will return 0.0 (and emit a warning) for signal lengths where the function could still compute permutation entropy (e.g., n=delay*(order-1)+1). Consider changing the guard to match the real minimum required for at least one embedded vector (or clearly justify/parameterize a stricter minimum).

Suggested change
# Check if signal is too short for the embedding
min_length = order + delay * (order - 1)
# Check if signal is too short for the embedding:
# need at least one embedded vector, i.e. n - delay * (order - 1) >= 1
min_length = delay * (order - 1) + 1

Copilot uses AI. Check for mistakes.
Comment thread core/gate.py
for onset_idx, offset_idx in zip(onset_indices, offset_indices):
if gate_series[offset_idx] == 0 and offset_idx > onset_idx:
offset_idx -= 1
# Use separate variable to avoid mutation issues with zip iteration

Copilot AI Feb 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new comment about “mutation issues with zip iteration” is misleading in Python: reassigning offset_idx inside the loop would affect subsequent uses of offset_idx within that iteration. If the intent is to make the inclusive end bound explicit (or to avoid implying mutation of offset_indices), consider rewording the comment to describe that instead.

Suggested change
# Use separate variable to avoid mutation issues with zip iteration
# Use a separate variable for the (potentially adjusted) inclusive end index

Copilot uses AI. Check for mistakes.
Comment thread core/features.py
Comment on lines 124 to +133
freqs, psd = signal.welch(sig, fs=fs, nperseg=min(len(sig), 256))

# Compute centroid as weighted mean
centroid = np.sum(freqs * psd) / np.sum(psd)
psd_sum = np.sum(psd)
if psd_sum > 0:
centroid = np.sum(freqs * psd) / psd_sum
else:
# If PSD is all zeros (silent/flatline signal), return 0.0
# to indicate absence of spectral content
centroid = 0.0

Copilot AI Feb 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behavior returns 0.0 when np.sum(psd) is zero. There’s currently no test covering a silent/zero signal (PSD all zeros) to ensure this path is exercised and avoids NaNs/ZeroDivision. Consider adding a unit test for compute_spectral_centroid(np.zeros(...), fs) expecting 0.0.

Copilot uses AI. Check for mistakes.
@dfeen87
dfeen87 deleted the copilot/fix-bugs-in-code-review branch March 24, 2026 08:58
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.

3 participants