Skip to main content

Development Guide

This guide covers project organization and production workflow. It does not repeat SDK installation or full examples; use the linked pages for those details. Keep acquisition, preprocessing / encoding, personalization, and application logic separate. That makes it easier to test each stage and swap trunks, heads, or SDKs later.

Development Workflow

  1. Define the BCI paradigm: motor imagery, P300, SSVEP, or another task.
  2. Lock the input contract: frozen encoder (model_id, embedding_dim) or classical feature type, sampling rate, channels, window, normalization.
  3. Fit a baseline: start with Personalizer(head="lda") on embeddings, or NimbusLDA on classical features; compare heads only if the baseline fails.
  4. Evaluate offline: use held-out sessions / CV before streaming; inspect BrainState gating.
  5. Add streaming: process embedding or feature chunks and aggregate trial decisions.
  6. Add safety policy: reject low confidence / high uncertainty (need_more_data) and log decisions.
  7. Deploy with monitoring: track latency, confidence, rejection rate, and drift.

Data Contracts

Document these invariants in your project:

Model Lifecycle

Treat a deployed model as more than weights. Save:
  • model object or model identifier
  • SDK version
  • feature extraction settings
  • normalization parameters
  • class labels and label mapping
  • training session metadata
  • validation metrics
Example metadata (Personalizer profile):
Classical-head metadata can still use "model": "NimbusLDA" + "feature_type": "csp". Persist Personalizer.save(...) profiles separately from the frozen trunk weights.

Testing Strategy

Prioritize small tests around contracts and failure modes:
  • Encoder / preprocessing output has expected shape and finite values.
  • Labels match the number of trials.
  • Normalization params are reused, not recomputed on test data.
  • Personalizer rejects incompatible embedding_dim / model_id on load.
  • Streaming chunks match chunk_size.
  • Low-confidence / high-uncertainty BrainState triggers the expected safety path.
For numerical tests, avoid hardcoding exact posteriors unless the model is fully deterministic. Prefer shape, range, monotonicity, and threshold checks.

Debugging Checklist

When accuracy or confidence is poor:
  1. Confirm data shape and label encoding.
  2. Check for NaN, Inf, constant features, logits passed as embeddings, or raw EEG as features.
  3. Verify the encode contract or preprocessing band / time window match the paradigm.
  4. Reuse training normalization parameters on test data.
  5. Compare against Personalizer(head="lda") / NimbusLDA as a baseline.
  6. Inspect BrainState confidence, uncertainty, and need_more_data, not only accuracy.
  7. Run preprocessing diagnostics before tuning model hyperparameters.

Performance Guidance

  • Warm up streaming inference before a live session.
  • Preallocate buffers in real-time loops.
  • Keep filtering and feature extraction outside hot model code when possible.
  • Prefer batch inference for offline evaluation.
  • Log per-stage latency: acquisition, preprocessing, inference, and application action.

Production Guardrails

Production BCI systems should include:
  • confidence thresholds by action risk
  • trial rejection and retry flows
  • session-level health monitoring
  • model/version audit logs
  • fallback behavior when the stream drops
  • clear separation between prediction and command execution
See Error Handling for a focused checklist.

Next Read

External Preprocessing Integration

Export/import handoff from MNE, EEGLAB, OpenViBE, or MATLAB.

Feature Normalization

Cross-session scaling strategy.

Streaming Configuration

Chunking, aggregation, and quality gates.

Model Specification

Choose the right model family.