Skip to main content

nimbus-bci

Nimbus Personalizer — Bayesian personalization head for frozen neural EEG embeddings.
Plug any frozen trunk that emits encode(X) → Z, adapt online with a Nimbus head, ship apps on BrainState — without owning or retraining the encoder.

0.6 product shape: the Personalizer surface — cheap online adaptation (~8–10× cheaper than batch refit, ~22–131× cheaper than trunk retraining at matched n), portable profiles, and paradigm recipes (MI · P300 · Riemannian).

Also ships sklearn-compatible heads for classical feature pipelines (CSP, Riemann, …): Bayesian LDA / QDA / Softmax, plus NimbusSTS (EKF latent state + point-estimated emissions). Those heads power Personalizer and can be used alone.

Docs · Personalizer · API reference · PyPI · Contact

Install

pip install nimbus-bci
# optional: pip install nimbus-bci[softmax]   # JAX Softmax head
# optional: pip install nimbus-bci[riemann]   # pyRiemann pipelines
# optional: pip install nimbus-bci[mne]       # MNE helpers
# optional: pip install nimbus-bci[train]     # torch trunk-arm trainers (LoRA / FT)
# optional: pip install nimbus-bci[viz]       # matplotlib plotting helpers
# optional: pip install nimbus-bci[all]       # everything above

From source: pip install -e ".[all]" after cloning.

Upgrading from 0.5? See Migration notes in CHANGELOG.md (ships in the sdist; also linked from docs.nimbusbci.com).

5-minute quickstart

Run the example (no external data needed):

python examples/quickstart.py

Or follow along:

import numpy as np
from nimbus_bci import Personalizer, wrap

# 1. Wrap any frozen trunk (EEGNet, REVE, ...) — here a random projection.
rng = np.random.default_rng(42)
proj = rng.standard_normal((6, 16))
enc = wrap(lambda X: X @ proj, model_id="toy", embedding_dim=16)

# 2. Fit a Bayesian head on ~30 calibration trials.
#    for_deployment = strict gating + LDA + minimal params (the common case).
#    For research/experimentation: Personalizer.for_research(enc, classes, ...).
#    For classical features (no encoder): Personalizer.for_features(classes).
#    To PIN the accept rate for your trunk (default-gate accept rates span
#    7-78% across trunks), fit + calibrate the gate in one call:
#    adapter.fit_calibrated(X_cal, y_cal, X_val, y_val, target_accept=0.7)
adapter = Personalizer.for_deployment(enc, ["left_hand", "right_hand"],
                                       paradigm="motor_imagery")
adapter.fit(X_cal, y_cal)

# 3. Predict → BrainState with trial rejection.
states = adapter.predict(X_test)         # list[BrainState]
accepted = [s for s in states if not s.rejected]  # confident trials
# s.intent, s.confidence, s.uncertainty, s.rejected, s.rejection_reason

# 4. Adapt online (exact conjugate update — no retraining).
adapter.partial_fit(X_new, y_new)

# 5. Save / load.
adapter.save("profile"); loaded = Personalizer.load("profile", encoder=enc)

The three regimes

# A. Classical features (CSP log-variance, tangent space, hand-crafted) —
#    no encoder, features go straight to the Bayesian head.
p = Personalizer.for_features(["left", "right"]).fit(X_csp, y)

# B. Frozen deep trunk (EEGNet, foundation model) — embeddings → head,
#    strict trial gating out of the box.
p = Personalizer.for_deployment(enc, ["left", "right"]).fit(X_cal, y_cal)
states = p.predict(X_test)          # BrainState per trial, rejected flagged

# C. Riemannian geometry & P300 (OAS / xDAWN tangent space) —
#    weak-trunk / raw epochs; for_riemann defaults to label-free geodesic
#    tracking (tracking_alpha=0.05). Opt out with tracking_alpha=0.0.
p = Personalizer.for_riemann(["left", "right"]).fit(X_cal, y_cal)
# Or for P300 spellers (tracking opt-in; recommend α=0.05 when enabling):
# Personalizer.for_p300(["NonTarget", "Target"], tracking_alpha=0.05)
p.adapt(epoch)                      # label-free reference update (0 labels needed!)

# D. Streaming adaptation loop — predict, optionally partial_fit on new
#    labels; the conjugate head update is exact and cheap (no retraining).
#    Reference: examples/middleware_streaming_adaptation.py
for trial in stream:
    state = p.predict(trial)                # BrainState
    if label_available(state):
        p.partial_fit(trial, label)         # ~1/30-1/131 the wall cost of retraining

Regime A/B/C are the shipped surface. A governed session runtime (drift gates, attribution, label budgets, quarantine) with subconscious error-potential self-supervision is in research and will ship separately.

The full parameter surface (user=, preset=, head choice) via direct construction — anything that maps inputs to embeddings (n, d) plugs in; Nimbus does not own DL architectures:

adapter = Personalizer(
    encoder=enc, head="lda", user="subject_001",
    classes=["left", "right"], preset="strict",
)

Full walkthrough with copy-paste synthetic data: Quickstart.

Optional shortcuts for common external trunks: wrap_eegnet, and from nimbus_bci.middleware.adapters import wrap_braindecode (see encoder contract).

Examples in this repo: middleware_personalizer.py, middleware_streaming_adaptation.py, middleware_geometry_gateway.py, middleware_mi_session.py, middleware_braindecode.py, middleware_reve.py, middleware_recommend_adapt.py.
Bench EEGNet demo (repo-only, needs nimbusbench[dl]): nimbusbench/scripts/middleware_eegnet.py.

When to adapt (thin helper)

Optional mean-shift check before spending labels on partial_fit. You choose the threshold tau.

dec = adapter.recommend_adapt(X_stream, tau=your_tau)  # stay vs stream update
if dec.should_adapt:
    adapter.partial_fit(X_lab, y_lab)

Trial rejection (BrainState.rejected / need_more_data) is a different gate — accept/reject the intent for the app.
Details: BrainState · recipe: examples/middleware_recommend_adapt.py.

A governed adaptation session — drift gates, label budgets, quarantine, and rollback — is under research and will ship as a separate release once its evidence matures.

Classical heads (CSP / features)

Same Bayesian heads without an encoder — inputs are already features:

from nimbus_bci import NimbusLDA

clf = NimbusLDA()
clf.fit(X_train, y_train)
proba = clf.predict_proba(X_test)
clf.partial_fit(X_new, y_new)

Also: streaming (StreamingSession), active learning (CalibrationSession), MNE helpers, optional Riemann pipelines. See docs.nimbusbci.com and examples/e2e_mne_csp_nimbus.py.

Head Role
NimbusLDA / NimbusQDA Conjugate Bayesian LDA/QDA
NimbusSoftmax Polya–Gamma VI (optional JAX)
NimbusSTS EKF latent-state / drift (EKF on z; point W/H/b)

Working with precomputed embeddings

If your pipeline already computed embeddings — frozen backbone → per-trial embeddings (N, F) — declare the contract so the Personalizer consumes X directly instead of re-encoding it through the attached trunk:

from nimbus_bci import Personalizer, wrap

adapter = Personalizer(
    encoder=wrap(module),        # attached for model_id / lineage — never called
    x_kind="embeddings",         # every X below is ALREADY the encoder output
    head="softmax",
    classes=["left", "right"],
)
adapter.fit(Z_cal, y_cal)                        # (N, F) — head + transforms fit directly
adapter.partial_fit(Z_stream, y_stream)          # online head updates
adapter.adapt(Z_stream, y_stream, level="head")  # supervised head adaptation

The rule: trunk adaptation needs raw encoder inputs. LoRA / BaLoRA / fine-tuning backpropagate through the trunk, and precomputed embeddings have no gradient path to trunk weights — so adapt(..., level="trunk"), adapt_trunk(...), adapt_async(...), fit_tent(...), trunk MC sampling, and Riemannian reference tracking (update_riemann_reference(...)) raise PersonalizerInputError under x_kind="embeddings". To adapt the trunk, feed raw epochs with the default x_kind="epochs". x_kind="embeddings" with encoder=None is also legal — that is the classical feature-space flow (Personalizer.for_features(...)).

Profiles round-trip the contract: export_profile() records x_kind and the observed embed_dim in UserProfile.meta; from_profile(...) restores them, refuses an x_kind mismatch, and validates the feature dim of the next fit against the recorded embed_dim.

Evidence

Public Personalizer story (heads, cost vs fine-tune, multi-trunk / REVE):
Evidence · Overview.

License

Two-track proprietary license — see the LICENSE.txt shipped with the package (and on PyPI). Non-commercial use is free under the Non-Commercial terms; commercial use requires a paid license. Contact: hello@nimbusbci.com.

Contributing & security

Licensees with source access: follow the repository CONTRIBUTING.md and SECURITY.md. Report vulnerabilities privately to hello@nimbusbci.com — do not open a public issue.

Metadata

Release files for nimbus-bci 0.7.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nimbus-bci 0.7.1
File Size Uploaded Provenance
nimbus_bci-0.7.1.tar.gz 1.3 MB Without provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for nimbus-bci 0.7.1
File
nimbus_bci-0.7.1-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
nimbus_bci-0.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
nimbus_bci-0.7.1-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
nimbus_bci-0.7.1-cp313-cp313-macosx_10_13_x86_64.whl CPython 3.13 CPython 3.13 macOS 10.13+ x86-64 Details
nimbus_bci-0.7.1-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
nimbus_bci-0.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
nimbus_bci-0.7.1-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
nimbus_bci-0.7.1-cp312-cp312-macosx_10_13_x86_64.whl CPython 3.12 CPython 3.12 macOS 10.13+ x86-64 Details
nimbus_bci-0.7.1-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
nimbus_bci-0.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
nimbus_bci-0.7.1-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
nimbus_bci-0.7.1-cp311-cp311-macosx_10_9_x86_64.whl CPython 3.11 CPython 3.11 macOS 10.9+ x86-64 Details

Total release size: 20.5 MB

Release files / nimbus_bci-0.7.1.tar.gz

Download URL nimbus_bci-0.7.1.tar.gz
Size 1.3 MB
Tags Source
SHA-256 checksum
How to use checksums
4ec666ca4c38a5080a4afbaf8aa3abaa80be12894c48780596bfbebc5edadb84
BLAKE2b-256 checksum
How to use checksums
81c41d28fa20304d489418cf4b4a2dcbed2b23b45402e2e050e32726f64f3549
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp313-cp313-win_amd64.whl

Download URL nimbus_bci-0.7.1-cp313-cp313-win_amd64.whl
Size 832.3 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
2002414ee3de67ca379072ff1321b512810a42b6c1c7a90105b4906577c1ed83
BLAKE2b-256 checksum
How to use checksums
f980f402f5d909aea19fee1e7adea6a803b1c302c06445d3ccfb93a90fc4a8c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL nimbus_bci-0.7.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 3.7 MB
Tags CPython 3.13 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
c21f0216cd8347e9b623eed0cc0ee26f1c65850355b9e1822d6414e1f66c0faf
BLAKE2b-256 checksum
How to use checksums
acfa3fa4551ae5a516a56f45d4fa75454c0e37f6d7cedd0a6e2ef0df9ed280b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp313-cp313-macosx_11_0_arm64.whl

Download URL nimbus_bci-0.7.1-cp313-cp313-macosx_11_0_arm64.whl
Size 908.8 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
ae97f8634991f8f918b8bd18522ca4489f52c8505f51adc340b851e1e00c4a10
BLAKE2b-256 checksum
How to use checksums
8f44ef2818cd91655cc49af13ca060997fe1a7a72b6fedad318d1070b2c6b56d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp313-cp313-macosx_10_13_x86_64.whl

Download URL nimbus_bci-0.7.1-cp313-cp313-macosx_10_13_x86_64.whl
Size 917.5 kB
Tags CPython 3.13 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
f4cb0e4a0617e5081061123fe9e2ba8acdc236dd2c80b392f74f989eeefc1f54
BLAKE2b-256 checksum
How to use checksums
cb1320d620c47d14c253b4d31c05d39d26ace3d4ffe813c5ab6c2eb589ec58e7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp312-cp312-win_amd64.whl

Download URL nimbus_bci-0.7.1-cp312-cp312-win_amd64.whl
Size 836.4 kB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
b4ef171e312d3b6e2b64be13264320ceb9be6fc42b26428e5ea3c8ae005e0b90
BLAKE2b-256 checksum
How to use checksums
a5fd1f471a7978cc8f1c8d4892fb40f7dddbf2d4255b9f22b21964748a82dd8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL nimbus_bci-0.7.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 3.7 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
59028bd7f544e98cc756b5c139ad81d5162b70a631c4a0e6b876a131b96100bd
BLAKE2b-256 checksum
How to use checksums
c9e248b9bdc150c839162d4ae2de6bfac0e4ba23b0be44896fc705f50f6c60f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp312-cp312-macosx_11_0_arm64.whl

Download URL nimbus_bci-0.7.1-cp312-cp312-macosx_11_0_arm64.whl
Size 913.4 kB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
57b90bad333061151bc22cd78ade0df5fddf5456be2226634a9ed6b682555a86
BLAKE2b-256 checksum
How to use checksums
52f75668bcda68bf49740bfb989de1f8e26c18162faeadcecbfe7ca69dade50f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp312-cp312-macosx_10_13_x86_64.whl

Download URL nimbus_bci-0.7.1-cp312-cp312-macosx_10_13_x86_64.whl
Size 920.6 kB
Tags CPython 3.12 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
63db0bf2d03109db5ecd1bffa9eadbec74938a6894d4582a8685bdaab8f2988b
BLAKE2b-256 checksum
How to use checksums
af6e56673eb070c16ab135f5b1c6363f57e4b1531dad0b0cc33a99b2954b30cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp311-cp311-win_amd64.whl

Download URL nimbus_bci-0.7.1-cp311-cp311-win_amd64.whl
Size 856.6 kB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
afcdb9e95475b17413937020da68235f663df16522f37b4f5601ba62723452e8
BLAKE2b-256 checksum
How to use checksums
c3bfa75852aa0988e9e3e0955c41920bb35f2228285f98389f9f1f1f6fcbb943
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL nimbus_bci-0.7.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 3.7 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
334219f0a68e192116c5f3df18ca7dc8fc6afe03e982c5e8c1193ae7b9919d9a
BLAKE2b-256 checksum
How to use checksums
d32a29a75a44b4278642d6abfe7b7f32ce6534091cd76d230498318b0747a676
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp311-cp311-macosx_11_0_arm64.whl

Download URL nimbus_bci-0.7.1-cp311-cp311-macosx_11_0_arm64.whl
Size 912.7 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
59c4c08a2a328d3b11a360fd62d63265a518ab210484bcd571bb2b77ed164760
BLAKE2b-256 checksum
How to use checksums
4cdaf759d98ed18005edfff15e4706772a8c78f593d933ee73a054880117a94b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / nimbus_bci-0.7.1-cp311-cp311-macosx_10_9_x86_64.whl

Download URL nimbus_bci-0.7.1-cp311-cp311-macosx_10_9_x86_64.whl
Size 939.1 kB
Tags CPython 3.11 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
c2f5a5142958298e0479575c6cf7527c790574f7065329beb551d8f3b0bee18f
BLAKE2b-256 checksum
How to use checksums
ffb09aa629c633c8996c4deddc4b84a52068d159f629866320f4c76acbbb4557
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for nimbus-bci 0.7.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page