Expand description
§exg — EEG/ECG/EMG preprocessing in pure Rust
exg is a zero-dependency* Rust library that implements the EEG
preprocessing pipeline. Every DSP step is ported from
MNE-Python and verified against MNE ground truth via
safetensors test vectors (run cargo test).
* No Python, no BLAS, no C libraries — pure Rust + RustFFT.
§Pipeline overview
sample_raw.fif
│
├─ fiff::open_raw() native FIFF reader (no MNE)
├─ resample::resample() FFT polyphase → target_sfreq (default 256 Hz)
├─ filter (FIR HP) firwin + overlap-add → 0.5 Hz cutoff
├─ reference per-timepoint channel mean removed
├─ normalize (z-score) (data − μ) / σ over all ch × t
├─ epoch non-overlapping 5 s windows
├─ baseline correct per-epoch per-channel mean removed
└─ ÷ data_norm ÷ 10 → std ≈ 0.1
│
└─→ Vec<([C, 1280] f32, [C, 3] f32)> (epochs, channel positions)§Quick start
use exg::{preprocess, PipelineConfig};
use exg::fiff::open_raw;
use ndarray::Array2;
// 1. Read a .fif file — no Python required
let raw = open_raw("data/sample1_raw.fif").unwrap();
let data = raw.read_all_data().unwrap(); // [C, T] f64
// 2. Channel positions from the FIF file (metres)
let chan_pos: Array2<f32> = Array2::zeros((raw.info.n_chan, 3));
// 3. Run the full preprocessing pipeline
let cfg = PipelineConfig::default();
let epochs = preprocess(
data.mapv(|v| v as f32),
chan_pos,
raw.info.sfreq as f32,
&cfg,
).unwrap();
for (i, (epoch_data, pos)) in epochs.iter().enumerate() {
println!("Epoch {i}: shape {:?}", epoch_data.dim());
}§Running individual steps
Each preprocessing step is also exposed as a standalone function:
use exg::resample::resample;
use exg::filter::{design_highpass, apply_fir_zero_phase};
use exg::reference::average_reference_inplace;
use exg::normalize::zscore_global_inplace;
use exg::epoch::epoch;
use ndarray::Array2;
let mut data: Array2<f32> = Array2::zeros((12, 3840)); // [C, T]
// Resample from 1024 Hz → 256 Hz
let data = resample(&data, 1024.0, 256.0).unwrap();
// Apply 0.5 Hz highpass FIR
let h = design_highpass(0.5, 256.0);
let mut data = data;
apply_fir_zero_phase(&mut data, &h).unwrap();
// Average reference
average_reference_inplace(&mut data);
// Global z-score
let (mean, std) = zscore_global_inplace(&mut data);
// Epoch into 5 s windows
let epochs = epoch(&data, 1280); // [E, C, 1280]§Feature coverage
See the README for a full table of which MNE features are implemented and which are not yet ported.
Re-exports§
pub use config::PipelineConfig;pub use epoch::epoch;pub use epoch::epoch_and_baseline;pub use fiff::open_raw;pub use fiff::RawFif;pub use fiff::BufferRecord;pub use fiff::ChannelInfo;pub use fiff::MeasInfo;pub use fiff::read_meas_info;pub use fiff::TagHeader;pub use fiff::read_tag_header;pub use fiff::read_i32;pub use fiff::read_f32;pub use fiff::read_f64;pub use fiff::read_string;pub use fiff::read_i32_array;pub use fiff::read_f32_array;pub use fiff::read_f64_array;pub use fiff::read_raw_bytes;pub use fiff::read_directory;pub use fiff::Node;pub use fiff::build_tree;pub use fiff::read_tree;pub use fiff::scan_directory;pub use fiff::try_load_directory;pub use filter::auto_trans_bandwidth;pub use filter::auto_filter_length;pub use filter::design_highpass;pub use filter::firwin;pub use filter::hamming;pub use filter::apply_fir_zero_phase;pub use filter::filter_1d;pub use io::RawData;pub use io::StWriter;pub use io::write_batch;pub use normalize::zscore_global_inplace;pub use normalize::baseline_correct_inplace;pub use reference::average_reference_inplace;pub use resample::resample;pub use resample::resample_1d;pub use resample::auto_npad;pub use resample::rational_approx;pub use resample::final_length;
Modules§
- config
- Pipeline configuration.
- epoch
- Fixed-length epoching.
- fiff
- FIFF file format reader.
- filter
- FIR filter design and application.
- io
- Safetensors I/O for the preprocessing pipeline.
- normalize
- Z-score normalisation and epoch baseline correction.
- reference
- Average reference: subtract the mean across channels at each time point.
- resample
- FFT-based rational resampler exactly matching MNE’s
resample(..., method='fft').
Functions§
- preprocess
- Run the full EEG preprocessing pipeline on a single continuous recording.
- zero_
bad_ channels - Zero-fill channels whose normalised name appears in
bad.