pub mod encoder;
pub mod encoders;
pub mod error;
pub mod modulators;
#[cfg(feature = "ndarray")]
pub mod ndarray_ext;
pub mod poisson;
pub mod rng;
pub mod types;
pub use error::EncoderError;
#[cfg(feature = "ndarray")]
pub use ndarray_ext::NdarrayEncoderExt;
pub mod prelude {
pub use crate::Encoder;
pub use crate::ModulatedEncoder;
pub use crate::encoder::*;
pub use crate::encoders::*;
pub use crate::error::*;
pub use crate::modulators::*;
#[cfg(feature = "ndarray")]
pub use crate::ndarray_ext::NdarrayEncoderExt;
pub use crate::poisson::*;
pub use crate::types::*;
}
use modulators::{EncodingGains, NeuroModulators, NeuromodulatorGainCurves};
use types::EncodedOutput;
pub trait ModulatedEncoder: Encoder {
fn encode_with_gains(&mut self, input: &[f32], gains: EncodingGains) -> EncodedOutput;
fn encode_step_with_gains(&mut self, input: &[f32], gains: EncodingGains) -> EncodedOutput {
self.encode_with_gains(input, gains)
}
fn encode_with_modulators(
&mut self,
input: &[f32],
modulators: &NeuroModulators,
gain_curves: &NeuromodulatorGainCurves,
) -> EncodedOutput {
self.encode_with_gains(input, gain_curves.evaluate(modulators))
}
fn encode_step_with_modulators(
&mut self,
input: &[f32],
modulators: &NeuroModulators,
gain_curves: &NeuromodulatorGainCurves,
) -> EncodedOutput {
self.encode_step_with_gains(input, gain_curves.evaluate(modulators))
}
}
pub trait Encoder {
fn encode(&mut self, input: &[f32]) -> EncodedOutput;
fn encode_step(&mut self, input: &[f32]) -> EncodedOutput {
self.encode(input)
}
fn reset(&mut self);
}
#[cfg(test)]
mod tests {
#[test]
fn test_lib_prelude_imports() {
use crate::prelude::*;
let _ = EncoderConfig::default();
}
#[test]
fn cargo_toml_has_no_neuromod_crate_dependency() {
let output = std::process::Command::new(env!("CARGO"))
.args(["metadata", "--no-deps", "--locked", "--format-version", "1"])
.current_dir(env!("CARGO_MANIFEST_DIR"))
.output()
.expect("spawn cargo metadata");
let metadata_detail = format!(
"cargo metadata failed (status={:?}): {}",
output.status.code(),
String::from_utf8_lossy(&output.stderr)
);
assert!(output.status.success(), "{metadata_detail}");
let meta: serde_json::Value =
serde_json::from_slice(&output.stdout).expect("parse cargo metadata json");
let packages = meta["packages"].as_array().expect("packages array");
let deps = packages
.iter()
.find(|p| p["name"] == "axon-encoder")
.expect("axon-encoder package in metadata")["dependencies"]
.as_array()
.expect("dependencies array");
let forbidden: Vec<&serde_json::Value> =
deps.iter().filter(|d| d["name"] == "neuromod").collect();
let detail = format!(
"forbidden neuromod deps (name/kind): {:?}",
forbidden
.iter()
.map(|d| (&d["name"], &d["kind"]))
.collect::<Vec<_>>()
);
assert!(forbidden.is_empty(), "{detail}");
}
#[test]
fn test_encoder_default_encode_step_delegates_to_encode() {
use crate::prelude::*;
struct PassThrough;
impl Encoder for PassThrough {
fn encode(&mut self, input: &[f32]) -> EncodedOutput {
let mut out = EncodedOutput::new();
for (i, &v) in input.iter().enumerate() {
out.spikes.push(SpikeEvent {
channel: i as u16,
timestamp: v as u64,
polarity: true,
});
}
out
}
fn reset(&mut self) {}
}
let mut enc = PassThrough;
let out = enc.encode_step(&[1.0, 2.0]);
assert_eq!(out.spikes.len(), 2);
}
}