axon-encoder 0.4.0

Flexible sensory encoding pipelines for spiking neural networks — rate, temporal, predictive, population, and neuromodulator-driven encoding for telemetry and cyber-physical data.
Documentation
# Axon Encoder

[![CI](https://github.com/Limen-Neural/axon-encoder/actions/workflows/ci.yml/badge.svg)](https://github.com/Limen-Neural/axon-encoder/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/Limen-Neural/axon-encoder/branch/main/graph/badge.svg)](https://codecov.io/gh/Limen-Neural/axon-encoder)
[![Qodana](https://github.com/Limen-Neural/axon-encoder/actions/workflows/qodana_code_quality.yml/badge.svg)](https://github.com/Limen-Neural/axon-encoder/actions/workflows/qodana_code_quality.yml)
[![Docs](https://docs.rs/axon-encoder/badge.svg)](https://docs.rs/axon-encoder)

**A flexible sensory encoding library for spiking neural networks (SNNs).**

`axon-encoder` turns continuous data—sensor readings, telemetry, control
signals—into **spikes**, the event-based signals SNNs process. Use it as the
front-end of a neuromorphic pipeline without pulling in a full SNN simulator.

## Installation

**0.4.x is experimental (pre-1.0).** Cargo treats `axon-encoder = "0.4"` as
`^0.4` (that is `>= 0.4.0, < 0.5.0`): compatible **patch** updates only.
A `0.5` release is a new breaking line; pin `"=0.4.0"` if you need an exact
crate version.

```toml
[dependencies]
axon-encoder = "0.4"
```

Optional features:

| Feature | Purpose |
| --- | --- |
| `serde` | Serialize configs and gain types |
| `ndarray` | Encode from `ndarray` views (`ArrayView1` / `ArrayView2`) |

```toml
[dependencies]
axon-encoder = { version = "0.4", features = ["ndarray"] }
ndarray = "0.16" # declare yourself so you can build ArrayView values
```

Requires **Rust 1.97.1+** (edition 2024). See `rust-version` in `Cargo.toml`.

## Quick start

```rust
use axon_encoder::prelude::*;

fn main() {
    // Prefer try_new: typed validation instead of panics on bad config.
    // Range is (min, max); values are clamped to that span. Endpoints map to
    // base_rate / max_rate (here 5–100 Hz at a 10 ms sampling interval).
    let mut encoder = RateEncoder::try_new(5.0, 100.0, (0.0, 1.0), 0.010)
        .expect("valid RateEncoder configuration");

    // Inclusive endpoints 0.0 ..= 1.0 (matches the range above).
    let input: Vec<f32> = (0..64).map(|i| i as f32 / 63.0).collect();
    let output = encoder.encode(&input);

    println!(
        "Input of {} values produced {} spikes.",
        input.len(),
        output.spikes.len()
    );
}
```

Full API docs: [docs.rs/axon-encoder](https://docs.rs/axon-encoder).

### Rate encoder time semantics

`RateEncoder` treats `base_rate` and `max_rate` as firing rates in **hertz**.
Prefer `RateEncoder::try_new(base_rate_hz, max_rate_hz, range, dt_seconds)` so the
sampling interval is explicit (finite and strictly positive). Stochastic batch
encoding uses `p = 1 - exp(-rate_hz * dt_seconds)`; streaming accumulates
`phase += rate_hz * dt_seconds`.

`RateEncoder::new(base_rate, max_rate, range)` remains for compatibility and
uses `dt_seconds = 0.1`.

### Constructor errors

Most encoders expose `try_new(...) -> Result<Self, EncoderError>` for invalid
rates, ranges, windows, thresholds, or channel counts. Prefer those over
panicking `new(...)` in libraries and applications. `PredictiveEncoder` is the
exception: its `new(...)` already returns a `Result`.

## Features

- **Encoders** for different signal structures:
  - **`RateEncoder`** — spike *rate* tracks input magnitude
  - **`DerivativeEncoder`** — fires on *change* (jumps / drops)
  - **`TemporalEncoder`***patterns* over time
  - **`PopulationEncoder`** — value distributed across a *population* of units
  - **`DeltaEncoder`** — spike when the signal moves by a threshold
  - **`LatencyEncoder`** — stronger input → earlier spike in a window
  - **`PoissonEncoder`** — Poisson-process style sampling
- **`Encoder` / `ModulatedEncoder` traits** — plug in custom encoders or apply
  gain scales (`EncodingGains`) without owning a full neuromodulator runtime
- **Optional `ndarray` helpers**`NdarrayEncoderExt` for view-based batch input
- **Small dependency surface** — easy to embed in larger systems

## Randomness (stochastic encoders)

`RateEncoder`, `PopulationEncoder`, and `PoissonEncoder` sample unit floats in
`[0, 1)` via `axon_encoder::rng`:

- **Default:** `gen_unit_f32()` uses a thread-local `rand` generator (not
  reproducible across runs).
- **Reproducible runs:** `gen_unit_f32_with_rng(&mut rng)` with a seeded RNG
  (for example `rand::rngs::StdRng`).
- For **encoding only** — not cryptographic use.

## WebAssembly

On `wasm32-unknown-unknown`, enable a working
[getrandom](https://docs.rs/getrandom) backend for your target (often the
JS/browser feature set). Stochastic encoders need OS/entropy-backed RNGs
through `rand`.

## Examples

Clone the repository and run:

```bash
cargo run --example rate_encoding
cargo run --example delta_encoding
cargo run --example ndarray_encoding --features ndarray
```

Other examples live under `examples/` (latency, population, temporal,
predictive, gain-adapter patterns, and more).

## What this crate is (and is not)

### In scope

- Sensory / signal → spike encoding algorithms
- Deterministic and stochastic encoding pipelines
- Generic gain controls (`EncodingGains`, gain curves) used only for scaling
  rate, threshold, latency, or sensitivity at encode time

### Out of scope

- Full SNN simulation, network topology, or synaptic plasticity (STDP)
- Long-horizon biological neuromodulator *dynamics* or reward loops (this crate
  only provides encoding-local gain helpers)
- FPGA / ASIC / GPU device bindings

The library is intentionally unopinionated about which simulator or hardware
stack you plug the spikes into.

## Docker (optional)

Published images ship **example binaries** (not a substitute for depending on
the crate from Cargo):

```bash
docker pull ghcr.io/limen-neural/axon-encoder:0.4.0
docker run --rm ghcr.io/limen-neural/axon-encoder:0.4.0
```

Build locally from a git checkout:

```bash
docker build -t axon-encoder:dev .
docker run --rm axon-encoder:dev

docker build --target builder -t axon-encoder:builder .
docker run --rm axon-encoder:builder   # cargo test --all-features --locked
```

## Contributing

Issues and pull requests are welcome—new encoders, fixes, and docs improvements
alike. Development notes and CI conventions live in the repository
(`REVIEW.md`, `.github/`).

## License

Dual-licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE-2.0]LICENSE-APACHE-2.0 or
  <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT License ([LICENSE-MIT]LICENSE-MIT or
  <http://opensource.org/licenses/MIT>)

at your option.