pub mod frequency_analysis;
pub mod time_series_analysis;
pub mod phase_analysis;
pub mod transform_methods;
pub mod filtering;
pub mod signal_utilities;
pub mod composite_extractors;
pub use frequency_analysis::{FilterBankExtractor, FrequencyDomainExtractor, STFT};
pub use time_series_analysis::{AutoregressiveExtractor, CrossCorrelationExtractor};
pub use phase_analysis::{HilbertTransform, PhaseBasedExtractor};
pub use transform_methods::WaveletTransform;
pub use filtering::{
BandpassFilter, FilterBank, FilterType, HighpassFilter, LowpassFilter, NotchFilter,
};
pub use signal_utilities::{EnvelopeDetector, Resampler};
pub use composite_extractors::{
apply_window, auto_correlate, convolve, convolve_mode, cross_correlate, generate_window,
normalized_cross_correlate, SignalFeatureExtractor,
};
pub type SignalProcessor = SignalFeatureExtractor;
pub type FrequencyProcessor = FrequencyDomainExtractor;
pub type TimeSeriesProcessor = AutoregressiveExtractor;
pub type PhaseProcessor = PhaseBasedExtractor;
pub type WaveletProcessor = WaveletTransform;
#[allow(non_snake_case)]
#[cfg(test)]
mod tests {
use super::*;
use scirs2_core::ndarray::Array1;
#[test]
fn test_frequency_domain_extractor() {
let signal = Array1::from_iter(
(0..512).map(|i| (2.0 * std::f64::consts::PI * 10.0 * i as f64 / 250.0).sin()),
);
let extractor = FrequencyDomainExtractor::new()
.n_fft(256)
.sample_rate(250.0);
let features = extractor
.extract_features(&signal.view())
.expect("operation should succeed");
assert!(!features.is_empty());
assert!(features.iter().all(|&x| x.is_finite()));
}
#[test]
fn test_autoregressive_extractor() {
let signal = Array1::from_iter((0..100).map(|i| i as f64 + 0.1 * (i as f64).sin()));
let extractor = AutoregressiveExtractor::new()
.order(5)
.method("yule_walker".to_string());
let features = extractor
.extract_features(&signal.view())
.expect("operation should succeed");
assert_eq!(features.len(), 5);
assert!(features.iter().all(|&x| x.is_finite()));
}
#[test]
fn test_phase_based_extractor() {
let signal = Array1::from_iter(
(0..512).map(|i| (2.0 * std::f64::consts::PI * 15.0 * i as f64 / 250.0).sin()),
);
let extractor = PhaseBasedExtractor::new().n_fft(256).hop_length(128);
let features = extractor
.extract_features(&signal.view())
.expect("operation should succeed");
assert!(!features.is_empty());
assert!(features.iter().all(|&x| x.is_finite()));
}
#[test]
fn test_wavelet_transform() {
let signal = Array1::from_iter(
(0..256).map(|i| (2.0 * std::f64::consts::PI * 5.0 * i as f64 / 100.0).sin()),
);
let extractor = WaveletTransform::new()
.wavelet("haar".to_string())
.levels(4);
let features = extractor
.extract_features(&signal.view())
.expect("operation should succeed");
assert!(features.len() <= 5); assert!(features.iter().all(|&x| x.is_finite()));
}
#[test]
fn test_bandpass_filter() {
let signal = Array1::from_iter(
(0..500).map(|i| (2.0 * std::f64::consts::PI * 10.0 * i as f64 / 250.0).sin()),
);
let filter = BandpassFilter::new()
.frequency_range(8.0, 12.0)
.sample_rate(250.0);
let features = filter
.extract_features(&signal.view())
.expect("operation should succeed");
assert_eq!(features.len(), 3); assert!(features.iter().all(|&x| x.is_finite()));
}
#[test]
fn test_signal_feature_extractor() {
let signal = Array1::from_iter(
(0..512).map(|i| (2.0 * std::f64::consts::PI * 20.0 * i as f64 / 250.0).sin()),
);
let extractor = SignalFeatureExtractor::new()
.include_statistical(true)
.include_spectral(true)
.include_temporal(true)
.sample_rate(250.0);
let features = extractor
.extract_features(&signal.view())
.expect("operation should succeed");
let expected_count = extractor.feature_count();
assert_eq!(features.len(), expected_count);
assert!(features.iter().all(|&x| x.is_finite()));
}
#[test]
fn test_cross_correlation() {
let signal1 = Array1::from_iter((0..100).map(|i| (i as f64 * 0.1).sin()));
let signal2 = Array1::from_iter((0..100).map(|i| (i as f64 * 0.1 + 0.5).sin()));
let correlation =
cross_correlate(&signal1.view(), &signal2.view()).expect("operation should succeed");
assert_eq!(correlation.len(), signal1.len() + signal2.len() - 1);
assert!(correlation.iter().all(|&x| x.is_finite()));
}
#[test]
fn test_apply_window() {
let signal = Array1::ones(128);
let windowed = apply_window(&signal.view(), "hanning").expect("operation should succeed");
assert_eq!(windowed.len(), signal.len());
assert!(windowed[0] < windowed[64]); assert!(windowed.iter().all(|&x| x.is_finite()));
}
}