1use std::collections::BTreeSet;
2
3use num::Float;
4use num_traits::{FromPrimitive, Zero};
5use crate::find_peaks::PeakFinder;
6
7pub fn gaussian(x1: f32, y1: f32, x2: f32, y2: f32, radius: f32) -> f32 {
8 let pi = std::f32::consts::PI;
9 let numerator = 1.0 / (2.0 * pi);
10 let denominator = 0.4;
11
12 let exponent =
13 -1.0
14 * (
15 3.0
16 * (
17 (x1 - x2).powi(2)
18 + (y1 - y2).powi(2)
19 ).sqrt()
20 / radius
21 ).powi(2)
22 / denominator;
23
24 let exponent = exponent.exp();
25
26 numerator * exponent
27}
28
29pub fn kde(x: f32, y: f32, points: &Vec<(f32, f32)>, radius: f32) -> f32 {
30 let mut sum = 0.0;
31
32 for point in points.iter() {
33 sum += gaussian(x, y, point.0, point.1, radius);
34 }
35
36 sum
37}
38
39fn amax(
40 vec: &[f32; 16384],
41) -> (usize, f32) {
42 let mut max = f32::zero();
43 let mut pos = 0;
44
45 for (i, val) in vec.iter().enumerate() {
46 if *val > max {
47 max = *val;
48 pos = i;
49 }
50 }
51
52 (pos, max)
53}
54
55const LOCALITY: f32 = 5.0f32;
56
57pub struct Kde {
58 pub data: [u32; 16384],
59 pub points: Vec<(f32, f32)>,
60 pub kde: [f32; 16384],
61
62 pub densest_points: BTreeSet<usize>,
63
64 pub x_min: f32,
65 pub x_max: f32,
66 pub y_min: f32,
67 pub y_max: f32,
68
69 pub radius: f32,
70}
71
72impl Kde {
73 pub fn new(vec: &[u32; 16384]) -> Kde {
74 let mut data = [0u32; 16384];
75
76 data.copy_from_slice(vec.as_slice());
77
78
79 Kde {
80 data,
81 points: Vec::new(),
82 kde: [0.0; 16384],
83
84 densest_points: BTreeSet::new(),
85
86 x_min: 0.0,
87 x_max: 0.0,
88 y_min: 0.0,
89 y_max: 0.0,
90
91 radius: 10.0,
92 }
93 }
94
95 pub fn clear(&mut self) {
96 self.points = Vec::new();
97 self.kde = [0.0f32; 16384];
98
99 self.densest_points = BTreeSet::new();
100
101 self.x_min = 0.0f32;
102 self.x_max = 0.0f32;
103 self.y_min = 0.0f32;
104 self.y_max = 0.0f32;
105
106 self.radius = 10.0f32;
107 }
108
109 pub fn build_points(&mut self) {
110 for y in 0..16384 {
111 if self.data[y] <= 0 {
112 continue;
113 }
114
115 self.points
116 .push(
117 (
118 (y / 128) as f32,
119 (y % 128) as f32
120 )
121 );
122 }
123 }
124
125 pub fn determine_kde_params(&mut self) -> Option<()> {
126 self.x_min = self.points.iter().map(|p| p.0).min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
128 self.x_max = self.points.iter().map(|p| p.0).max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
129 self.y_min = self.points.iter().map(|p| p.1).min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
130 self.y_max = self.points.iter().map(|p| p.1).max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
131
132 let dx = self.x_max - self.x_min;
133 let dy = self.y_max - self.y_min;
134
135 self.radius = dx.min(dy) / LOCALITY;
136
137 Some(())
138 }
139
140 pub fn calculate_kde(&mut self) {
141 for y in 0..128 {
142 for x in 0..128 {
143 self.kde[(x * 128) + y] =
144 kde(
145 x as f32,
146 y as f32,
147 &self.points,
148 self.radius,
149 );
150 }
151 }
152 }
153
154 pub fn determine_densest_points(&mut self) {
155 let mut pf =
156 PeakFinder::new(&self.kde);
157
158 pf.with_min_prominence(2.0);
159
160 let peaks =
161 pf.find_peaks();
162
163 let peaks =
164 peaks.iter()
165 .map(|p| p.clone().position.collect::<Vec<_>>())
166 .flatten()
167 .collect::<Vec<_>>();
168
169 for peak in peaks {
171 let (x, y) = (peak / 128, peak % 128);
172
173 let cutoff = 10.0;
174
175 for point in self.points.iter() {
177 if (point.0 - x as f32).abs() < cutoff
178 && (point.1 - y as f32).abs() < cutoff {
179 let idx = point.0 as u32 * 128 + point.1 as u32;
180
181 if self.data[idx as usize] > 0 {
182 self.densest_points.insert(idx as usize);
183 }
184 }
185 }
186 }
187
188 dbg!(&self.densest_points);
189 }
190
191 pub fn fit_kde(&mut self) {
192 let (min, max) =
193 self.kde
194 .iter()
195 .fold(
196 (std::f32::MAX, std::f32::MIN),
197 |(min, max), &x|
198 (
199 min.min(x),
200 max.max(x)
201 ),
202 );
203
204 self.kde
206 .iter_mut()
207 .for_each(|x|
208 *x = ((*x - min) / (max - min)) * 255.0
209 );
210 }
211
212 pub fn get_kde_data(&self) -> [u32; 16384] {
213 let mut kde_data = [0u32; 16384];
214
215 for (i, val) in self.kde.iter().enumerate() {
216 kde_data[i] = *val as u32;
217 }
218
219 kde_data
220 }
221
222 pub fn run(&mut self) {
223 self.build_points();
224 self.determine_kde_params();
225 self.calculate_kde();
226 self.determine_densest_points();
227 self.fit_kde();
228 }
229}
230
231pub struct Density {
232 pub data: [u32; 16384],
233}
234
235impl Density {
236 pub fn new(vec: &[u32]) -> Self {
237 assert_eq!(vec.len(), 16384);
238
239 let mut data = [0u32; 16384];
240
241 data.copy_from_slice(vec);
242
243 Self {
244 data,
245 }
246 }
247
248 pub fn set_data(&mut self, vec: &[u32; 16384]) {
249 let mut data = [0u32; 16384];
250
251 data.copy_from_slice(vec.as_slice());
252
253 self.data = data;
254 }
255
256 pub fn get_data(&self) -> &[u32; 16384] {
257 &self.data
258 }
259
260 pub fn filter_points_min(&mut self, min: u32) {
261 self.data
262 .iter_mut()
263 .filter(|b| **b < min)
264 .for_each(|b| *b = u32::zero());
265 }
266
267 pub fn kde(&mut self) -> Kde {
268 let mut kde =
269 Kde::new(&self.data);
270
271 kde.run();
272
273 kde
274 }
275}