Skip to main content

fdars_core/depth/
modal.rs

1//! Modal depth measures.
2
3use crate::iter_maybe_parallel;
4use crate::matrix::FdMatrix;
5#[cfg(feature = "parallel")]
6use rayon::iter::ParallelIterator;
7
8/// Compute modal depth for 1D functional data.
9///
10/// Uses a Gaussian kernel to measure density around each curve.
11///
12/// # Arguments
13/// * `data_obj` - Data to compute depth for
14/// * `data_ori` - Reference data
15/// * `h` - Bandwidth parameter
16#[must_use = "expensive computation whose result should not be discarded"]
17pub fn modal_1d(data_obj: &FdMatrix, data_ori: &FdMatrix, h: f64) -> Vec<f64> {
18    let nobj = data_obj.nrows();
19    let nori = data_ori.nrows();
20    let n_points = data_obj.ncols();
21
22    if nobj == 0 || nori == 0 || n_points == 0 {
23        return Vec::new();
24    }
25
26    iter_maybe_parallel!(0..nobj)
27        .map(|i| {
28            let mut depth = 0.0;
29
30            for j in 0..nori {
31                let mut dist_sq = 0.0;
32                for t in 0..n_points {
33                    let diff = data_obj[(i, t)] - data_ori[(j, t)];
34                    dist_sq += diff * diff;
35                }
36                let dist = (dist_sq / n_points as f64).sqrt();
37                let kernel_val = (-0.5 * (dist / h).powi(2)).exp();
38                depth += kernel_val;
39            }
40
41            depth / nori as f64
42        })
43        .collect()
44}
45
46/// Compute modal depth for 2D functional data.
47#[must_use = "expensive computation whose result should not be discarded"]
48pub fn modal_2d(data_obj: &FdMatrix, data_ori: &FdMatrix, h: f64) -> Vec<f64> {
49    modal_1d(data_obj, data_ori, h)
50}