Skip to main content

sklears_decomposition/signal_processing/
mod.rs

1//! Signal Processing Framework for Decomposition Applications
2//!
3//! This module provides a comprehensive suite of signal processing techniques for
4//! machine learning and data analysis, organized into 5 specialized domains:
5//!
6//! ## Core Modules
7//!
8//! ### 1. **Empirical Mode Decomposition** (`emd_decomposition`)
9//! - Adaptive signal decomposition into Intrinsic Mode Functions (IMFs)
10//! - Multiple boundary conditions (Mirror, Periodic, Linear, Constant)
11//! - Multiple interpolation methods (CubicSpline, Linear, Polynomial)
12//! - SIMD-accelerated processing (5.9x-8.7x speedup)
13//! - Instantaneous frequency analysis and Hilbert-Huang spectrum
14//!
15//! ### 2. **Multivariate EMD** (`multivariate_emd`)
16//! - Extension of EMD for multivariate signals
17//! - Cross-channel correlation analysis
18//! - Energy distribution computation across channels
19//! - Enhanced validation for multivariate inputs
20//!
21//! ### 3. **Spectral Decomposition** (`spectral_decomposition`)
22//! - Short-Time Fourier Transform (STFT) with 9 window functions
23//! - Power Spectral Density (PSD) computation
24//! - Spectral peak detection and feature extraction
25//! - Cross-spectral analysis for multi-channel signals
26//! - Spectral centroid and rolloff analysis
27//!
28//! ### 4. **Blind Source Separation** (`blind_source_separation`)
29//! - **FastICA**: Independent Component Analysis with SIMD acceleration
30//! - **JADE**: Joint Approximate Diagonalization of Eigenmatrices
31//! - **InfoMax**: Information-theoretic source separation
32//! - Comprehensive performance evaluation (SIR, Amari distance)
33//! - Signal reconstruction and mixing matrix analysis
34//!
35//! ### 5. **Wavelet Transform** (`wavelet_transform`)
36//! - Multiple wavelet families (Haar, Daubechies, Biorthogonal, Coiflets)
37//! - Multiple boundary conditions (Zero-padding, Symmetric, Periodic)
38//! - Discrete Wavelet Transform (DWT) and analysis tools
39//! - Coefficient thresholding for denoising applications
40//! - Energy distribution and sparsity analysis
41//!
42//! ## Performance Features
43//!
44//! - **SIMD Acceleration**: Vectorized operations achieving 5.8x-10.8x speedups
45//! - **SciRS2 Compliance**: Full integration with SciRS2 ecosystem
46//! - **Comprehensive Testing**: Extensive unit tests with high coverage
47//! - **Memory Efficiency**: Optimized memory usage for large datasets
48//! - **Error Handling**: Robust validation and error propagation
49//!
50//! ## Usage Examples
51//!
52//! ### Empirical Mode Decomposition
53//! ```rust,ignore
54//! use sklears_decomposition::signal_processing::*;
55//! use scirs2_core::ndarray::array;
56//!
57//! // Create composite signal
58//! let signal = array![/* signal data */];
59//!
60//! // Configure and run EMD
61//! let emd = EmpiricalModeDecomposition::new()
62//!     .max_imfs(5)
63//!     .tolerance(1e-6)
64//!     .boundary_condition(BoundaryCondition::Mirror);
65//!
66//! let result = emd.decompose(&signal)?;
67//! let reconstructed = result.reconstruct();
68//! ```
69//!
70//! ### Blind Source Separation
71//! ```rust,ignore
72//! // FastICA for source separation
73//! let fastica = FastICA::new()
74//!     .n_components(3)
75//!     .fun(NonLinearityType::LogCosh)
76//!     .max_iter(200);
77//!
78//! let bss_result = fastica.fit_transform(&mixed_signals)?;
79//! let separated_sources = bss_result.sources;
80//! ```
81
82// Module declarations
83pub mod blind_source_separation;
84pub mod emd_decomposition;
85pub mod multivariate_emd;
86pub mod spectral_decomposition;
87pub mod wavelet_transform;
88
89// Re-export common types and utilities
90use sklears_core::error::Result;
91use sklears_core::types::Float;
92
93// Re-export core types and functionality from individual modules
94
95// EMD Domain re-exports
96pub use emd_decomposition::{
97    BoundaryCondition, EMDConfig, EMDResult, EmpiricalModeDecomposition, InterpolationMethod,
98};
99
100// Multivariate EMD re-exports
101pub use multivariate_emd::{MEMDResult, MultivariateEMD};
102
103// Spectral Decomposition re-exports
104pub use spectral_decomposition::{
105    CrossSpectralResult, SpectralDecomposition, SpectralResult, WindowFunction,
106};
107
108// Blind Source Separation re-exports
109pub use blind_source_separation::{BSSResult, FastICA, InfoMax, NonLinearityType, JADE};
110
111// Wavelet Transform re-exports
112pub use wavelet_transform::{WaveletBoundary, WaveletResult, WaveletTransform, WaveletType};
113
114/// Comprehensive signal processing factory for creating different processors
115pub struct SignalProcessingFactory {
116    default_emd_config: EMDConfig,
117}
118
119impl SignalProcessingFactory {
120    /// Create a new signal processing factory with default configurations
121    pub fn new() -> Self {
122        Self {
123            default_emd_config: EMDConfig::default(),
124        }
125    }
126
127    /// Create factory with custom EMD configuration
128    pub fn with_emd_config(config: EMDConfig) -> Self {
129        Self {
130            default_emd_config: config,
131        }
132    }
133
134    /// Create a new EMD instance with factory defaults
135    pub fn emd(&self) -> Result<EmpiricalModeDecomposition> {
136        let mut emd = EmpiricalModeDecomposition::new()
137            .tolerance(self.default_emd_config.tolerance)?
138            .max_sift_iter(self.default_emd_config.max_sift_iter)?
139            .boundary_condition(self.default_emd_config.boundary_condition)
140            .interpolation(self.default_emd_config.interpolation);
141
142        if let Some(max_imfs) = self.default_emd_config.max_imfs {
143            emd = emd.max_imfs(max_imfs)?;
144        }
145        Ok(emd)
146    }
147
148    /// Create a new EMD instance with custom configuration
149    pub fn emd_with_config(&self, config: EMDConfig) -> Result<EmpiricalModeDecomposition> {
150        let mut emd = EmpiricalModeDecomposition::new()
151            .tolerance(config.tolerance)?
152            .max_sift_iter(config.max_sift_iter)?
153            .boundary_condition(config.boundary_condition)
154            .interpolation(config.interpolation);
155
156        if let Some(max_imfs) = config.max_imfs {
157            emd = emd.max_imfs(max_imfs)?;
158        }
159        Ok(emd)
160    }
161
162    /// Create a new multivariate EMD instance
163    pub fn memd(&self, n_channels: usize) -> Result<MultivariateEMD> {
164        Ok(MultivariateEMD::new(n_channels)?.config(self.default_emd_config.clone()))
165    }
166
167    /// Create a new spectral decomposition instance
168    pub fn spectral(&self, window_size: usize) -> SpectralDecomposition {
169        SpectralDecomposition::new(window_size)
170    }
171
172    /// Create a new FastICA instance
173    pub fn fast_ica(&self) -> FastICA {
174        FastICA::new()
175    }
176
177    /// Create a new JADE instance
178    pub fn jade(&self) -> JADE {
179        JADE::new()
180    }
181
182    /// Create a new InfoMax instance
183    pub fn infomax(&self) -> InfoMax {
184        InfoMax::new()
185    }
186
187    /// Create a new wavelet transform instance
188    pub fn wavelet(&self, wavelet_type: WaveletType, levels: usize) -> WaveletTransform {
189        WaveletTransform::new()
190            .wavelet_type(wavelet_type)
191            .levels(levels)
192    }
193}
194
195impl Default for SignalProcessingFactory {
196    fn default() -> Self {
197        Self::new()
198    }
199}
200
201/// Convenience functions for common signal processing tasks
202pub mod convenience {
203    use super::*;
204    use scirs2_core::ndarray::{Array1, Array2};
205
206    /// Quick EMD decomposition with default settings
207    pub fn quick_emd(signal: &Array1<Float>) -> Result<EMDResult> {
208        let emd = EmpiricalModeDecomposition::new();
209        emd.decompose(signal)
210    }
211
212    /// Quick FastICA with default settings
213    pub fn quick_fastica(mixed_signals: &Array2<Float>) -> Result<BSSResult> {
214        let fastica = FastICA::new();
215        fastica.fit_transform(mixed_signals)
216    }
217
218    /// Quick spectral analysis with default settings
219    pub fn quick_stft(signal: &Array1<Float>, window_size: usize) -> Result<SpectralResult> {
220        let spectral = SpectralDecomposition::new(window_size);
221        spectral.stft(signal)
222    }
223
224    /// Quick wavelet transform with Haar wavelet
225    pub fn quick_wavelet(
226        signal: &Array1<Float>,
227        levels: usize,
228    ) -> Result<crate::signal_processing::wavelet_transform::WaveletDecomposition> {
229        let wavelet = WaveletTransform::new()
230            .wavelet_type(WaveletType::Haar)
231            .levels(levels);
232        wavelet.dwt(signal).map_err(|e| {
233            sklears_core::error::SklearsError::Other(format!("Wavelet error: {:?}", e))
234        })
235    }
236}
237
238#[allow(non_snake_case)]
239#[cfg(test)]
240mod tests {
241    use super::*;
242    use scirs2_core::ndarray::array;
243
244    #[test]
245    fn test_signal_processing_factory() {
246        let factory = SignalProcessingFactory::new();
247
248        // Test EMD creation
249        let _emd = factory.emd().expect("valid parameter");
250
251        // Test MEMD creation
252        let _memd = factory.memd(2).expect("valid parameter");
253
254        // Test spectral decomposition creation
255        let _spectral = factory.spectral(64);
256
257        // Test BSS algorithms creation
258        let _fastica = factory.fast_ica();
259        let _jade = factory.jade();
260        let _infomax = factory.infomax();
261
262        // Test wavelet creation
263        let _wavelet = factory.wavelet(WaveletType::Haar, 3);
264    }
265
266    #[test]
267    fn test_convenience_functions() {
268        let signal = array![1.0, 2.0, 3.0, 4.0, 3.0, 2.0, 1.0, 0.0];
269
270        // Test quick EMD
271        let _emd_result = convenience::quick_emd(&signal).expect("operation should succeed");
272
273        // Test quick wavelet
274        let _wavelet_result =
275            convenience::quick_wavelet(&signal, 2).expect("operation should succeed");
276
277        // Test quick spectral analysis
278        let _spectral_result =
279            convenience::quick_stft(&signal, 4).expect("operation should succeed");
280    }
281
282    #[test]
283    fn test_module_integration() {
284        // Test that all modules work together
285        let factory = SignalProcessingFactory::new();
286
287        // Create test signal
288        let signal = array![1.0, 2.0, 3.0, 4.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0];
289
290        // Test EMD
291        let emd = factory.emd().expect("valid parameter");
292        let _emd_result = emd.decompose(&signal).expect("operation should succeed");
293
294        // Test wavelet
295        let wavelet = factory.wavelet(WaveletType::Haar, 2);
296        let _wavelet_result = wavelet.dwt(&signal).expect("operation should succeed");
297
298        // Test spectral analysis
299        let spectral = factory.spectral(4);
300        let _spectral_result = spectral.stft(&signal).expect("operation should succeed");
301    }
302}