Metadata-Version: 2.4
Name: nimbus-bci
Version: 0.4.0
Summary: Nimbus BCI: Bayesian classifiers for brain-computer interfaces
Author-email: "Nimbus BCI Inc." <hello@nimbusbci.com>
License: NIMBUS PYSDK SOFTWARE LICENSE AGREEMENT
        
        Copyright (c) 2024-2025 Nimbus BCI Inc.
        All rights reserved.
        
        ================================================================================
        PROPRIETARY SOFTWARE LICENSE
        ================================================================================
        
        This software and associated documentation files (the "Software") are the
        proprietary and confidential property of Nimbus BCI Inc. ("Nimbus BCI").
        
        NOTICE: This Software is protected by copyright laws and international treaty
        provisions. Unauthorized reproduction, distribution, modification, public
        display, or public performance of this Software is strictly prohibited and
        may result in severe civil and criminal penalties.
        
        ================================================================================
        LICENSE GRANT
        ================================================================================
        
        Subject to the terms of this Agreement and payment of applicable fees, Nimbus
        BCI grants you a limited, non-exclusive, non-transferable, revocable license
        to use the Software solely in accordance with your purchased license tier.
        
        ================================================================================
        LICENSE TIERS
        ================================================================================
        
        1. EVALUATION LICENSE (30 Days)
           ------------------------------------------------------------------------
           - Free evaluation for research and development purposes
           - Limited to non-production use
           - No commercial deployment permitted
           - Expires 30 days from first use
        
        2. ACADEMIC LICENSE (Free)
           ------------------------------------------------------------------------
           - FREE for accredited academic institutions and non-profit research
           - For non-commercial research and educational purposes only
           - Requires proof of academic affiliation (.edu email or institution letter)
           - May not be used for commercial products or services
           - Attribution required: cite Nimbus BCI Inc. in publications
        
        3. STARTUP LICENSE
           ------------------------------------------------------------------------
           - For companies with less than $1M annual revenue
           - Single product use
           - Standard support via email
        
        4. COMMERCIAL LICENSE
           ------------------------------------------------------------------------
           - Full production rights for commercial applications
           - Unlimited products within licensed organization
           - Priority technical support
           - Custom integration assistance available
        
        5. ENTERPRISE LICENSE
           ------------------------------------------------------------------------
           - Unlimited deployments across organization
           - Dedicated support with SLA guarantees
           - On-premise deployment options
           - Custom feature development
           - Training and onboarding included
        
        6. OEM / EMBEDDED LICENSE
           ------------------------------------------------------------------------
           - For medical devices and embedded systems
           - FDA regulatory compliance documentation package
           - White-label and redistribution rights
           - Extended warranty and indemnification options
           - Design review and integration support
        
        For all licensing inquiries, contact: hello@nimbusbci.com
        
        ================================================================================
        RESTRICTIONS
        ================================================================================
        
        You may NOT:
        
        1. Copy, modify, adapt, translate, or create derivative works of the Software
        
        2. Reverse engineer, disassemble, decompile, or attempt to discover the source
           code or underlying algorithms of the Software
        
        3. Rent, lease, loan, sublicense, distribute, or transfer the Software to any
           third party
        
        4. Remove, alter, or obscure any proprietary notices, labels, or marks on the
           Software
        
        5. Use the Software to develop competing products or services
        
        6. Use the Software in any manner that violates applicable laws or regulations
        
        7. Use the Software for any life-critical, safety-critical, or medical
           diagnostic purposes without appropriate regulatory clearances and a valid
           OEM/Embedded License
        
        8. Share, publish, or expose API keys, license keys, or authentication
           credentials
        
        ================================================================================
        INTELLECTUAL PROPERTY
        ================================================================================
        
        The Software, including all algorithms, methods, designs, and implementations,
        is and shall remain the exclusive property of Nimbus BCI Inc. This Agreement
        does not transfer any ownership rights to you.
        
        The Software contains proprietary Bayesian inference algorithms including but
        not limited to:
        - Bayesian Linear Discriminant Analysis (LDA) with conjugate priors
        - Bayesian Gaussian Mixture Models (GMM/QDA)
        - Polya-Gamma Variational Inference for Softmax Regression
        - Real-time streaming inference methods
        - Online learning and model adaptation techniques
        
        These algorithms constitute valuable trade secrets of Nimbus BCI Inc.
        
        ================================================================================
        CONFIDENTIALITY
        ================================================================================
        
        You acknowledge that the Software contains confidential and proprietary
        information. You agree to:
        
        1. Maintain the confidentiality of the Software
        2. Use at least the same degree of care to protect the Software as you use
           to protect your own confidential information
        3. Not disclose the Software or any information derived from it to third
           parties without prior written consent from Nimbus BCI
        
        ================================================================================
        DATA PRIVACY
        ================================================================================
        
        The Software processes all EEG and neurophysiological data locally on your
        systems. Nimbus BCI does not collect, store, or have access to your research
        data or subject data processed through the Software.
        
        The Software may transmit the following to Nimbus BCI servers:
        - License key validation requests
        - Aggregated usage metrics (inference counts, feature usage)
        - Software version and platform information for compatibility
        
        ================================================================================
        WARRANTY DISCLAIMER
        ================================================================================
        
        THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
        
        NIMBUS BCI DOES NOT WARRANT THAT:
        - The Software will meet your specific requirements
        - The Software will be uninterrupted, timely, secure, or error-free
        - The results obtained from the Software will be accurate or reliable
        - Any errors in the Software will be corrected
        
        ================================================================================
        MEDICAL DEVICE DISCLAIMER
        ================================================================================
        
        IMPORTANT: THE SOFTWARE IS NOT A MEDICAL DEVICE.
        
        The Software has NOT been cleared or approved by the U.S. Food and Drug
        Administration (FDA), European Medicines Agency (EMA), or any other regulatory
        body for use as a medical device.
        
        The Software is intended for RESEARCH AND DEVELOPMENT PURPOSES ONLY and must
        NOT be used for:
        - Clinical diagnosis or treatment of patients
        - Medical decision-making or patient care
        - Any application where failure could result in death or personal injury
        
        Use of the Software for medical or clinical purposes requires:
        - Appropriate regulatory clearances (510(k), CE Mark, etc.)
        - A valid OEM/Embedded License with regulatory support package
        - Independent validation and verification
        
        ================================================================================
        LIMITATION OF LIABILITY
        ================================================================================
        
        TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW:
        
        IN NO EVENT SHALL NIMBUS BCI INC., ITS AFFILIATES, OFFICERS, DIRECTORS,
        EMPLOYEES, OR AGENTS BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
        CONSEQUENTIAL, OR PUNITIVE DAMAGES, INCLUDING BUT NOT LIMITED TO:
        
        - Loss of profits, revenue, or business opportunities
        - Loss of data or research results
        - Business interruption
        - Cost of substitute goods or services
        
        WHETHER ARISING FROM CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY, OR ANY
        OTHER LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
        
        NIMBUS BCI'S TOTAL AGGREGATE LIABILITY SHALL NOT EXCEED THE GREATER OF:
        - The fees paid by you in the 12 months preceding the claim, OR
        - One Hundred U.S. Dollars ($100)
        
        ================================================================================
        TERM AND TERMINATION
        ================================================================================
        
        This license is effective until terminated. Nimbus BCI may terminate this
        license immediately if you breach any term of this Agreement.
        
        Upon termination:
        1. You must cease all use of the Software
        2. You must destroy all copies of the Software in your possession
        3. You must certify in writing that you have complied with these requirements
        
        Sections regarding Intellectual Property, Confidentiality, Warranty Disclaimer,
        Limitation of Liability, and Governing Law shall survive termination.
        
        ================================================================================
        GOVERNING LAW AND JURISDICTION
        ================================================================================
        
        This Agreement shall be governed by and construed in accordance with the laws
        of the State of Delaware, United States, without regard to its conflict of
        laws principles.
        
        Any disputes arising under this Agreement shall be resolved exclusively in
        the state or federal courts located in Delaware. You consent to the personal
        jurisdiction of such courts.
        
        ================================================================================
        EXPORT COMPLIANCE
        ================================================================================
        
        The Software may be subject to U.S. export control laws and regulations. You
        agree to comply with all applicable export laws and not to export or re-export
        the Software to any prohibited countries, entities, or persons.
        
        ================================================================================
        ENTIRE AGREEMENT
        ================================================================================
        
        This Agreement constitutes the entire agreement between you and Nimbus BCI
        regarding the Software and supersedes all prior agreements, understandings,
        and communications.
        
        No modification of this Agreement shall be effective unless in writing and
        signed by an authorized representative of Nimbus BCI.
        
        ================================================================================
        CONTACT INFORMATION
        ================================================================================
        
        Nimbus BCI Inc.
        588 El Camino Real
        Santa Clara, CA 95050
        United States
        
        Email: hello@nimbusbci.com
        Website: https://nimbusbci.com
        Documentation: https://docs.nimbusbci.com
        
        ================================================================================
        
        By using the Software, you acknowledge that you have read this Agreement,
        understand it, and agree to be bound by its terms and conditions.
        
        ================================================================================
        
        Last Updated: December 2025
        Version: 1.0
        
        © 2024-2025 Nimbus BCI Inc. All rights reserved.
        
        
        
Project-URL: Homepage, https://nimbusbci.com
Project-URL: Documentation, https://docs.nimbusbci.com
Project-URL: Repository, https://github.com/nimbusbci/nimbuspysdk
Project-URL: Issues, https://github.com/nimbusbci/nimbuspysdk/issues
Keywords: bci,eeg,machine-learning,bayesian,classification,sklearn
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: numpy>=1.26
Requires-Dist: scikit-learn>=1.4
Requires-Dist: scipy>=1.17.1
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: python-dateutil>=2.9.0; extra == "dev"
Requires-Dist: Cython>=3.0; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Provides-Extra: viz
Requires-Dist: matplotlib>=3.8; extra == "viz"
Provides-Extra: mne
Requires-Dist: mne>=1.6; extra == "mne"
Provides-Extra: softmax
Requires-Dist: jax>=0.4.25; extra == "softmax"
Provides-Extra: all
Requires-Dist: matplotlib>=3.8; extra == "all"
Requires-Dist: mne>=1.6; extra == "all"
Requires-Dist: scipy>=1.17.1; extra == "all"
Requires-Dist: jax>=0.4.25; extra == "all"
Dynamic: license-file

# nimbus-bci

Bayesian BCI classifiers with **sklearn compatibility**, **streaming inference**, **active-learning calibration loops**, and **rich diagnostics**.

[PyPI](https://pypi.org/project/nimbus-bci/)
[Python](https://pypi.org/project/nimbus-bci/)
[License](LICENSE.txt)

**Documentation in this repo:** [Why Nimbus? (vs sklearn / pyRiemann)](docs/why_nimbus.md) · [Trust, calibration, and rejection](docs/trust_and_calibration.md) · [Active-learning calibration loops](docs/active_learning.md) — cut calibration time with BALD ranking and label-free stopping. Hosted docs: [docs.nimbusbci.com](https://docs.nimbusbci.com).

## Features

- **Four sklearn-compatible classifiers**: three static Bayesian decoders — **LDA**, **QDA**, **Softmax** (Polya–Gamma) — plus **NimbusSTS** for latent-state / non-stationary settings (EKF-style updates, experimental)
- **sklearn-compatible API**: Works with pipelines, cross-validation, and GridSearchCV
- **Streaming inference**: Real-time chunk-by-chunk processing
- **Active learning**: `suggest_next_trial` (BALD on LDA/QDA/Softmax), `should_query` streaming gate, and label-free `calibration_sufficient` stopping — cut cued calibration time without manual heuristics
- **Rich diagnostics**: Entropy, Mahalanobis distance, calibration metrics (ECE/MCE)
- **Online learning**: Update models with new data without retraining
- **BCI-specific utilities**: ITR calculation, temporal aggregation, quality assessment
- **MNE-Python integration**: Convert between MNE Epochs and Nimbus data formats

## Installation

```bash
pip install nimbus-bci
```

To use the optional JAX-based softmax model:

```bash
pip install nimbus-bci[softmax]
```

**From source:**

```bash
git clone https://github.com/nimbusbci/nimbuspysdk.git
cd nimbuspysdk
pip install -e ".[all]"
```

## Quick Start

### sklearn-Compatible API (Recommended)

```python
from nimbus_bci import NimbusLDA, NimbusQDA, NimbusSoftmax, NimbusSTS
import numpy as np

# Create and fit classifier
clf = NimbusLDA()
clf.fit(X_train, y_train)

# Predict
predictions = clf.predict(X_test)
probabilities = clf.predict_proba(X_test)

# Online learning
clf.partial_fit(X_new, y_new)
```

### Works with sklearn Pipelines

```python
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import cross_val_score, GridSearchCV

# Simple pipeline
pipe = make_pipeline(StandardScaler(), NimbusLDA())
pipe.fit(X_train, y_train)

# Cross-validation
scores = cross_val_score(NimbusLDA(), X, y, cv=5)
print(f"Accuracy: {scores.mean():.2%} (+/- {scores.std():.2%})")

# Hyperparameter tuning
param_grid = {'mu_scale': [1.0, 3.0, 5.0], 'class_prior_alpha': [0.5, 1.0]}
grid = GridSearchCV(NimbusLDA(), param_grid, cv=5)
grid.fit(X, y)
print(f"Best params: {grid.best_params_}")
```

### Streaming Inference (Real-Time BCI)

```python
from nimbus_bci import NimbusLDA, StreamingSession
from nimbus_bci.data import BCIMetadata

# Setup
metadata = BCIMetadata(
    sampling_rate=250.0,
    paradigm="motor_imagery",
    feature_type="csp",
    n_features=16,
    n_classes=4,
    chunk_size=125,  # 500ms chunks
    temporal_aggregation="logvar",
)

# Train model
clf = NimbusLDA()
clf.fit(X_train, y_train)

# Create streaming session
session = StreamingSession(clf.model_, metadata)

# Process chunks in real-time
for chunk in eeg_stream:
    result = session.process_chunk(chunk)
    print(f"Chunk prediction: {result.prediction} ({result.confidence:.2%})")

# Finalize trial with aggregation
final = session.finalize_trial(method="weighted_vote")
print(f"Final: class {final.prediction} (entropy: {final.entropy:.2f} bits)")
```

For **NimbusSTS** specifically (stateful latent dynamics), use `StreamingSessionSTS`
so the latent state can be propagated and updated with delayed feedback:

```python
from nimbus_bci import NimbusSTS
from nimbus_bci.inference import StreamingSessionSTS
from nimbus_bci.data import BCIMetadata

metadata = BCIMetadata(
    sampling_rate=250.0,
    paradigm="motor_imagery",
    feature_type="csp",
    n_features=16,
    n_classes=2,
    chunk_size=125,
    temporal_aggregation="mean",
)

clf = NimbusSTS().fit(X_train, y_train)
session = StreamingSessionSTS(clf, metadata)

result = session.process_chunk(chunk)  # propagates state by default
session.provide_feedback(label=0)      # when label arrives later
```

### Active Learning (Calibration Loop)

Cut cued-calibration time by labeling only the trials the model is genuinely uncertain about, and stop automatically when the posterior settles:

```python
from nimbus_bci import NimbusLDA
from nimbus_bci.active_learning import (
    suggest_next_trial,
    calibration_sufficient,
)

clf = NimbusLDA().fit(X_seed, y_seed)   # small initial cued batch
prev = clf.get_model()

for _ in range(max_rounds):
    # Rank the unlabeled pool by BALD informativeness, label the top 4.
    ranked = suggest_next_trial(
        clf, X_pool, strategy="bald", n=4, num_posterior_samples=64,
    )
    X_new, y_new = collect_labels_for(ranked.indices)   # cue + record
    clf.partial_fit(X_new, y_new)

    # Label-free stopping: when predict_proba over the pool stops moving,
    # more cues will not change predictions much.
    status = calibration_sufficient(
        clf, X_pool,
        criterion="posterior_stability",
        previous=prev, threshold=0.02,
    )
    if status.is_sufficient:
        break
    prev = clf.get_model()
```

Strategies (`entropy`, `margin`, `least_confidence`, `bald`) and stopping criteria (`posterior_stability`, `expected_info_gain`) are all model-agnostic. STS gets `posterior_stability` for free; BALD-based features on STS are deferred to v1.1. Full recipe in [docs/active_learning.md](docs/active_learning.md).

### Batch Inference with Diagnostics

```python
from nimbus_bci import predict_batch
from nimbus_bci.data import BCIData, BCIMetadata

# Create BCI data container
metadata = BCIMetadata(
    sampling_rate=250.0,
    paradigm="motor_imagery",
    feature_type="csp",
    n_features=16,
    n_classes=4,
)
data = BCIData(features, metadata, labels)

# Run batch inference with full diagnostics
result = predict_batch(model, data)

print(f"Mean entropy: {result.mean_entropy:.2f} bits")
print(f"Balance: {result.balance:.2%}")
if result.calibration is not None:
    print(f"ECE: {result.calibration.ece:.3f}")
print(f"Latency: {result.latency_ms:.1f}ms")
```

### MNE-Python Integration

```python
import mne
from nimbus_bci import NimbusLDA
from nimbus_bci.compat import from_mne_epochs, extract_csp_features

# Load and preprocess with MNE
raw = mne.io.read_raw_gdf("motor_imagery.gdf")
events = mne.find_events(raw)
epochs = mne.Epochs(raw, events, tmin=0, tmax=4, baseline=None, preload=True)
epochs.filter(8, 30)  # Mu + Beta bands

# Extract CSP features
csp_features, csp = extract_csp_features(epochs, n_components=8)

# Train Nimbus classifier
clf = NimbusLDA()
clf.fit(csp_features, epochs.events[:, 2])
```

## Available Classifiers


| Classifier      | Description                                                            | Best For                                                          |
| --------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `NimbusLDA`     | Bayesian LDA with shared covariance                                    | Fast, when classes have similar shapes                            |
| `NimbusQDA`     | Bayesian QDA with class-specific covariances                           | Complex class distributions                                       |
| `NimbusSoftmax` | Bayesian logistic regression (Polya-Gamma VI)                          | Non-Gaussian decision boundaries                                  |
| `NimbusSTS`     | Structural time series classifier (latent state + EKF-style inference) | Non-stationary settings, drifting class boundaries (experimental) |


## Choosing the Right Classifier

### Quick Decision Guide

**Is your data stationary (distributions don't change over time)?**

- **Yes** → Use static models (LDA/QDA/Softmax)
- **No** → Use `NimbusSTS` for temporal adaptation

**For stationary data:**

- **Classes have similar covariance?** → `NimbusLDA` (fastest)
- **Classes have different shapes?** → `NimbusQDA`
- **Non-Gaussian boundaries?** → `NimbusSoftmax`

**For non-stationary data:**

- **Gradual drift (fatigue, electrode shift)?** → `NimbusSTS`
- **Multi-day sessions with state transfer?** → `NimbusSTS`
- **Delayed feedback paradigms?** → `NimbusSTS`

### Detailed Comparison


| Scenario                                              | Recommended Model                                | Why?                                                              |
| ----------------------------------------------------- | ------------------------------------------------ | ----------------------------------------------------------------- |
| **Stable offline datasets**                           | `NimbusLDA`                                      | Fastest, closed-form solution                                     |
| **P300 spelling (stable)**                            | `NimbusLDA` or `NimbusQDA`                       | Event-related, stationary                                         |
| **SSVEP**                                             | `NimbusLDA`                                      | Highly stationary frequency response                              |
| **Motor Imagery (short sessions)**                    | `NimbusLDA` or `NimbusQDA`                       | Stationary within session                                         |
| **Motor Imagery (long sessions, fatigue)**            | `NimbusSTS`                                      | Tracks drift due to fatigue                                       |
| **Multi-day experiments**                             | `NimbusSTS`                                      | State transfer across sessions                                    |
| **Electrode repositioning**                           | `NimbusSTS`                                      | Adapts to impedance changes                                       |
| **Closed-loop with delayed feedback**                 | `NimbusSTS`                                      | Explicit state propagation                                        |
| **Asynchronous BCI (idle vs active)**                 | `NimbusSTS`                                      | Models engagement state                                           |
| **Neurofeedback training**                            | `NimbusSTS`                                      | Tracks learning-induced changes                                   |
| **Long calibration sessions, want to cut label cost** | Any head + `suggest_next_trial(strategy="bald")` | Pool-based BALD on the conjugate posterior; LDA/QDA/Softmax in v1 |
| **Don't know when to stop calibrating**               | Any head + `calibration_sufficient`              | Label-free `posterior_stability` works for STS too                |


### NimbusSTS Example (Temporal Adaptation)

```python
from nimbus_bci import NimbusSTS

# Train on calibration data
clf = NimbusSTS(transition_cov=0.05, num_steps=50)
clf.fit(X_calibration, y_calibration)

# Online session with delayed feedback
for x_trial, y_feedback in online_trials:
    # 1. Propagate state forward (no label needed)
    clf.propagate_state()
    
    # 2. Make prediction
    prediction = clf.predict(x_trial)
    
    # ... user performs action, feedback arrives later ...
    
    # 3. Update with true label
    clf.partial_fit(x_trial, y_feedback)

# Multi-day state transfer
z_day1, P_day1 = clf.get_latent_state()

# Day 2: Initialize with Day 1 state (increased uncertainty)
clf_day2 = NimbusSTS()
clf_day2.fit(X_day2_calib, y_day2_calib)
clf_day2.set_latent_state(z_day1 * 0.5, P_day1 * 2.0)
```

## Label Conventions (Important)

Nimbus supports common EEG/BCI labeling patterns:

- **BCIData labels**: can be any **non-negative integer codes** (e.g., MNE event IDs like 769/770),
as long as the number of unique labels does not exceed `BCIMetadata.n_classes`.
- **sklearn estimators** (`NimbusLDA`, `NimbusQDA`, `NimbusSoftmax`, `NimbusSTS`):
  - `fit()` learns `classes_` from your provided labels.
  - `predict()` returns labels in the **original label space** (elements of `classes_`).
- **Model-snapshot inference** (`NimbusModel` + `predict_batch` / `StreamingSession`):
  - predictions are returned in the model’s **label_base** convention (`label_base` is stored in `model.params`).
  - use `nimbus_bci.data.labels_to_zero_indexed(...)` for metrics/aggregation that require 0-indexed labels.

## NimbusSTS Sequence Semantics (Important)

`NimbusSTS` has a latent state. For correctness and sklearn compatibility:

- `NimbusSTS.predict_proba(X)` treats rows as **conditionally independent** by default.
- For **time-ordered** evaluation, propagate explicitly:
  - call `clf.propagate_state()` between trials/chunks, or
  - use the functional API `nimbus_sts_predict_proba(model, X, evolve_state=True)` when `X` rows are ordered in time.

## Metrics & Diagnostics

```python
from nimbus_bci import (
    compute_entropy,            # Prediction uncertainty
    compute_calibration_metrics,  # ECE, MCE
    calculate_itr,              # Information Transfer Rate
    assess_trial_quality,       # Quality checks
)

# Entropy (uncertainty)
entropy = compute_entropy(posterior)  # bits

# Calibration
calib = compute_calibration_metrics(predictions, confidences, labels)
print(f"ECE: {calib.ece:.3f}, MCE: {calib.mce:.3f}")

# ITR
itr = calculate_itr(accuracy=0.85, n_classes=4, trial_duration=4.0)
print(f"ITR: {itr:.1f} bits/min")
```

## Normalization

Critical for cross-session BCI performance:

```python
from nimbus_bci import estimate_normalization_params, apply_normalization

# Estimate from training data
params = estimate_normalization_params(X_train, method="zscore")

# Apply to all data
X_train_norm = apply_normalization(X_train, params)
X_test_norm = apply_normalization(X_test, params)  # Same params!
```

## Project Structure

```
nimbus_bci/
├── models/              # Classifiers
│   ├── nimbus_lda/     # LDA (shared covariance)
│   ├── nimbus_qda/     # QDA (class-specific covariances)
│   └── nimbus_softmax/ # Softmax (Polya-Gamma)
├── data/               # Data contracts (BCIData, BCIMetadata)
├── inference/          # Batch and streaming inference
├── metrics/            # Diagnostics, calibration, ITR
├── utils/              # Normalization, aggregation
└── compat/             # sklearn/MNE compatibility
```

## Functional API (Backward Compatible)

The original functional API is still available:

```python
from nimbus_bci import (
    nimbus_lda_fit, nimbus_lda_predict, nimbus_lda_update,
    nimbus_qda_fit, nimbus_qda_predict,
    nimbus_softmax_fit, nimbus_softmax_predict,
    nimbus_save, nimbus_load,
)

# Fit model
model = nimbus_lda_fit(X, y, n_classes=4, label_base=0, ...)

# Predict
probs = nimbus_lda_predict_proba(model, X_test)

# Update (online learning)
model = nimbus_lda_update(model, X_new, y_new)

# Save/load
nimbus_save(model, "model.npz")
model = nimbus_load("model.npz")
```

## Testing

```bash
pip install -e ".[dev]"
pytest -v
```

## Requirements

**Core** (installed with `pip install nimbus-bci`):

- Python ≥ 3.11
- NumPy ≥ 1.26
- scikit-learn ≥ 1.4

**Optional extras:**

- **JAX** ≥ 0.4.25 — required for `NimbusSoftmax` and the softmax functional API (`pip install nimbus-bci[softmax]`)
- **MNE** ≥ 1.6 — EEG integration (`pip install nimbus-bci[mne]`)
- **matplotlib** ≥ 3.8 — visualization (`pip install nimbus-bci[viz]`)
- **SciPy** ≥ 1.12 — included in `pip install nimbus-bci[all]` alongside the extras above

## License

This software is **proprietary** and requires a valid license for use.

### License Tiers


| Tier             | Use Case                     |
| ---------------- | ---------------------------- |
| **Evaluation**   | 30-day free trial for R&D    |
| **Academic**     | University research (free)   |
| **Startup**      | Companies < $1M revenue      |
| **Commercial**   | Full production rights       |
| **Enterprise**   | Unlimited deployments + SLA  |
| **OEM/Embedded** | Medical devices, FDA support |


### Request Access

To obtain a license:

1. Email **[hello@nimbusbci.com](mailto:hello@nimbusbci.com)** with your use case
2. Receive API key and license agreement
3. Install and start building

**Website:** [https://nimbusbci.com](https://nimbusbci.com)

---

© 2024-2025 [Nimbus BCI Inc.](https://nimbusbci.com) — The AI Engine for Brain-Computer Interfaces
