Skip to content

Fix falsy pad-constant check in pad_sliding_window and correct window stat docstrings - #429

Merged
gbeane merged 1 commit into
mainfrom
claude/quality-2026-08-07
Aug 7, 2026
Merged

Fix falsy pad-constant check in pad_sliding_window and correct window stat docstrings#429
gbeane merged 1 commit into
mainfrom
claude/quality-2026-08-07

Conversation

@gbeane

@gbeane gbeane commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Reasoning

src/jabs/feature_extraction/window_operations/window_stats.py backs every non-circular window feature in JABS (mean, median, std_dev, skew, kurtosis, min, max — see the _window_operations table in feature_base_class.py:70-78), and it had no test module at all. Three defects were sitting in it:

  1. Latent bug — falsy pad constant. pad_sliding_window tested if pad_const: to decide between constant padding and edge padding. Its own docstring says "None will pad with value at the edge", but a pad constant of 0 or 0.0 is falsy, so it silently took the edge-padding branch instead. This is the classic "truthiness where you meant is not None" bug. Every caller today passes np.nan (truthy), so no computed feature value changes — hence no FEATURE_VERSION bump. It's a trap for the next caller, not a live regression.

  2. Inverted docstring. get_window_masks documented its return as "valid (0) and invalid (1)". The code returns the opposite polarity: True marks valid values. Both call sites confirm this — window_median passes mask=~window_masks to np.ma.array (where True means masked-out), and window_min/window_max pass where=window_masks to the reduction (where True means include). A reader trusting the docstring would invert the mask.

  3. Copy-paste docstring. window_min was documented as "Calculates a masked maximum of a window" / "sliding window maximum values".

I looked at several other candidates — TrackLabels.downsample binning rules, the LOGO split helpers in classifier_utils.py, and the psd helpers in signal_stats.py — but those are either already well documented or would require a behavior change to "fix". This file had the highest ratio of real defect to blast radius, and it was the only one where a latent bug, two wrong docstrings, and zero test coverage all overlapped.

Why this is safe: the only executable change is if pad_const:if pad_const is not None:, which can only differ when pad_const is 0/0.0, and no caller in the repository passes that. The get_window_masks rewrite is provably equivalent: np.where on a 1-D boolean returns a 1-tuple, so the old for loop iterated exactly once over the index array and assigned the same rows the new boolean index assigns. Full suite: 825 passed, 200 skipped.

Change

Logic changes

src/jabs/feature_extraction/window_operations/window_stats.py

  • pad_sliding_window: if pad_const:if pad_const is not None:, so a pad constant of 0 is honored instead of falling through to edge padding.
  • get_window_masks: replaced for no_data_row in np.where(np.all(~window_masks, axis=1)): with a direct boolean index window_masks[np.all(~window_masks, axis=1)] = True. Same result, no single-iteration loop over a np.where tuple. Rewrote the docstring to state the actual mask polarity (True = valid) and to explain why all-pad rows are returned fully unmasked.
  • window_min: corrected the docstring, which described a maximum.

tests/feature_extraction/window_operations/test_window_stats.py (new)

  • 15 tests covering pad_sliding_window (shape, edge padding, constant padding — parametrized over 0.0 / -1.0 / nan so the falsy-constant case is a regression test), get_window_masks (nan and non-nan constants, all-pad rows), window_mean / window_median / window_std_dev padding behavior, window_min / window_max including the all-nan guard, and that window_skew / window_kurtosis agree with np_skew / np_kurtosis on the padded view.

Mechanical updates

None — no imports, exports, or call sites were touched.


This PR was produced by an automated analysis from Claude Code.


Generated by Claude Code

…docs

pad_sliding_window used a truthiness check on pad_const, so a pad constant
of 0 (or 0.0) silently fell through to edge padding instead of constant
padding. Every current caller pads with nan, so this is a latent bug with
no change to computed features. Also corrects two misleading docstrings
and replaces an obscure np.where loop with a direct boolean index.

Adds unit tests for the previously untested window_stats module.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ALN3xSiV2DPo5JFDRXa9sK

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 hardens and clarifies the sliding-window statistics helpers used across JABS feature extraction by fixing a latent padding bug, correcting misleading docstrings, and adding a dedicated unit test module for window_stats.py.

Changes:

  • Fixed pad_sliding_window to treat pad_const=0/0.0 as a real constant (using is not None instead of a truthiness check).
  • Simplified get_window_masks implementation while correcting/clarifying mask polarity documentation (True = valid).
  • Added a new pytest module covering padding, masking, and the windowed stats helpers (mean/median/std/min/max/skew/kurtosis).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/jabs/feature_extraction/window_operations/window_stats.py Fixes the falsy-constant padding bug, simplifies get_window_masks, and corrects docstrings.
tests/feature_extraction/window_operations/test_window_stats.py Adds unit tests to prevent regressions and validate padding/masking/stat behavior.

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

@gbeane
gbeane merged commit b5373d5 into main Aug 7, 2026
6 checks passed
@gbeane
gbeane deleted the claude/quality-2026-08-07 branch August 7, 2026 19:18
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.

2 participants