Skip to content

Fix pop_select nopoint removing two samples too few - #317

Open
arnodelorme wants to merge 1 commit into
developfrom
fix/pop-select-nopoint-extent
Open

Fix pop_select nopoint removing two samples too few#317
arnodelorme wants to merge 1 commit into
developfrom
fix/pop-select-nopoint-extent

Conversation

@arnodelorme

Copy link
Copy Markdown
Collaborator

🤖 Fix pop_select so user-supplied removal ranges (nopoint, notime, rmpoint, rmtime) remove exactly the requested samples, matching EEGLAB.

Problem

On sample_data/eeglab_data.set (30504 samples, 128 Hz), compared against EEGLAB R2025b:

call MATLAB pnts Python pnts (before) MATLAB boundary Python boundary (before)
nopoint=[276, 525] 30254 (removes 250) 30256 (removes 248) 275.5 276.5
nopoint=[1, 10] 30494 (removes 10) 30495 (removes 9) 0.5 0.5
point=[276, 525] 250 kept 250 kept 0.5 0.5

The keep path (point/time) was already correct; only the removal path was off by one sample at every interior edge.

Cause

EEGLAB pop_select.m (lines 564-584) shifts interior edges by +/-1/srate only inside if isempty(g.notime), i.e. when notime is derived as the complement of a user-supplied time keep range (so the kept samples are exactly [t0, t1]). User-supplied notime/nopoint (and their rmtime/rmpoint aliases, which are plain reassignments at lines 261-266) go straight to eeg_lat2point and eeg_eegrej.

Python pop_select.py (previously lines 96-97 and 408-420) applied that shift to every notime matrix except one that came from rmtime, so nopoint, notime, and rmpoint each removed two samples too few (one at each edge, or one at a dataset edge).

Fix

Move the +/-1-sample interior-edge adjustment into the branch that builds the complement from time_mat, and drop the notime_from_rmtime special case. All four user-supplied removal keywords now pass through unchanged, and the derived-complement case for time/point is unchanged.

Verification

MATLAB (R2025b, EEGLAB) vs Python after the fix, on sample_data/eeglab_data.set with the branch on PYTHONPATH. Boundaries are (latency, duration); maxabs is the max absolute data difference.

case py pnts ml pnts py boundaries ml boundaries maxabs
nopoint=[276, 525] 30254 30254 (275.5, 250) (275.5, 250) 0
nopoint=[1, 10] 30494 30494 (0.5, 10) (0.5, 10) 0
nopoint=[30495, 30504] 30494 30494 (30494.5, 10) (30494.5, 10) 0
rmpoint=[276, 525] 30254 30254 (275.5, 250) (275.5, 250) 0
notime=[2.15, 4.1] 30253 30253 (275.5, 251) (275.5, 251) 0
rmtime=[2.15, 4.1] 30253 30253 (275.5, 251) (275.5, 251) 0
point=[276, 525] 250 250 (0.5, 275), (250.5, 29979) (0.5, 275), (250.5, 29979) 0
time=[2.15, 4.1] 251 251 (0.5, 275), (251.5, 29978) (0.5, 275), (251.5, 29978) 0
nopoint=[[100, 200], [300, 400]] 30302 30302 (99.5, 101), (198.5, 101) (99.5, 101), (198.5, 101) 0
point=[[100, 200], [300, 400]] 202 202 (0.5, 99), (101.5, 99), (202.5, 30104) same 0

Tests added in tests/test_pop_select.py:

  • TestPopSelectContinuousRemoval (6 tests): exact pnts and boundary (latency, duration) for the cases above, plus a complement test that point=[a, b] keeps exactly the samples nopoint=[a, b] removes and that concatenating the two reconstructs the original data.
  • TestPopSelectParity.test_parity_nopoint_continuous: MATLAB parity for nopoint (skips without MATLAB).
EEGPREP_SKIP_MATLAB=1 QT_QPA_PLATFORM=offscreen python -m pytest tests/test_pop_select.py tests/test_gui_pop_select.py tests/test_rejection_workflows.py tests/test_eeg_eegrej.py -q
# 94 passed, 8 skipped

EEGPREP_EEGLAB_ROOT=... python -m pytest tests/test_pop_select.py::TestPopSelectParity -q
# 5 passed (MATLAB engine)

No pop_rejcont test encoded the old off-by-one values, so none needed updating. ruff check and ruff format --check pass on the changed files.

@claude claude Bot 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.

⚠️ Code review skipped: your organization's credit balance is too low for Code Review to run.

An organization admin can purchase credits or upgrade the plan in Plans & Billing.

Once credits are available, reopen this pull request to trigger a review.

@claude

claude Bot commented Sep 7, 2026

Copy link
Copy Markdown

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

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.

1 participant