# Axon Encoder
[](https://github.com/Limen-Neural/axon-encoder/actions/workflows/ci.yml)
[](https://codecov.io/gh/Limen-Neural/axon-encoder)
[](https://github.com/Limen-Neural/axon-encoder/actions/workflows/qodana_code_quality.yml)
[](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:
| `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.