|
1 | 1 | use crate::evaluator::*; |
2 | 2 | use crate::extractor::FeatureExtractor; |
3 | | -use crate::peak_indices::peak_indices_reverse_sorted; |
| 3 | +use crate::features::_periodogram_peaks::PeriodogramPeaks; |
4 | 4 | use crate::periodogram; |
5 | 5 | use crate::periodogram::{AverageNyquistFreq, NyquistFreq, PeriodogramPower, PeriodogramPowerFft}; |
6 | 6 |
|
7 | 7 | use std::convert::TryInto; |
8 | 8 | use std::fmt::Debug; |
9 | | -use std::iter; |
10 | | - |
11 | | -fn number_ending(i: usize) -> &'static str { |
12 | | - #[allow(clippy::match_same_arms)] |
13 | | - match (i % 10, i % 100) { |
14 | | - (1, 11) => "th", |
15 | | - (1, _) => "st", |
16 | | - (2, 12) => "th", |
17 | | - (2, _) => "nd", |
18 | | - (3, 13) => "th", |
19 | | - (3, _) => "rd", |
20 | | - (_, _) => "th", |
21 | | - } |
22 | | -} |
23 | | - |
24 | | -macro_const! { |
25 | | - const PERIODOGRAM_PEAK_DOC: &'static str = r#" |
26 | | -Peak evaluator for [Periodogram] |
27 | | -"#; |
28 | | -} |
29 | | - |
30 | | -#[doc(hidden)] |
31 | | -#[doc = PERIODOGRAM_PEAK_DOC!()] |
32 | | -#[derive(Clone, Debug, Serialize, Deserialize)] |
33 | | -#[serde( |
34 | | - from = "PeriodogramPeaksParameters", |
35 | | - into = "PeriodogramPeaksParameters" |
36 | | -)] |
37 | | -pub struct PeriodogramPeaks { |
38 | | - peaks: usize, |
39 | | - properties: Box<EvaluatorProperties>, |
40 | | -} |
41 | | - |
42 | | -impl PeriodogramPeaks { |
43 | | - pub fn new(peaks: usize) -> Self { |
44 | | - assert!(peaks > 0, "Number of peaks should be at least one"); |
45 | | - let info = EvaluatorInfo { |
46 | | - size: 2 * peaks, |
47 | | - min_ts_length: 1, |
48 | | - t_required: true, |
49 | | - m_required: true, |
50 | | - w_required: false, |
51 | | - sorting_required: true, |
52 | | - variability_required: false, |
53 | | - }; |
54 | | - let names = (0..peaks) |
55 | | - .flat_map(|i| vec![format!("period_{}", i), format!("period_s_to_n_{}", i)]) |
56 | | - .collect(); |
57 | | - let descriptions = (0..peaks) |
58 | | - .flat_map(|i| { |
59 | | - vec![ |
60 | | - format!( |
61 | | - "period of the {}{} highest peak of periodogram", |
62 | | - i + 1, |
63 | | - number_ending(i + 1), |
64 | | - ), |
65 | | - format!( |
66 | | - "Spectral density to spectral density standard deviation ratio of \ |
67 | | - the {}{} highest peak of periodogram", |
68 | | - i + 1, |
69 | | - number_ending(i + 1) |
70 | | - ), |
71 | | - ] |
72 | | - }) |
73 | | - .collect(); |
74 | | - Self { |
75 | | - properties: EvaluatorProperties { |
76 | | - info, |
77 | | - names, |
78 | | - descriptions, |
79 | | - } |
80 | | - .into(), |
81 | | - peaks, |
82 | | - } |
83 | | - } |
84 | | - |
85 | | - #[inline] |
86 | | - pub fn default_peaks() -> usize { |
87 | | - 1 |
88 | | - } |
89 | | - |
90 | | - pub fn doc() -> &'static str { |
91 | | - PERIODOGRAM_PEAK_DOC |
92 | | - } |
93 | | -} |
94 | | - |
95 | | -impl Default for PeriodogramPeaks { |
96 | | - fn default() -> Self { |
97 | | - Self::new(Self::default_peaks()) |
98 | | - } |
99 | | -} |
100 | | - |
101 | | -impl EvaluatorInfoTrait for PeriodogramPeaks { |
102 | | - fn get_info(&self) -> &EvaluatorInfo { |
103 | | - &self.properties.info |
104 | | - } |
105 | | -} |
106 | | - |
107 | | -impl FeatureNamesDescriptionsTrait for PeriodogramPeaks { |
108 | | - fn get_names(&self) -> Vec<&str> { |
109 | | - self.properties.names.iter().map(String::as_str).collect() |
110 | | - } |
111 | | - |
112 | | - fn get_descriptions(&self) -> Vec<&str> { |
113 | | - self.properties |
114 | | - .descriptions |
115 | | - .iter() |
116 | | - .map(String::as_str) |
117 | | - .collect() |
118 | | - } |
119 | | -} |
120 | | - |
121 | | -impl<T> FeatureEvaluator<T> for PeriodogramPeaks |
122 | | -where |
123 | | - T: Float, |
124 | | -{ |
125 | | - fn eval_no_ts_check(&self, ts: &mut TimeSeries<T>) -> Result<Vec<T>, EvaluatorError> { |
126 | | - let peak_indices = peak_indices_reverse_sorted(&ts.m.sample); |
127 | | - Ok(peak_indices |
128 | | - .iter() |
129 | | - .flat_map(|&i| { |
130 | | - iter::once(T::two() * T::PI() / ts.t.sample[i]) |
131 | | - .chain(iter::once(ts.m.signal_to_noise(ts.m.sample[i]))) |
132 | | - }) |
133 | | - .chain(iter::repeat(T::zero())) |
134 | | - .take(2 * self.peaks) |
135 | | - .collect()) |
136 | | - } |
137 | | -} |
138 | | - |
139 | | -#[derive(Serialize, Deserialize, JsonSchema)] |
140 | | -#[serde(rename = "PeriodogramPeaks")] |
141 | | -struct PeriodogramPeaksParameters { |
142 | | - peaks: usize, |
143 | | -} |
144 | | - |
145 | | -impl From<PeriodogramPeaks> for PeriodogramPeaksParameters { |
146 | | - fn from(f: PeriodogramPeaks) -> Self { |
147 | | - Self { peaks: f.peaks } |
148 | | - } |
149 | | -} |
150 | | - |
151 | | -impl From<PeriodogramPeaksParameters> for PeriodogramPeaks { |
152 | | - fn from(p: PeriodogramPeaksParameters) -> Self { |
153 | | - Self::new(p.peaks) |
154 | | - } |
155 | | -} |
156 | | - |
157 | | -impl JsonSchema for PeriodogramPeaks { |
158 | | - json_schema!(PeriodogramPeaksParameters, false); |
159 | | -} |
160 | 9 |
|
161 | 10 | macro_const! { |
162 | 11 | const DOC: &str = r#" |
@@ -300,8 +149,16 @@ where |
300 | 149 | /// New [Periodogram] that finds given number of peaks |
301 | 150 | pub fn new(peaks: usize) -> Self { |
302 | 151 | let peaks = PeriodogramPeaks::new(peaks); |
303 | | - let peak_names = peaks.properties.names.clone(); |
304 | | - let peak_descriptions = peaks.properties.descriptions.clone(); |
| 152 | + let peak_names = peaks |
| 153 | + .get_names() |
| 154 | + .into_iter() |
| 155 | + .map(ToOwned::to_owned) |
| 156 | + .collect(); |
| 157 | + let peak_descriptions = peaks |
| 158 | + .get_descriptions() |
| 159 | + .into_iter() |
| 160 | + .map(ToOwned::to_owned) |
| 161 | + .collect(); |
305 | 162 | let peaks_size_hint = peaks.size_hint(); |
306 | 163 | let peaks_min_ts_length = peaks.min_ts_length(); |
307 | 164 | let info = EvaluatorInfo { |
@@ -437,7 +294,7 @@ where |
437 | 294 | let mut features = feature_extractor.into_vec(); |
438 | 295 | let rest_of_features = features.split_off(1); |
439 | 296 | let periodogram_peaks: PeriodogramPeaks = features.pop().unwrap().try_into().unwrap(); |
440 | | - let peaks = periodogram_peaks.peaks; |
| 297 | + let peaks = periodogram_peaks.get_peaks(); |
441 | 298 |
|
442 | 299 | Self { |
443 | 300 | resolution, |
|
0 commit comments