Fri, 28 Nov 2025 12:48:17 -0500
Initialise repository, separating measure from pointsource_algs
|
0
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
1 | /*! |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
2 | Spike merging heuristics for [`DiscreteMeasure`]s. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
3 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
4 | This module primarily provides the [`SpikeMerging`] trait, and within it, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
5 | the [`SpikeMerging::merge_spikes`] method. The trait is implemented on |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
6 | [`DiscreteMeasure<Loc<N, F>, F>`]s in dimensions `N=1` and `N=2`. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
7 | */ |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
8 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
9 | use numeric_literals::replace_float_literals; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
10 | use serde::{Deserialize, Serialize}; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
11 | use std::cmp::Ordering; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
12 | //use clap::builder::{PossibleValuesParser, PossibleValue}; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
13 | use alg_tools::nanleast::NaNLeast; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
14 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
15 | use super::delta::*; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
16 | use super::discrete::*; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
17 | use alg_tools::loc::Loc; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
18 | use alg_tools::types::*; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
19 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
20 | /// Spike merging heuristic selection |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
21 | #[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug)] |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
22 | #[allow(dead_code)] |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
23 | pub struct SpikeMergingMethod<F> { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
24 | // Merging radius |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
25 | pub radius: F, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
26 | // Enabled |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
27 | pub enabled: bool, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
28 | // Interpolate merged points |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
29 | pub interp: bool, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
30 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
31 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
32 | #[replace_float_literals(F::cast_from(literal))] |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
33 | impl<F: Float> Default for SpikeMergingMethod<F> { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
34 | fn default() -> Self { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
35 | SpikeMergingMethod { radius: 0.01, enabled: false, interp: true } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
36 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
37 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
38 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
39 | /// Trait for dimension-dependent implementation of heuristic peak merging strategies. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
40 | pub trait SpikeMerging<F> { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
41 | /// Attempt spike merging according to [`SpikeMerging`] method. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
42 | /// |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
43 | /// Returns the last [`Some`] returned by the merging candidate acceptance decision closure |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
44 | /// `accept` if any merging is performed. The closure should accept as its only parameter a |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
45 | /// new candidate measure (it will generally be internally mutated `self`, although this is |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
46 | /// not guaranteed), and return [`None`] if the merge is accepted, and otherwise a [`Some`] of |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
47 | /// an arbitrary value. This method will return that value for the *last* accepted merge, or |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
48 | /// [`None`] if no merge was accepted. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
49 | /// |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
50 | /// This method is stable with respect to spike locations: on merge, the weights of existing |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
51 | /// removed spikes is set to zero, new ones inserted at the end of the spike vector. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
52 | /// They merge may also be performed by increasing the weights of the existing spikes, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
53 | /// without inserting new spikes. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
54 | fn merge_spikes<G>(&mut self, method: SpikeMergingMethod<F>, accept: G) -> usize |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
55 | where |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
56 | G: FnMut(&'_ Self) -> bool, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
57 | { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
58 | if method.enabled { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
59 | self.do_merge_spikes_radius(method.radius, method.interp, accept) |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
60 | } else { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
61 | 0 |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
62 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
63 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
64 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
65 | /// Attempt to merge spikes based on a value and a fitness function. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
66 | /// |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
67 | /// Calls [`SpikeMerging::merge_spikes`] with `accept` constructed from the composition of |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
68 | /// `value` and `fitness`, compared to initial fitness. Returns the last return value of `value` |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
69 | // for a merge accepted by `fitness`. If no merge was accepted, `value` applied to the initial |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
70 | /// `self` is returned. also the number of merges is returned; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
71 | fn merge_spikes_fitness<G, H, V, O>( |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
72 | &mut self, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
73 | method: SpikeMergingMethod<F>, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
74 | value: G, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
75 | fitness: H, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
76 | ) -> (V, usize) |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
77 | where |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
78 | G: Fn(&'_ Self) -> V, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
79 | H: Fn(&'_ V) -> O, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
80 | O: PartialOrd, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
81 | { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
82 | let mut res = value(self); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
83 | let initial_fitness = fitness(&res); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
84 | let count = self.merge_spikes(method, |μ| { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
85 | res = value(μ); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
86 | fitness(&res) <= initial_fitness |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
87 | }); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
88 | (res, count) |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
89 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
90 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
91 | /// Attempt to merge spikes that are within radius $ρ$ of each other (unspecified norm). |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
92 | /// |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
93 | /// This method implements [`SpikeMerging::merge_spikes`]. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
94 | fn do_merge_spikes_radius<G>(&mut self, ρ: F, interp: bool, accept: G) -> usize |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
95 | where |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
96 | G: FnMut(&'_ Self) -> bool; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
97 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
98 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
99 | #[replace_float_literals(F::cast_from(literal))] |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
100 | impl<F: Float, const N: usize> DiscreteMeasure<Loc<N, F>, F> { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
101 | /// Attempts to merge spikes with indices `i` and `j`. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
102 | /// |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
103 | /// This assumes that the weights of the two spikes have already been checked not to be zero. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
104 | /// |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
105 | /// The parameter `res` points to the current “result” for [`SpikeMerging::merge_spikes`]. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
106 | /// If the merge is accepted by `accept` returning a [`Some`], `res` will be replaced by its |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
107 | /// return value. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
108 | /// |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
109 | /// Returns the index of `self.spikes` storing the new spike. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
110 | fn attempt_merge<G>( |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
111 | &mut self, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
112 | i: usize, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
113 | j: usize, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
114 | interp: bool, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
115 | accept: &mut G, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
116 | ) -> Option<usize> |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
117 | where |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
118 | G: FnMut(&'_ Self) -> bool, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
119 | { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
120 | let &DeltaMeasure { x: xi, α: αi } = &self.spikes[i]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
121 | let &DeltaMeasure { x: xj, α: αj } = &self.spikes[j]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
122 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
123 | if interp { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
124 | // Merge inplace |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
125 | self.spikes[i].α = 0.0; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
126 | self.spikes[j].α = 0.0; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
127 | let αia = αi.abs(); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
128 | let αja = αj.abs(); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
129 | self.spikes |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
130 | .push(DeltaMeasure { α: αi + αj, x: (xi * αia + xj * αja) / (αia + αja) }); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
131 | if accept(self) { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
132 | Some(self.spikes.len() - 1) |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
133 | } else { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
134 | // Merge not accepted, restore modification |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
135 | self.spikes[i].α = αi; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
136 | self.spikes[j].α = αj; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
137 | self.spikes.pop(); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
138 | None |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
139 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
140 | } else { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
141 | // Attempt merge inplace, first combination |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
142 | self.spikes[i].α = αi + αj; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
143 | self.spikes[j].α = 0.0; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
144 | if accept(self) { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
145 | // Merge accepted |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
146 | Some(i) |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
147 | } else { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
148 | // Attempt merge inplace, second combination |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
149 | self.spikes[i].α = 0.0; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
150 | self.spikes[j].α = αi + αj; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
151 | if accept(self) { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
152 | // Merge accepted |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
153 | Some(j) |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
154 | } else { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
155 | // Merge not accepted, restore modification |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
156 | self.spikes[i].α = αi; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
157 | self.spikes[j].α = αj; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
158 | None |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
159 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
160 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
161 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
162 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
163 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
164 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
165 | /// Sorts a vector of indices into `slice` by `compare`. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
166 | /// |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
167 | /// The closure `compare` operators on references to elements of `slice`. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
168 | /// Returns the sorted vector of indices into `slice`. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
169 | pub fn sort_indices_by<V, F>(slice: &[V], mut compare: F) -> Vec<usize> |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
170 | where |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
171 | F: FnMut(&V, &V) -> Ordering, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
172 | { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
173 | let mut indices = Vec::from_iter(0..slice.len()); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
174 | indices.sort_by(|&i, &j| compare(&slice[i], &slice[j])); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
175 | indices |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
176 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
177 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
178 | #[replace_float_literals(F::cast_from(literal))] |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
179 | impl<F: Float> SpikeMerging<F> for DiscreteMeasure<Loc<1, F>, F> { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
180 | fn do_merge_spikes_radius<G>(&mut self, ρ: F, interp: bool, mut accept: G) -> usize |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
181 | where |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
182 | G: FnMut(&'_ Self) -> bool, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
183 | { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
184 | // Sort by coordinate into an indexing array. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
185 | let mut indices = sort_indices_by(&self.spikes, |&δ1, &δ2| { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
186 | let &Loc([x1]) = &δ1.x; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
187 | let &Loc([x2]) = &δ2.x; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
188 | // nan-ignoring ordering of floats |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
189 | NaNLeast(x1).cmp(&NaNLeast(x2)) |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
190 | }); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
191 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
192 | // Initialise result |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
193 | let mut count = 0; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
194 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
195 | // Scan consecutive pairs and merge if close enough and accepted by `accept`. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
196 | if indices.len() == 0 { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
197 | return count; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
198 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
199 | for k in 0..(indices.len() - 1) { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
200 | let i = indices[k]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
201 | let j = indices[k + 1]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
202 | let &DeltaMeasure { x: Loc([xi]), α: αi } = &self.spikes[i]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
203 | let &DeltaMeasure { x: Loc([xj]), α: αj } = &self.spikes[j]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
204 | debug_assert!(xi <= xj); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
205 | // If close enough, attempt merging |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
206 | if αi != 0.0 && αj != 0.0 && xj <= xi + ρ { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
207 | if let Some(l) = self.attempt_merge(i, j, interp, &mut accept) { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
208 | // For this to work (the debug_assert! to not trigger above), the new |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
209 | // coordinate produced by attempt_merge has to be at most xj. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
210 | indices[k + 1] = l; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
211 | count += 1 |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
212 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
213 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
214 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
215 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
216 | count |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
217 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
218 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
219 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
220 | /// Orders `δ1` and `δ1` according to the first coordinate. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
221 | fn compare_first_coordinate<F: Float>( |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
222 | δ1: &DeltaMeasure<Loc<2, F>, F>, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
223 | δ2: &DeltaMeasure<Loc<2, F>, F>, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
224 | ) -> Ordering { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
225 | let &Loc([x11, ..]) = &δ1.x; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
226 | let &Loc([x21, ..]) = &δ2.x; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
227 | // nan-ignoring ordering of floats |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
228 | NaNLeast(x11).cmp(&NaNLeast(x21)) |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
229 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
230 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
231 | #[replace_float_literals(F::cast_from(literal))] |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
232 | impl<F: Float> SpikeMerging<F> for DiscreteMeasure<Loc<2, F>, F> { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
233 | fn do_merge_spikes_radius<G>(&mut self, ρ: F, interp: bool, mut accept: G) -> usize |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
234 | where |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
235 | G: FnMut(&'_ Self) -> bool, |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
236 | { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
237 | // Sort by first coordinate into an indexing array. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
238 | let mut indices = sort_indices_by(&self.spikes, compare_first_coordinate); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
239 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
240 | // Initialise result |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
241 | let mut count = 0; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
242 | let mut start_scan_2nd = 0; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
243 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
244 | // Scan in order |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
245 | if indices.len() == 0 { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
246 | return count; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
247 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
248 | for k in 0..indices.len() - 1 { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
249 | let i = indices[k]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
250 | let &DeltaMeasure { x: Loc([xi1, xi2]), α: αi } = &self[i]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
251 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
252 | if αi == 0.0 { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
253 | // Nothin to be done if the weight is already zero |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
254 | continue; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
255 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
256 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
257 | let mut closest = None; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
258 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
259 | // Scan for second spike. We start from `start_scan_2nd + 1` with `start_scan_2nd` |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
260 | // the smallest invalid merging index on the previous loop iteration, because a |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
261 | // the _closest_ mergeable spike might have index less than `k` in `indices`, and a |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
262 | // merge with it might have not been attempted with this spike if a different closer |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
263 | // spike was discovered based on the second coordinate. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
264 | 'scan_2nd: for l in (start_scan_2nd + 1)..indices.len() { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
265 | if l == k { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
266 | // Do not attempt to merge a spike with itself |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
267 | continue; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
268 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
269 | let j = indices[l]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
270 | let &DeltaMeasure { x: Loc([xj1, xj2]), α: αj } = &self[j]; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
271 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
272 | if xj1 < xi1 - ρ { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
273 | // Spike `j = indices[l]` has too low first coordinate. Update starting index |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
274 | // for next iteration, and continue scanning. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
275 | start_scan_2nd = l; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
276 | continue 'scan_2nd; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
277 | } else if xj1 > xi1 + ρ { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
278 | // Break out: spike `j = indices[l]` has already too high first coordinate, no |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
279 | // more close enough spikes can be found due to the sorting of `indices`. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
280 | break 'scan_2nd; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
281 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
282 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
283 | // If also second coordinate is close enough, attempt merging if closer than |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
284 | // previously discovered mergeable spikes. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
285 | let d2 = (xi2 - xj2).abs(); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
286 | if αj != 0.0 && d2 <= ρ { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
287 | let r1 = xi1 - xj1; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
288 | let d = (d2 * d2 + r1 * r1).sqrt(); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
289 | match closest { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
290 | None => closest = Some((l, j, d)), |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
291 | Some((_, _, r)) if r > d => closest = Some((l, j, d)), |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
292 | _ => {} |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
293 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
294 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
295 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
296 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
297 | // Attempt merging closest close-enough spike |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
298 | if let Some((l, j, _)) = closest { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
299 | if let Some(n) = self.attempt_merge(i, j, interp, &mut accept) { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
300 | // If merge was succesfull, make new spike candidate for merging. |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
301 | indices[l] = n; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
302 | count += 1; |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
303 | let compare = |i, j| compare_first_coordinate(&self.spikes[i], &self.spikes[j]); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
304 | // Re-sort relevant range of indices |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
305 | if l < k { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
306 | indices[l..k].sort_by(|&i, &j| compare(i, j)); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
307 | } else { |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
308 | indices[k + 1..=l].sort_by(|&i, &j| compare(i, j)); |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
309 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
310 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
311 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
312 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
313 | |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
314 | count |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
315 | } |
|
e8f3b6c55ce7
Initialise repository, separating measure from pointsource_algs
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
316 | } |