qsm_core/kernels/
laplacian.rs1pub fn laplacian_kernel(
20 nx: usize, ny: usize, nz: usize,
21 vsx: f64, vsy: f64, vsz: f64,
22 negative: bool,
23) -> Vec<f64> {
24 let n_total = nx * ny * nz;
25 let mut l = vec![0.0; n_total];
26
27 let hx = 1.0 / (vsx * vsx);
29 let hy = 1.0 / (vsy * vsy);
30 let hz = 1.0 / (vsz * vsz);
31 let center = -2.0 * (hx + hy + hz);
32
33 let sign = if negative { -1.0 } else { 1.0 };
34
35 l[0] = sign * center;
39
40 if nx > 1 {
42 l[1] = sign * hx; l[nx - 1] = sign * hx; }
45
46 if ny > 1 {
48 l[nx] = sign * hy; l[(ny - 1) * nx] = sign * hy; }
51
52 if nz > 1 {
54 l[nx * ny] = sign * hz; l[(nz - 1) * nx * ny] = sign * hz; }
57
58 l
59}
60
61pub fn negative_laplacian_kernel(
63 nx: usize, ny: usize, nz: usize,
64 vsx: f64, vsy: f64, vsz: f64,
65) -> Vec<f64> {
66 laplacian_kernel(nx, ny, nz, vsx, vsy, vsz, true)
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_laplacian_kernel_sum() {
75 let l = laplacian_kernel(8, 8, 8, 1.0, 1.0, 1.0, false);
77 let sum: f64 = l.iter().sum();
78 assert!(sum.abs() < 1e-10, "Laplacian should sum to 0, got {}", sum);
79 }
80
81 #[test]
82 fn test_laplacian_kernel_center() {
83 let l = laplacian_kernel(8, 8, 8, 1.0, 1.0, 1.0, false);
84 assert!((l[0] - (-6.0)).abs() < 1e-10, "Center should be -6, got {}", l[0]);
86 }
87
88 #[test]
89 fn test_negative_laplacian() {
90 let l_pos = laplacian_kernel(8, 8, 8, 1.0, 1.0, 1.0, false);
91 let l_neg = laplacian_kernel(8, 8, 8, 1.0, 1.0, 1.0, true);
92
93 for (p, n) in l_pos.iter().zip(l_neg.iter()) {
94 assert!((p + n).abs() < 1e-10, "Negative should be opposite sign");
95 }
96 }
97}