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.3

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.3
File Size Uploaded Provenance
nimbus_bci-0.7.3.tar.gz 1.3 MB Without provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for nimbus-bci 0.7.3
File
nimbus_bci-0.7.3-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
nimbus_bci-0.7.3-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.3-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
nimbus_bci-0.7.3-cp313-cp313-macosx_10_13_x86_64.whl CPython 3.13 CPython 3.13 macOS 10.13+ x86-64 Details
nimbus_bci-0.7.3-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
nimbus_bci-0.7.3-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.3-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
nimbus_bci-0.7.3-cp312-cp312-macosx_10_13_x86_64.whl CPython 3.12 CPython 3.12 macOS 10.13+ x86-64 Details
nimbus_bci-0.7.3-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
nimbus_bci-0.7.3-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.28+ x86-64, Linux glibc 2.17+ x86-64 Details
nimbus_bci-0.7.3-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
nimbus_bci-0.7.3-cp311-cp311-macosx_10_9_x86_64.whl CPython 3.11 CPython 3.11 macOS 10.9+ x86-64 Details

Total release size: 20.6 MB

Release files / nimbus_bci-0.7.3.tar.gz

Download URL nimbus_bci-0.7.3.tar.gz
Size 1.3 MB
Tags Source
SHA-256 checksum
How to use checksums
469f773aa39e0a5bca27aa965374fab759f7c849c47e8b9eceec9b2d2e241772
BLAKE2b-256 checksum
How to use checksums
7c494c4e37397066432843a56fa2c24c83649d8e4642f923719e9bef1c897fba
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.3-cp313-cp313-win_amd64.whl

Download URL nimbus_bci-0.7.3-cp313-cp313-win_amd64.whl
Size 840.7 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
57c669952ceebd8b1222b8d56fda7b2eafe0cb15a917c3de07b41a96545dbeb7
BLAKE2b-256 checksum
How to use checksums
1f82d08022c23d5c6572ccb27d8e8c9dc27699a29addaef1b505f48d5eecc712
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.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL nimbus_bci-0.7.3-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
26fb3aa84d0a42d2cd7426592f5030d870b6f68bee4bd4a818918837e6383b45
BLAKE2b-256 checksum
How to use checksums
2a1f6213c6020af9a1c493e4612e650cf479b62bc7670e1668fca8e530133677
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.3-cp313-cp313-macosx_11_0_arm64.whl

Download URL nimbus_bci-0.7.3-cp313-cp313-macosx_11_0_arm64.whl
Size 917.1 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
8165146f1b9f9807d67e74ccfd0a3d15b22552d58f0f7ae83d5e585949b0ef39
BLAKE2b-256 checksum
How to use checksums
03624b0965a061702c7676ab8a0ea707e76127bcb4f62a2bcee6c10f48e20903
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.3-cp313-cp313-macosx_10_13_x86_64.whl

Download URL nimbus_bci-0.7.3-cp313-cp313-macosx_10_13_x86_64.whl
Size 925.7 kB
Tags CPython 3.13 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
02d22637389b9886b0751beb466585272b649cb5f55f7e17c81a936c84043d7a
BLAKE2b-256 checksum
How to use checksums
022b1ee26fb5b1c619d134a52d50b50ee0be0cf90c97b3be6749c839d36cc2f3
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.3-cp312-cp312-win_amd64.whl

Download URL nimbus_bci-0.7.3-cp312-cp312-win_amd64.whl
Size 844.7 kB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
83a08287d0adc89ae6112251c4472897467c1207d4b3c6ad1917d074b83c8875
BLAKE2b-256 checksum
How to use checksums
a4f6dba4157f81b4635e835b4ed54d95d3330758cefa582d9db2009c733222e4
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.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL nimbus_bci-0.7.3-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
d1b40a449999eb6c1241dd97ebb02af9bb2dec04b60be6e5118d687995845436
BLAKE2b-256 checksum
How to use checksums
a8dd63f2ddddf3d2fff2bf9663095f6b21154d05e0be4fbdae20fd0f429816a4
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.3-cp312-cp312-macosx_11_0_arm64.whl

Download URL nimbus_bci-0.7.3-cp312-cp312-macosx_11_0_arm64.whl
Size 921.6 kB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
23857e24e5f52dcd94dc6276b750f20219558a9a0e4b4e9c50c5e30c108b9c2b
BLAKE2b-256 checksum
How to use checksums
d3ede81b04293f1f52f6a5ed72d93b12768ca8c96051e30e1bee40bbc22e207b
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.3-cp312-cp312-macosx_10_13_x86_64.whl

Download URL nimbus_bci-0.7.3-cp312-cp312-macosx_10_13_x86_64.whl
Size 928.9 kB
Tags CPython 3.12 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
76b78e09b1f7d4510598be4f084daeb0dcece3d9a8e7204881611fb5f37be45f
BLAKE2b-256 checksum
How to use checksums
c62f5632c2c8b4c30139187eac44569f6795325b19546655339f51815a1607fa
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.3-cp311-cp311-win_amd64.whl

Download URL nimbus_bci-0.7.3-cp311-cp311-win_amd64.whl
Size 865.0 kB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
1a06ee77a52eaae3fe9979197d5ec63a44f46c4db7fecb6f27bc7a53d1b3a1c9
BLAKE2b-256 checksum
How to use checksums
585edd12152d382e3a299a9298087b97466630b04856b4268b02e68ee7e0fdca
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.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL nimbus_bci-0.7.3-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
5d950c3621d2244ff9e3141a6a1d0895f2cd79eb9c9dbc5c9c524c698467c2c7
BLAKE2b-256 checksum
How to use checksums
aaf672f2952eeaaee811d61be520865bfc4057c1b584a0245ddd5599fa4e25a8
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.3-cp311-cp311-macosx_11_0_arm64.whl

Download URL nimbus_bci-0.7.3-cp311-cp311-macosx_11_0_arm64.whl
Size 920.9 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9f1ed0a4b2c388b9fd3ece67376ea7de5ac1688ea1501737c1ac9d9a432a9c29
BLAKE2b-256 checksum
How to use checksums
680c3548d10faa3f5bf146eedcae56cfd35ce7623b68115cb008c35afe8f4bef
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.3-cp311-cp311-macosx_10_9_x86_64.whl

Download URL nimbus_bci-0.7.3-cp311-cp311-macosx_10_9_x86_64.whl
Size 947.4 kB
Tags CPython 3.11 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
c571d6592d1eed3ba430b3beed4da8b5162c6fef826d1f15a7dca6b37a26383c
BLAKE2b-256 checksum
How to use checksums
005086cd225e04828426d889cf37d418294f658fcf537cfee1cbae7a3e987d00
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.3

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