use std::fmt;
use polars::prelude::*;
pub const COL_X: &str = "x";
pub const COL_Y: &str = "y";
pub const COL_T: &str = "t";
pub const COL_POLARITY: &str = "polarity";
pub mod config;
pub mod denoise;
pub mod downsampling;
pub mod drop_pixel;
pub mod hot_pixel;
pub mod polarity;
pub mod python;
pub mod spatial;
pub mod temporal; pub mod utils;
pub use config::{FilterConfig, FilterError, FilterResult};
pub use denoise::{DenoiseFilter, RefractoryFilter};
pub use downsampling::{DownsamplingFilter, DownsamplingStrategy};
pub use drop_pixel::{DropPixelFilter, PixelMask};
pub use hot_pixel::{HotPixelDetector, HotPixelFilter};
pub use polarity::PolarityFilter;
pub use spatial::{
CircularROI, MultipleROIs, Point, PolygonROI, ROICombination, RegionOfInterest, SpatialFilter,
};
pub use temporal::TemporalFilter;
pub fn filter_events_dataframe(df: LazyFrame, config: &FilterConfig) -> PolarsResult<LazyFrame> {
let mut filtered_df = df;
if let Some(temporal_filter) = &config.temporal_filter {
filtered_df = temporal_filter.apply_to_dataframe(filtered_df)?;
}
if let Some(spatial_filter) = &config.spatial_filter {
filtered_df = spatial_filter.apply_to_dataframe(filtered_df)?;
}
if let Some(polarity_filter) = &config.polarity_filter {
filtered_df = polarity_filter.apply_to_dataframe(filtered_df)?;
}
Ok(filtered_df)
}
#[derive(Debug, Clone)]
pub struct FilterStats {
pub input_count: usize,
pub output_count: usize,
pub removed_count: usize,
pub removal_fraction: f64,
pub processing_time: f64,
pub throughput: f64,
}
impl FilterStats {
pub fn new(input_count: usize, output_count: usize, processing_time: f64) -> Self {
let removed_count = input_count.saturating_sub(output_count);
let removal_fraction = if input_count > 0 {
removed_count as f64 / input_count as f64
} else {
0.0
};
let throughput = if processing_time > 0.0 {
input_count as f64 / processing_time
} else {
0.0
};
Self {
input_count,
output_count,
removed_count,
removal_fraction,
processing_time,
throughput,
}
}
}
impl fmt::Display for FilterStats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Filter Stats: {} -> {} events ({:.1}% removed) in {:.3}s ({:.0} events/s)",
self.input_count,
self.output_count,
self.removal_fraction * 100.0,
self.processing_time,
self.throughput
)
}
}
pub mod presets {
use super::*;
pub fn noise_removal() -> FilterConfig {
FilterConfig::new()
.with_hot_pixel_filter(HotPixelFilter::percentile(99.5))
.with_denoise_filter(DenoiseFilter::refractory(1000.0)) }
pub fn aggressive_noise_removal() -> FilterConfig {
FilterConfig::new()
.with_hot_pixel_filter(HotPixelFilter::percentile(99.0))
.with_denoise_filter(DenoiseFilter::refractory(500.0)) }
pub fn minimal_processing() -> FilterConfig {
FilterConfig::new().with_hot_pixel_filter(HotPixelFilter::percentile(99.9))
}
pub fn high_throughput() -> FilterConfig {
FilterConfig::new()
.with_hot_pixel_filter(HotPixelFilter::percentile(98.0))
.with_denoise_filter(DenoiseFilter::refractory(2000.0)) .with_downsampling_filter(DownsamplingFilter::uniform(0.5)) }
}
#[cfg(test)]
mod tests {
use super::*;
}