exg_luna/lib.rs
1//! # exg-luna — LUNA seizure-detection EEG preprocessing pipeline
2//!
3//! [](https://crates.io/crates/exg-luna)
4//! [](https://docs.rs/exg-luna)
5//!
6//! Part of the [`exg`](https://crates.io/crates/exg) workspace.
7//! Uses `exg` DSP primitives (filter design, resampling, montage conversion)
8//! under the hood.
9//!
10//! ## Pipeline
11//!
12//! Implements the full preprocessing chain used by the LUNA seizure detection
13//! model, matching the Python training pipeline:
14//!
15//! 1. Channel rename (strip `"EEG "` prefix, `"-REF"` / `"-LE"` suffix)
16//! 2. Pick standard 10-20 channels (21 electrodes)
17//! 3. Bandpass filter 0.1–75 Hz (zero-phase FIR, MNE `_firwin_design` parity)
18//! 4. Notch filter at 60 Hz (configurable for 50 Hz)
19//! 5. Resample to 256 Hz (FFT polyphase)
20//! 6. TCP bipolar montage (22 channels from 21 reference electrodes)
21//! 7. Epoch into 5 s non-overlapping windows (1280 samples)
22//!
23//! **Note:** Channel-wise z-score is _not_ applied here — LUNA does that at
24//! inference time inside the model. Use
25//! `exg::normalize::zscore_channelwise_inplace` separately if needed.
26//!
27//! ## I/O
28//!
29//! This crate also provides safetensors serialization of preprocessed epochs
30//! in a format compatible with `luna-rs` `InputBatch`.
31//!
32//! ## Quick start
33//!
34//! ```ignore
35//! use exg::edf::open_raw_edf;
36//! use exg_luna::{preprocess_luna, LunaPipelineConfig};
37//!
38//! let raw = open_raw_edf("recording.edf").unwrap();
39//! let data = raw.read_all_data().unwrap();
40//! let ch_names = raw.channel_names();
41//! let cfg = LunaPipelineConfig::default();
42//! let epochs = preprocess_luna(data, &ch_names, raw.header.sample_rate, &cfg).unwrap();
43//! ```
44
45mod io;
46mod pipeline;
47
48pub use io::{LunaEpoch, export_luna_epochs, load_luna_epochs};
49pub use pipeline::{preprocess_luna, LunaPipelineConfig, STANDARD_10_20};