Skip to main content

Get Started with Nimbus BCI

Build your first brain-computer interface application in just a few steps. This guide will take you from setup to running inference on neural data in under 10 minutes.

Prerequisites

Before you begin, make sure you have:
  • Julia 1.9+ installed on your system
  • Basic understanding of EEG data and BCI concepts
  • Preprocessed features (CSP, bandpower, etc.) - see preprocessing requirements
Important: NimbusSDK.jl expects preprocessed features, not raw EEG data. You must apply bandpass filtering, artifact removal, and feature extraction (e.g., CSP) before using the SDK.

Step 1: Get Your API Key

Request API Access

Contact us at hello@nimbusbci.com to request your API key. Include your use case and expected volume.
API keys are typically issued within 24 hours. Include details about your BCI application, expected data volume, and timeline in your request.

Step 2: Install NimbusSDK.jl

NimbusSDK.jl is now available in the public Julia General Registry:
using Pkg

# Install the public wrapper (no private registry needed!)
Pkg.add("NimbusSDK")
After installing the wrapper, install the proprietary core with your API key:
using NimbusSDK

# One-time setup: Install the commercial core
NimbusSDK.install_core("your-api-key-here")
What changed? NimbusSDK.jl is now a public wrapper package. No more private registry setup! Just Pkg.add("NimbusSDK") and then install the core with your API key.
The core installation is persistent. You only need to run install_core() once per machine. After that, simply using NimbusSDK will work in any Julia project.

Step 3: Your First BCI Inference

Create a new Julia script and run your first BCI inference:
using NimbusSDK

# Step 1: One-time setup with your API key
NimbusSDK.install_core("your-api-key-here")

# Step 2: Load a pre-trained RxLDA model
model = load_model(RxLDAModel, "motor_imagery_4class_v1")
println("✓ Model loaded: $(get_n_features(model)) features, $(get_n_classes(model)) classes")

# Step 3: Prepare your preprocessed CSP features
# Shape: (n_features × n_samples × n_trials)
# Example: 16 CSP features × 250 samples × 20 trials
n_features = 16
n_samples = 250  # 1 second at 250 Hz
n_trials = 20

# Generate sample CSP features (in practice, load from your preprocessing)
features = randn(n_features, n_samples, n_trials)
labels = rand(1:4, n_trials)  # Random labels for demo

# Create BCIData with metadata
metadata = BCIMetadata(
    sampling_rate = 250.0,
    paradigm = :motor_imagery,
    feature_type = :csp,
    n_features = n_features,
    n_classes = 4,
    chunk_size = nothing  # Batch mode
)

data = BCIData(features, metadata, labels)

# Step 4: Run batch inference
println("Running batch inference...")
results = predict_batch(model, data; iterations=10)

# Step 5: Analyze results
println("\n✓ Results:")
println("  Mean confidence: $(round(mean(results.confidences), digits=3))")
println("  Accuracy: $(round(100 * sum(results.predictions .== labels) / length(labels), digits=1))%")
println("  ITR: $(round(calculate_ITR(
    sum(results.predictions .== labels) / length(labels),
    4,
    4.0
), digits=1)) bits/minute")

Required Format for Features

NimbusSDK expects features in a specific format:
  • Dimensions: (n_features × n_samples × n_trials)
  • Feature types: CSP (recommended), bandpower, ERP amplitudes
  • Preprocessing: Must be applied before using SDK
Critical: You must preprocess your EEG data before using NimbusSDK. The SDK does NOT process raw EEG - it requires extracted features. See Preprocessing Guide for details.

Step 4: Training Your Own Model

Train a custom RxLDA model on your labeled data:
using NimbusSDK

# One-time setup: Install core with your API key
NimbusSDK.install_core("your-api-key")

# Prepare training data (features already preprocessed!)
train_features = load_your_csp_features()  # (n_features × n_samples × n_trials)
train_labels = load_your_labels()         # Vector of integers: 1, 2, 3, 4, ...

train_data = BCIData(
    train_features,
    BCIMetadata(
        sampling_rate = 250.0,
        paradigm = :motor_imagery,
        feature_type = :csp,
        n_features = 16,
        n_classes = 4,
        chunk_size = nothing,  # Batch mode
        temporal_aggregation = :logvar  # For CSP features in MI
    ),
    train_labels  # Required for training!
)

# Train the model
println("Training RxLDA model...")
model = train_model(
    RxLDAModel,
    train_data;
    iterations = 50,        # Number of inference iterations
    showprogress = true,    # Show training progress
    name = "my_custom_model",
    description = "4-class motor imagery with CSP"
)

# Save the trained model
save_model(model, "my_custom_model.jld2")

# Use for inference
test_data = BCIData(test_features, metadata)
results = predict_batch(model, test_data)

Step 5: Streaming Inference

For real-time applications, use streaming inference:
using NimbusSDK

# One-time setup: Install core with your API key
NimbusSDK.install_core("your-api-key")

# Load model (core is already installed)
model = load_model(RxLDAModel, "motor_imagery_4class_v1")

# Initialize streaming session (1 second chunks at 250 Hz)
metadata = BCIMetadata(
    sampling_rate = 250.0,
    paradigm = :motor_imagery,
    feature_type = :csp,
    n_features = 16,
    n_classes = 4,
    chunk_size = 250,  # 1 second chunks
    temporal_aggregation = :logvar  # For CSP features in MI
)

session = init_streaming(model, metadata)

# Process chunks as they arrive
for trial in your_eeg_stream()
    # Process one chunk
    chunk_result = process_chunk(session, trial)
    
    println("Chunk prediction: $(chunk_result.prediction) " *
            "(confidence: $(round(chunk_result.confidence, digits=3)))")
    
    # Finalize trial with weighted voting across all chunks
    if is_trial_complete(trial)
        final_result = finalize_trial(session; method=:weighted_vote)
        println("✓ Final prediction: $(final_result.prediction)")
        
        # Check quality
        if should_reject_trial(final_result.confidence, 0.7)
            println("⚠️ Low confidence - trial rejected")
        end
    end
end

Available Models

NimbusSDK includes two Bayesian inference models:

Bayesian LDA (RxLDA)

API Name: RxLDAModel
Mathematical Model: Pooled Gaussian Classifier (PGC)
  • Shared covariance across classes
  • Fast inference and training
  • Best for well-separated classes
  • Typical training time: 10-30 seconds (50 iterations, 100 trials)

Bayesian GMM (RxGMM)

API Name: RxGMMModel
Mathematical Model: Heteroscedastic Gaussian Classifier (HGC)
  • Class-specific covariances
  • More flexible, handles overlapping distributions
  • Better for complex class structures
  • Slightly slower than Bayesian LDA
Both models use RxInfer.jl for efficient variational Bayesian inference with reactive message passing.

Next Steps

Now that you have NimbusSDK running, explore these advanced features:

Common Use Cases

Troubleshooting

API Key Issues:Data Format Issues:
  • Features must be in shape: (n_features × n_samples × n_trials)
  • Ensure you’ve applied preprocessing (filtering, artifact removal, feature extraction)
  • No NaN or Inf values in data
Model Loading Issues:
  • Check that you have a valid model name
  • Ensure your internet connection is working (for pre-trained models)
  • Verify API key is authenticated
Need assistance? We’re here to help:
  • Email: hello@nimbusbci.com for technical support
  • Documentation: Browse our comprehensive guides
  • Examples: Check out working code samples in the SDK
  • API Documentation: See Julia SDK Reference
When reporting issues, please include:
  • Your Julia version and OS
  • The exact error message
  • A minimal code example that reproduces the issue
  • Your data shape and preprocessing steps

Performance Tips

Optimize for Production:
  • Use batch inference for multiple trials (more efficient than streaming)
  • Implement proper error handling with try-catch blocks
  • Monitor API usage and quotas
  • Cache model information locally after loading
  • Use appropriate confidence thresholds for your application
  • Check preprocessing quality with diagnose_preprocessing()
Congratulations! 🎉 You’ve successfully set up NimbusSDK.jl and run your first brain-computer interface inference. You’re now ready to build powerful BCI applications with sub-20ms latency and production-ready Bayesian inference.