Skip to content

Commit 88836b8

Browse files
committed
More PeriodogramPeaks to a new module
1 parent c70abfd commit 88836b8

File tree

6 files changed

+184
-157
lines changed

6 files changed

+184
-157
lines changed

src/feature.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ where
5050
PercentAmplitude,
5151
PercentDifferenceMagnitudePercentile,
5252
Periodogram(Periodogram<T, Self>),
53-
_PeriodogramPeaks,
53+
_PeriodogramPeaks(PeriodogramPeaks),
5454
ReducedChi2,
5555
Skew,
5656
StandardDeviation,

src/features/_periodogram_peaks.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
use crate::evaluator::*;
2+
use crate::evaluator::{Deserialize, EvaluatorInfo, EvaluatorProperties, Serialize};
3+
use crate::peak_indices::peak_indices_reverse_sorted;
4+
use crate::{
5+
number_ending, EvaluatorError, EvaluatorInfoTrait, FeatureEvaluator,
6+
FeatureNamesDescriptionsTrait, Float, TimeSeries,
7+
};
8+
9+
use schemars::JsonSchema;
10+
use std::iter;
11+
12+
macro_const! {
13+
const PERIODOGRAM_PEAKS_DOC: &'static str = r#"
14+
Peak evaluator for [Periodogram]
15+
"#;
16+
}
17+
18+
#[doc(hidden)]
19+
#[doc = PERIODOGRAM_PEAKS_DOC!()]
20+
#[derive(Clone, Debug, Serialize, Deserialize)]
21+
#[serde(
22+
from = "PeriodogramPeaksParameters",
23+
into = "PeriodogramPeaksParameters"
24+
)]
25+
pub struct PeriodogramPeaks {
26+
peaks: usize,
27+
properties: Box<EvaluatorProperties>,
28+
}
29+
30+
impl PeriodogramPeaks {
31+
pub fn new(peaks: usize) -> Self {
32+
assert!(peaks > 0, "Number of peaks should be at least one");
33+
let info = EvaluatorInfo {
34+
size: 2 * peaks,
35+
min_ts_length: 1,
36+
t_required: true,
37+
m_required: true,
38+
w_required: false,
39+
sorting_required: true,
40+
variability_required: false,
41+
};
42+
let names = (0..peaks)
43+
.flat_map(|i| vec![format!("period_{}", i), format!("period_s_to_n_{}", i)])
44+
.collect();
45+
let descriptions = (0..peaks)
46+
.flat_map(|i| {
47+
vec![
48+
format!(
49+
"period of the {}{} highest peak of periodogram",
50+
i + 1,
51+
number_ending(i + 1),
52+
),
53+
format!(
54+
"Spectral density to spectral density standard deviation ratio of \
55+
the {}{} highest peak of periodogram",
56+
i + 1,
57+
number_ending(i + 1)
58+
),
59+
]
60+
})
61+
.collect();
62+
Self {
63+
properties: EvaluatorProperties {
64+
info,
65+
names,
66+
descriptions,
67+
}
68+
.into(),
69+
peaks,
70+
}
71+
}
72+
73+
pub fn get_peaks(&self) -> usize {
74+
self.peaks
75+
}
76+
77+
#[inline]
78+
pub fn default_peaks() -> usize {
79+
1
80+
}
81+
82+
pub fn doc() -> &'static str {
83+
PERIODOGRAM_PEAKS_DOC
84+
}
85+
}
86+
87+
impl Default for PeriodogramPeaks {
88+
fn default() -> Self {
89+
Self::new(Self::default_peaks())
90+
}
91+
}
92+
93+
impl EvaluatorInfoTrait for PeriodogramPeaks {
94+
fn get_info(&self) -> &EvaluatorInfo {
95+
&self.properties.info
96+
}
97+
}
98+
99+
impl FeatureNamesDescriptionsTrait for PeriodogramPeaks {
100+
fn get_names(&self) -> Vec<&str> {
101+
self.properties.names.iter().map(String::as_str).collect()
102+
}
103+
104+
fn get_descriptions(&self) -> Vec<&str> {
105+
self.properties
106+
.descriptions
107+
.iter()
108+
.map(String::as_str)
109+
.collect()
110+
}
111+
}
112+
113+
impl<T> FeatureEvaluator<T> for PeriodogramPeaks
114+
where
115+
T: Float,
116+
{
117+
fn eval_no_ts_check(&self, ts: &mut TimeSeries<T>) -> Result<Vec<T>, EvaluatorError> {
118+
let peak_indices = peak_indices_reverse_sorted(&ts.m.sample);
119+
Ok(peak_indices
120+
.iter()
121+
.flat_map(|&i| {
122+
iter::once(T::two() * T::PI() / ts.t.sample[i])
123+
.chain(iter::once(ts.m.signal_to_noise(ts.m.sample[i])))
124+
})
125+
.chain(iter::repeat(T::zero()))
126+
.take(2 * self.peaks)
127+
.collect())
128+
}
129+
}
130+
131+
#[derive(Serialize, Deserialize, JsonSchema)]
132+
#[serde(rename = "PeriodogramPeaks")]
133+
struct PeriodogramPeaksParameters {
134+
peaks: usize,
135+
}
136+
137+
impl From<PeriodogramPeaks> for PeriodogramPeaksParameters {
138+
fn from(f: PeriodogramPeaks) -> Self {
139+
Self { peaks: f.peaks }
140+
}
141+
}
142+
143+
impl From<PeriodogramPeaksParameters> for PeriodogramPeaks {
144+
fn from(p: PeriodogramPeaksParameters) -> Self {
145+
Self::new(p.peaks)
146+
}
147+
}
148+
149+
impl JsonSchema for PeriodogramPeaks {
150+
json_schema!(PeriodogramPeaksParameters, false);
151+
}

src/features/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! Feature sctructs implements [crate::FeatureEvaluator] trait
22
3+
mod _periodogram_peaks;
4+
pub(crate) use _periodogram_peaks::PeriodogramPeaks;
5+
36
mod amplitude;
47
pub use amplitude::Amplitude;
58

@@ -82,8 +85,8 @@ mod percent_difference_magnitude_percentile;
8285
pub use percent_difference_magnitude_percentile::PercentDifferenceMagnitudePercentile;
8386

8487
mod periodogram;
88+
pub use _periodogram_peaks::PeriodogramPeaks as _PeriodogramPeaks;
8589
pub use periodogram::Periodogram;
86-
pub use periodogram::PeriodogramPeaks as _PeriodogramPeaks;
8790

8891
mod reduced_chi2;
8992
pub use reduced_chi2::ReducedChi2;
@@ -110,4 +113,5 @@ mod villar_fit;
110113
pub use villar_fit::{VillarFit, VillarInitsBounds, VillarLnPrior};
111114

112115
mod weighted_mean;
116+
113117
pub use weighted_mean::WeightedMean;

src/features/periodogram.rs

Lines changed: 12 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -1,162 +1,11 @@
11
use crate::evaluator::*;
22
use crate::extractor::FeatureExtractor;
3-
use crate::peak_indices::peak_indices_reverse_sorted;
3+
use crate::features::_periodogram_peaks::PeriodogramPeaks;
44
use crate::periodogram;
55
use crate::periodogram::{AverageNyquistFreq, NyquistFreq, PeriodogramPower, PeriodogramPowerFft};
66

77
use std::convert::TryInto;
88
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-
}
1609

16110
macro_const! {
16211
const DOC: &str = r#"
@@ -300,8 +149,16 @@ where
300149
/// New [Periodogram] that finds given number of peaks
301150
pub fn new(peaks: usize) -> Self {
302151
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();
305162
let peaks_size_hint = peaks.size_hint();
306163
let peaks_min_ts_length = peaks.min_ts_length();
307164
let info = EvaluatorInfo {
@@ -437,7 +294,7 @@ where
437294
let mut features = feature_extractor.into_vec();
438295
let rest_of_features = features.split_off(1);
439296
let periodogram_peaks: PeriodogramPeaks = features.pop().unwrap().try_into().unwrap();
440-
let peaks = periodogram_peaks.peaks;
297+
let peaks = periodogram_peaks.get_peaks();
441298

442299
Self {
443300
resolution,

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ pub use nl_fit::LmsderCurveFit;
4444
pub use nl_fit::{prior, LnPrior, LnPrior1D};
4545
pub use nl_fit::{CurveFitAlgorithm, McmcCurveFit};
4646

47+
mod number_ending;
48+
pub(crate) use number_ending::number_ending;
49+
4750
#[doc(hidden)]
4851
pub mod periodogram;
4952
pub use periodogram::recurrent_sin_cos::RecurrentSinCos;

0 commit comments

Comments
 (0)