Skip to content

Prepare release v1.5.1 - #1023

Merged
bruAristimunha merged 6 commits into
masterfrom
release/1.5.1
May 20, 2026
Merged

bruAristimunha merged 6 commits into
masterfrom
release/1.5.1

Conversation

@bruAristimunha

Copy link
Copy Markdown
Collaborator

Summary

Patch release for braindecode 1.5.1, 11 days after v1.5.0.

  • Bump braindecode/version.py from 1.5.0 → 1.5.1
  • Split the post-v1.5.0 changelog entries into a new Current 1.5.1 (stable) section in docs/whats_new.rst, mirroring the pattern from PR Prepare release v1.5.0 #1010.

What's in 1.5.1

Enhancements

Bug fixes

Test plan

  • CI green (tests, docs, pre-commit)
  • python -m build --sdist produces braindecode-1.5.1.tar.gz
  • Docs build locally with make html

Post-merge checklist

  • Snapshot docs to braindecode.github.io/1.5/ and refresh stable/
  • python -m twine upload --repository braindecode dist/*
  • Tag v1.5.1 and create the GitHub release

Bump version from 1.5.0 to 1.5.1 and split the post-v1.5.0 changelog
entries (BandRotation, EMG2QwertyNet SpecAugment + return_features,
AmplitudeScale RNG crash fix, Jonathan Dan author link) into a new
'Current 1.5.1 (stable)' section, mirroring the pattern from the
v1.5.0 release commit.
Copilot AI review requested due to automatic review settings May 19, 2026 21:36

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

Prepares the braindecode v1.5.1 patch release by updating the package version and stamping the changelog so the post-v1.5.0 entries are grouped under a new “Current 1.5.1 (stable)” section.

Changes:

  • Bump package version from 1.5.0 → 1.5.1.
  • Reorganize docs/whats_new.rst to add a new Current 1.5.1 (stable) section with enhancements + bug fixes (and link PR references via :gh:).

Reviewed changes

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

File Description
docs/whats_new.rst Adds “Current 1.5.1 (stable)” section and moves/annotates release notes for the 1.5.1 patch release.
braindecode/version.py Updates __version__ to 1.5.1 (used by pyproject dynamic version).

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

PR #993 (1.5.0) removed the per-batch ch_names kwarg from
Labram.forward and tightened the __init__ chs_info check into a
ValueError. Downstream wrappers (neuroai's _LabramChannelWrapper)
were still calling Labram with non-canonical chs_info and a per-batch
ch_names subset, producing 7 test failures.

Restore the kwarg as keyword-only (via *); when provided it
case-insensitively maps each name to LABRAM_CHANNEL_ORDER and uses
those indices for the position-embedding bank. When None, fall back
to the 1.5.0 arange-over-canonical behavior. The __init__ canonical
check is downgraded to a UserWarning so wrappers can build the inner
Labram with their union channel set and resolve the subset per batch.

Update test_labram_rejects_non_canonical_chs to assert the warning
(renamed to test_labram_warns_on_non_canonical_chs). Document the
restoration under 1.5.1 'API and behavior changes' in whats_new.
…-of-raise

Since 1.5.1 downgraded Labram's non-canonical-chs_info ValueError to a
UserWarning (to keep wrappers like neuroai's _LabramChannelWrapper
working), update plot_channel_interpolation.py to demonstrate the
warning behavior instead of catching the exception. The 'pretrained
model expects a specific layout' narrative still holds — vanilla
Labram still mis-aligns position embeddings on arbitrary user data
when ch_names is not provided per batch.
Copilot AI review requested due to automatic review settings May 19, 2026 22:33

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

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

Comment thread braindecode/models/labram.py
Comment thread braindecode/models/labram.py
Comment thread braindecode/models/labram.py Outdated
Comment thread examples/model_building/plot_channel_interpolation.py Outdated
Apply review feedback:
- Lift the ch_names -> canonical-index dict to module scope as
  _LABRAM_CANONICAL_INDEX instead of rebuilding it every forward
  call (~128 string ops + dict inserts saved per batch).
- Strip changelog narrative (the 'Restored in 1.5.1' / neuroai mentions)
  from the forward docstring and __init__ comment — that history lives
  in whats_new.rst, not in the runtime code.
- Tighten the non-canonical-chs_info warning: drop Sphinx :meth: /
  :class: roles (they don't render at runtime) and collapse to 4 lines.
- Drop the redundant 'x is already in canonical order' comment in the
  forward fallback branch — the arange already says it.
- Trim the length-mismatch ValueError to the equation alone.

Behavior unchanged; all 25 braindecode labram tests + 13 neuroai
test_labram tests still pass.
Shipped-release changelog entries are append-only in this repo; the
1.5.1 entry already describes the ch_names restoration so the
cross-reference in the 1.5.0 entry was redundant and broke convention.
Copilot AI review requested due to automatic review settings May 19, 2026 22:44

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

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

Comments suppressed due to low confidence (4)

braindecode/models/labram.py:722

  • forward introduces a * before ch_names, which also makes return_patch_tokens, return_all_tokens, and return_features keyword-only. If the intent is only to make ch_names keyword-only (as stated in the changelog), move the * so existing positional calls for the return flags remain supported, or update the docs to reflect the broader API change.

This issue also appears in the following locations of the same file:

  • line 731
  • line 751
  • line 756
    def forward(
        self,
        x,
        *,
        ch_names: list[str] | None = None,
        return_patch_tokens=False,
        return_all_tokens=False,
        return_features=False,
    ):

braindecode/models/labram.py:755

  • When ch_names is None, input_chans is always built for the full canonical 128-channel bank. If x.shape[1] != len(LABRAM_CHANNEL_ORDER) (e.g., constructing Labram with a smaller chs_info now only emits a warning), this will later produce a token/position-embedding shape mismatch and fail at runtime. Consider adding an explicit ValueError here when ch_names is None but x is not canonical-sized (and point users to ch_names or InterpolatedLaBraM).
        if ch_names is None:
            input_chans = torch.arange(
                len(LABRAM_CHANNEL_ORDER) + 1, device=x.device, dtype=torch.long
            )
        else:

braindecode/models/labram.py:737

  • ch_names is documented as selecting channel position embeddings, but it is only applied in forward_features when self.neural_tokenizer is True; in decoder mode the code path ignores input_chans. To avoid confusing callers, consider either raising/ warning when ch_names is passed in decoder mode, or documenting that ch_names is supported only in tokenizer mode.
        ch_names : list of str, optional
            Channel names matching the channel axis of ``x``. Matched
            case-insensitively against :data:`LABRAM_CHANNEL_ORDER` to
            select the corresponding position embeddings, so callers can
            forward an arbitrary subset of canonical channels. If
            ``None`` (default), ``x`` is assumed to already be in
            :data:`LABRAM_CHANNEL_ORDER`.

braindecode/models/labram.py:771

  • The new ch_names mapping logic (case-insensitive matching, unknown-name error path, and the new behavior when ch_names is omitted) is not exercised by unit tests. Adding focused tests for: (1) successful subset forward with ch_names (including mixed-case names), and (2) a clear error when ch_names contains an unknown channel would help prevent regressions.
            if len(ch_names) != x.shape[1]:
                raise ValueError(
                    f"len(ch_names)={len(ch_names)} != x.shape[1]={x.shape[1]}"
                )
            try:
                matched = [_LABRAM_CANONICAL_INDEX[n.upper()] for n in ch_names]
            except KeyError as exc:
                raise ValueError(
                    f"ch_names contains a name not in LABRAM_CHANNEL_ORDER: "
                    f"{exc.args[0]!r}. Filter unknown channels before calling "
                    f"forward, or use InterpolatedLaBraM."
                ) from exc
            # CLS token at index 0; canonical channel indices are offset by 1.
            input_chans = torch.tensor(
                [0] + [i + 1 for i in matched], device=x.device, dtype=torch.long
            )

Comment thread examples/model_building/plot_channel_interpolation.py Outdated
Comment thread examples/model_building/plot_channel_interpolation.py Outdated
- forward(): move `*` after the return_* flags so only `ch_names` is
  keyword-only. `return_patch_tokens`, `return_all_tokens` and
  `return_features` stay positional, preserving back-compat for
  callers that used positional args before #993.
- forward(): when `ch_names is None`, validate `x.shape[1] ==
  len(LABRAM_CHANNEL_ORDER)` up front and raise a clear ValueError
  pointing to `ch_names=` or `InterpolatedLaBraM` instead of failing
  later with a confusing shape mismatch inside `forward_features`.
- forward() docstring: clarify that `ch_names` is keyword-only and
  only honored when `neural_tokenizer=True`; in decoder mode the
  position embedding is sequential.
- examples/plot_channel_interpolation: drop the redundant in-body
  `import warnings` (already imported at module top) and rewrite the
  "silently mis-align" wording — the model warns at construction and
  forward now raises ValueError on a non-canonical channel count.
- test_foundation_models: add focused tests for the ch_names path
  — subset forward, case-insensitive matching, unknown-channel
  ValueError, length mismatch, the new None+non-canonical guard,
  and back-compat for positional return_* flags.
@bruAristimunha
bruAristimunha merged commit 93a8b82 into master May 20, 2026
13 checks passed
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