linfa_reduction/
utils.rs

1use ndarray::Array2;
2use ndarray_rand::rand::Rng;
3use num_traits::float::FloatConst;
4
5/// Generates a three dimension swiss roll, centered at the origin with height `height` and
6/// outwards speed `speed`
7pub fn generate_swissroll(
8    height: f64,
9    speed: f64,
10    n_points: usize,
11    rng: &mut impl Rng,
12) -> Array2<f64> {
13    let mut roll: Array2<f64> = Array2::zeros((n_points, 3));
14
15    for i in 0..n_points {
16        let z = rng.gen_range(0.0..height);
17        let phi: f64 = rng.gen_range(0.0..10.0);
18        //let offset: f64 = rng.gen_range(-0.5..0.5);
19        let offset = 0.0;
20
21        let x = speed * phi * phi.cos() + offset;
22        let y = speed * phi * phi.sin() + offset;
23
24        roll[(i, 0)] = x;
25        roll[(i, 1)] = y;
26        roll[(i, 2)] = z;
27    }
28    roll
29}
30
31pub fn generate_convoluted_rings(
32    rings: &[(f64, f64)],
33    n_points: usize,
34    rng: &mut impl Rng,
35) -> Array2<f64> {
36    let n_points = (n_points as f32 / rings.len() as f32).ceil() as usize;
37    let mut array = Array2::zeros((n_points * rings.len(), 3));
38
39    for (n, (start, end)) in rings.iter().enumerate() {
40        // inner circle
41        for i in 0..n_points {
42            let r: f64 = rng.gen_range(*start..*end);
43            let phi: f64 = rng.gen_range(0.0..(f64::PI() * 2.0));
44            let theta: f64 = rng.gen_range(0.0..(f64::PI() * 2.0));
45
46            let x = theta.sin() * phi.cos() * r;
47            let y = theta.sin() * phi.sin() * r;
48            let z = theta.cos() * r;
49
50            array[(n * n_points + i, 0)] = x;
51            array[(n * n_points + i, 1)] = y;
52            array[(n * n_points + i, 2)] = z;
53        }
54    }
55
56    array
57}
58
59pub fn generate_convoluted_rings2d(
60    rings: &[(f64, f64)],
61    n_points: usize,
62    rng: &mut impl Rng,
63) -> Array2<f64> {
64    let n_points = (n_points as f32 / rings.len() as f32).ceil() as usize;
65    let mut array = Array2::zeros((n_points * rings.len(), 2));
66
67    for (n, (start, end)) in rings.iter().enumerate() {
68        // inner circle
69        for i in 0..n_points {
70            let r: f64 = rng.gen_range(*start..*end);
71            let phi: f64 = rng.gen_range(0.0..(f64::PI() * 2.0));
72
73            let x = phi.cos() * r;
74            let y = phi.sin() * r;
75
76            array[(n * n_points + i, 0)] = x;
77            array[(n * n_points + i, 1)] = y;
78        }
79    }
80
81    array
82}