> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nimbusbci.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Message Passing Architecture

> Understanding the reactive message passing architecture in Nimbus. Learn about factor graphs, belief propagation, and RxInfer.jl reactive inference.

Nimbus uses reactive message passing on factor graphs to perform efficient Bayesian inference for BCI applications. This architecture enables real-time probabilistic reasoning while maintaining scalability and flexibility. Understanding this foundation helps you build more effective BCI systems.

<Note>
  **SDK Implementation:**

  * **Julia SDK**: Full access to RxInfer.jl's reactive message passing on factor graphs, enabling custom model development
  * **Python SDK**: Packaged Bayesian heads (`NimbusLDA`, `NimbusQDA`, `NimbusSoftmax`, and `NimbusSTS`) with optimized inference engines. [`Personalizer`](/personalizer/overview) uses those heads without requiring manual graph construction.

  Both SDKs provide the same probabilistic guarantees and real-time performance. Julia SDK offers more flexibility for research; Python SDK offers more ergonomics for production BCI applications.
</Note>

## Factor Graphs for BCI

### What are Factor Graphs?

Factor graphs are a mathematical framework for representing probabilistic models. They consist of:

* **Variable nodes**: Represent unknown quantities (brain states, intentions, etc.)
* **Factor nodes**: Represent probabilistic relationships between variables
* **Edges**: Connect variables to factors that depend on them

### BCI Example: Motor Imagery

Consider a simple motor imagery BCI:

```
EEG Signals → Neural Features → Brain State → Motor Intention → Cursor Movement
     |              |             |              |              |
  [Factor]      [Factor]      [Factor]      [Factor]      [Factor]
```

Each factor represents a probabilistic relationship:

* **Signal model**: How EEG relates to neural features
* **Feature model**: How features relate to brain state
* **State model**: How brain state relates to intention
* **Motor model**: How intention relates to movement

### Advantages for BCI

<Columns cols={2}>
  <Card title="Modular Design" icon="boxes">
    Each component can be developed and tested independently
  </Card>

  <Card title="Flexible Architecture" icon="refresh-cw">
    Easy to add new sensors, features, or output modalities
  </Card>

  <Card title="Uncertainty Propagation" icon="signal">
    Uncertainty flows naturally through the entire system
  </Card>

  <Card title="Efficient Inference" icon="bolt">
    Exploit sparsity and local structure for fast computation
  </Card>
</Columns>

## Message Passing Inference

### How Message Passing Works

Instead of computing the full joint probability distribution (computationally expensive), message passing computes local messages between connected nodes:

1. **Forward pass**: Messages flow from observations to hidden variables
2. **Backward pass**: Messages flow from priors to observations
3. **Marginal computation**: Combine messages to get final beliefs
4. **Reactive updates**: Only recompute affected messages when data arrives

### Real-time Updates

Traditional batch inference recomputes everything when new data arrives. RxInfer.jl's reactive message passing enables incremental updates:

**Traditional batch approach:**

* Recompute entire posterior when new data arrives
* High latency (100ms+)
* Wasteful computation

**RxInfer reactive approach:**

* Only update affected parts of the factor graph
* Low latency (10-20ms)
* Efficient incremental computation

### Reactive Programming

NimbusSDK uses RxInfer.jl reactive programming principles:

* **Event-driven**: Computation triggered by new data
* **Asynchronous**: Non-blocking message updates
* **Efficient**: Only update what changed
* **Robust**: Handle varying data rates gracefully

## BCI-Specific Optimizations

### Temporal Models

BCI signals have strong temporal structure. NimbusSDK exploits this:

**State Space Models**: Model how brain states evolve over time

```
Brain State[t-1] → Brain State[t] → Brain State[t+1]
       |                |                |
   EEG[t-1]         EEG[t]         EEG[t+1]
```

Benefits:

* **Prediction**: Anticipate future brain states
* **Smoothing**: Reduce noise by considering temporal context
* **Missing data**: Interpolate when signals are corrupted

**Multi-scale Dynamics**: Different neural processes operate at different timescales

* Slow Dynamics (seconds): Attention, arousal
* Medium Dynamics (100ms): Motor planning
* Fast Dynamics (10ms): Neural oscillations

NimbusLDA and NimbusQDA (both SDKs), plus the non-Gaussian static models (`NimbusSoftmax` in Python / `NimbusProbit` in Julia), handle temporal structure through proper feature aggregation and trial-level inference.

### Multi-modal Integration

Modern BCIs combine multiple signal types. Factor graphs naturally handle this:

```
    EEG → Neural State ← EMG
     |        |         |
   P300    Attention   Muscle
  Speller    Level    Activity
     |        |         |
     └── Intention ──────┘
            |
      Final Command
```

Each modality provides complementary information that improves overall performance.

### Hierarchical Processing

Brain activity operates at multiple levels. Nimbus models this hierarchy:

```
Global Brain State (Attention, Arousal)
        |
Regional Activity (Motor Cortex, Visual Cortex)  
        |
Local Populations (Individual Electrodes)
        |
Raw Signals (EEG, EMG, EOG)
```

Higher levels provide context for lower levels, improving inference quality.

## Implementation Details

### Efficient Message Computation

RxInfer.jl optimizes message passing for BCI workloads:

* **Sparse updates**: Only compute messages for affected nodes
* **Caching**: Reuse previous computations when possible
* **Topological sorting**: Optimal message update order
* **Variational inference**: Closed-form message updates (no sampling)

### Memory Management

Real-time systems require careful memory management:

* **Message caching**: Reuse previous computations
* **Bounded memory**: Fixed memory usage regardless of runtime
* **Efficient GC**: Minimal garbage collection pressure

### Numerical Stability

BCI signals can have extreme values. RxInfer handles this robustly:

* **Log-space computation**: Avoid numerical underflow
* **Adaptive precision**: Use appropriate numerical types
* **Regularization**: Prevent degenerate solutions

## Bayesian Models in NimbusSDK

### Model Structure

NimbusLDA and NimbusQDA (both SDKs), the non-Gaussian static models (`NimbusSoftmax` in Python / `NimbusProbit` in Julia), and NimbusSTS (Python) all use factor graph representations:

**NimbusLDA**: Linear Discriminant Analysis

* Gaussian observations with shared precision matrix
* Fast inference due to shared covariance
* Optimal for well-separated classes

**NimbusQDA**: Quadratic Discriminant Analysis (QDA)

* Class-specific covariance matrices
* More flexible for overlapping distributions
* Handles complex class structures

**Non-Gaussian static models**: Multinomial classifiers with uncertainty quantification

* `NimbusSoftmax` (Python): Bayesian multinomial logistic regression with Polya-Gamma variational inference
* `NimbusProbit` (Julia): Bayesian multinomial probit regression with RxInfer
* Most flexible for complex multinomial tasks

**Bayesian STS (`NimbusSTS`)**: State-space model with temporal dynamics (Python SDK only)

### Inference Process

1. **Observation**: Neural features from preprocessed EEG
2. **Message passing**: Update beliefs using variational inference
3. **Marginalization**: Compute posterior over classes
4. **Prediction**: Select class with highest posterior probability

## Best Practices

### Model Design

<Tip>
  Start simple and add complexity gradually. A simple model that works reliably is better than a complex model that fails unpredictably.
</Tip>

1. **Begin with linear models**: Add nonlinearity only when needed
2. **Use domain knowledge**: Incorporate known neural principles
3. **Validate incrementally**: Test each component separately
4. **Monitor performance**: Track inference speed and accuracy

### Scalability

1. **Exploit sparsity**: Most neural connections are sparse
2. **Use hierarchical models**: Process at multiple resolutions
3. **Cache computations**: Reuse expensive calculations
4. **Profile regularly**: Identify and fix bottlenecks

## Getting Started

Ready to build with message passing?

<CardGroup cols={2}>
  <Card title="Quick Start" icon="play" href="/quickstart">
    Build your first factor graph BCI
  </Card>

  <Card title="Julia SDK Reference" icon="code" href="/julia-sdk/api-reference">
    Explore Julia SDK functions and model APIs
  </Card>

  <Card title="Examples" icon="list" href="/examples/basic-examples">
    See message passing in action
  </Card>

  <Card title="Advanced Topics" icon="settings" href="/model-specification">
    Build custom probabilistic models with RxInfer.jl
  </Card>
</CardGroup>

***

<Note>
  **Next**: Learn how to configure [real-time inference](/inference-configuration/real-time-setup) for your BCI application.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.