Skip to content

Commit baa0f47

Browse files
committed
Initial impl of MiltiColorPeriodogram
1 parent 88836b8 commit baa0f47

File tree

13 files changed

+393
-62
lines changed

13 files changed

+393
-62
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ clap = { version = "3.2.6", features = ["std", "color", "suggestions", "derive",
6565
criterion = "0.4"
6666
hyperdual = "1.1"
6767
light-curve-common = "0.1.0"
68+
ndarray = { version = "^0.15", features = ["approx-0_5"] }
6869
plotters = { version = "0.3.1", default-features = false, features = ["errorbar", "line_series", "ttf"] }
6970
plotters-bitmap = "0.3.1"
7071
rand = "0.7"

src/data/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
mod data_sample;
22
pub use data_sample::DataSample;
33

4-
mod multi_color_time_series;
4+
pub(crate) mod multi_color_time_series;
55
pub use multi_color_time_series::MultiColorTimeSeries;
66

77
mod sorted_array;
88
pub use sorted_array::SortedArray;
99

1010
mod time_series;
11-
1211
pub use time_series::TimeSeries;

src/data/multi_color_time_series.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::float_trait::Float;
33
use crate::multicolor::PassbandTrait;
44
use crate::{DataSample, PassbandSet};
55

6+
use conv::prelude::*;
67
use itertools::Either;
78
use itertools::EitherOrBoth;
89
use itertools::Itertools;
@@ -23,6 +24,22 @@ where
2324
P: PassbandTrait + 'p,
2425
T: Float,
2526
{
27+
pub fn total_lenu(&self) -> usize {
28+
match self {
29+
Self::Mapping(mapping) => mapping.total_lenu(),
30+
Self::Flat(flat) => flat.total_lenu(),
31+
Self::MappingFlat { flat, .. } => flat.total_lenu(),
32+
}
33+
}
34+
35+
pub fn total_lenf(&self) -> T {
36+
match self {
37+
Self::Mapping(mapping) => mapping.total_lenf(),
38+
Self::Flat(flat) => flat.total_lenf(),
39+
Self::MappingFlat { flat, .. } => flat.total_lenf(),
40+
}
41+
}
42+
2643
pub fn from_map(map: impl Into<BTreeMap<P, TimeSeries<'a, T>>>) -> Self {
2744
Self::Mapping(MappedMultiColorTimeSeries::new(map))
2845
}
@@ -148,13 +165,30 @@ where
148165
)
149166
}
150167

168+
pub fn total_lenu(&self) -> usize {
169+
self.0.values().map(|ts| ts.lenu()).sum()
170+
}
171+
172+
pub fn total_lenf(&self) -> T {
173+
self.total_lenu().value_as::<T>().unwrap()
174+
}
175+
151176
pub fn passbands<'slf>(
152177
&'slf self,
153178
) -> std::collections::btree_map::Keys<'slf, P, TimeSeries<'a, T>>
154179
where
155180
'a: 'slf,
156181
{
157-
self.keys()
182+
self.0.keys()
183+
}
184+
185+
pub fn iter_ts<'slf>(
186+
&'slf self,
187+
) -> std::collections::btree_map::Values<'slf, P, TimeSeries<'a, T>>
188+
where
189+
'a: 'slf,
190+
{
191+
self.0.values()
158192
}
159193

160194
pub fn iter_passband_set<'slf, 'ps>(
@@ -305,4 +339,12 @@ where
305339
passband_set: mapping.keys().cloned().collect(),
306340
}
307341
}
342+
343+
pub fn total_lenu(&self) -> usize {
344+
self.t.sample.len()
345+
}
346+
347+
pub fn total_lenf(&self) -> T {
348+
self.t.sample.len().value_as::<T>().unwrap()
349+
}
308350
}

src/error.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::data::multi_color_time_series::MappedMultiColorTimeSeries;
2+
use crate::float_trait::Float;
13
use crate::PassbandTrait;
24

35
use std::collections::BTreeSet;
@@ -28,6 +30,15 @@ pub enum MultiColorEvaluatorError {
2830
actual: BTreeSet<String>,
2931
desired: BTreeSet<String>,
3032
},
33+
34+
#[error("No time-series long enough: maximum length found is {maximum_actual}, while minimum required is {minimum_required}")]
35+
AllTimeSeriesAreShort {
36+
maximum_actual: usize,
37+
minimum_required: usize,
38+
},
39+
40+
#[error(r#"Underlying feature caused an error: "{0:?}""#)]
41+
UnderlyingEvaluatorError(#[from] EvaluatorError),
3142
}
3243

3344
impl MultiColorEvaluatorError {
@@ -43,6 +54,20 @@ impl MultiColorEvaluatorError {
4354
desired: desired.map(|p| p.name().into()).collect(),
4455
}
4556
}
57+
58+
pub fn all_time_series_short<P, T>(
59+
mapped: &MappedMultiColorTimeSeries<P, T>,
60+
minimum_required: usize,
61+
) -> Self
62+
where
63+
P: PassbandTrait,
64+
T: Float,
65+
{
66+
Self::AllTimeSeriesAreShort {
67+
maximum_actual: mapped.iter_ts().map(|ts| ts.lenu()).max().unwrap_or(0),
68+
minimum_required,
69+
}
70+
}
4671
}
4772

4873
#[derive(Debug, thiserror::Error, PartialEq, Eq)]

src/features/periodogram.rs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::features::_periodogram_peaks::PeriodogramPeaks;
44
use crate::periodogram;
55
use crate::periodogram::{AverageNyquistFreq, NyquistFreq, PeriodogramPower, PeriodogramPowerFft};
66

7+
use ndarray::Array1;
78
use std::convert::TryInto;
89
use std::fmt::Debug;
910

@@ -32,7 +33,7 @@ series without observation errors (unity weights are used if required). You can
3233
#[doc = DOC!()]
3334
#[derive(Clone, Debug, Deserialize, Serialize)]
3435
#[serde(
35-
bound = "T: Float, F: FeatureEvaluator<T> + From<PeriodogramPeaks> + TryInto<PeriodogramPeaks>, <F as std::convert::TryInto<PeriodogramPeaks>>::Error: Debug,",
36+
bound = "T: Float, F: FeatureEvaluator<T> + From<PeriodogramPeaks> + TryInto<PeriodogramPeaks>, <F as TryInto<PeriodogramPeaks>>::Error: Debug,",
3637
from = "PeriodogramParameters<T, F>",
3738
into = "PeriodogramParameters<T, F>"
3839
)]
@@ -43,7 +44,7 @@ where
4344
resolution: f32,
4445
max_freq_factor: f32,
4546
nyquist: NyquistFreq,
46-
feature_extractor: FeatureExtractor<T, F>,
47+
pub(crate) feature_extractor: FeatureExtractor<T, F>,
4748
periodogram_algorithm: PeriodogramPower<T>,
4849
properties: Box<EvaluatorProperties>,
4950
}
@@ -119,24 +120,24 @@ where
119120
self
120121
}
121122

122-
fn periodogram(&self, ts: &mut TimeSeries<T>) -> periodogram::Periodogram<T> {
123+
pub(crate) fn periodogram(&self, t: &[T]) -> periodogram::Periodogram<T> {
123124
periodogram::Periodogram::from_t(
124125
self.periodogram_algorithm.clone(),
125-
ts.t.as_slice(),
126+
t,
126127
self.resolution,
127128
self.max_freq_factor,
128129
self.nyquist.clone(),
129130
)
130131
}
131132

132-
pub fn power(&self, ts: &mut TimeSeries<T>) -> Vec<T> {
133-
self.periodogram(ts).power(ts)
133+
pub fn power(&self, ts: &mut TimeSeries<T>) -> Array1<T> {
134+
self.periodogram(ts.t.as_slice()).power(ts)
134135
}
135136

136-
pub fn freq_power(&self, ts: &mut TimeSeries<T>) -> (Vec<T>, Vec<T>) {
137-
let p = self.periodogram(ts);
137+
pub fn freq_power(&self, ts: &mut TimeSeries<T>) -> (Array1<T>, Array1<T>) {
138+
let p = self.periodogram(ts.t.as_slice());
138139
let power = p.power(ts);
139-
let freq = (0..power.len()).map(|i| p.freq(i)).collect::<Vec<_>>();
140+
let freq = (0..power.len()).map(|i| p.freq_by_index(i)).collect();
140141
(freq, power)
141142
}
142143
}
@@ -190,15 +191,12 @@ impl<T, F> Periodogram<T, F>
190191
where
191192
T: Float,
192193
F: FeatureEvaluator<T> + From<PeriodogramPeaks> + TryInto<PeriodogramPeaks>,
193-
<F as std::convert::TryInto<PeriodogramPeaks>>::Error: Debug,
194+
<F as TryInto<PeriodogramPeaks>>::Error: Debug,
194195
{
195196
fn transform_ts(&self, ts: &mut TimeSeries<T>) -> Result<TmArrays<T>, EvaluatorError> {
196-
self.check_ts_length(ts)?;
197+
self.check_ts(ts)?;
197198
let (freq, power) = self.freq_power(ts);
198-
Ok(TmArrays {
199-
t: freq.into(),
200-
m: power.into(),
201-
})
199+
Ok(TmArrays { t: freq, m: power })
202200
}
203201
}
204202

@@ -225,7 +223,7 @@ impl<T, F> EvaluatorInfoTrait for Periodogram<T, F>
225223
where
226224
T: Float,
227225
F: FeatureEvaluator<T> + From<PeriodogramPeaks> + TryInto<PeriodogramPeaks>,
228-
<F as std::convert::TryInto<PeriodogramPeaks>>::Error: Debug,
226+
<F as TryInto<PeriodogramPeaks>>::Error: Debug,
229227
{
230228
fn get_info(&self) -> &EvaluatorInfo {
231229
&self.properties.info
@@ -236,7 +234,7 @@ impl<T, F> FeatureNamesDescriptionsTrait for Periodogram<T, F>
236234
where
237235
T: Float,
238236
F: FeatureEvaluator<T> + From<PeriodogramPeaks> + TryInto<PeriodogramPeaks>,
239-
<F as std::convert::TryInto<PeriodogramPeaks>>::Error: Debug,
237+
<F as TryInto<PeriodogramPeaks>>::Error: Debug,
240238
{
241239
fn get_names(&self) -> Vec<&str> {
242240
self.properties.names.iter().map(String::as_str).collect()
@@ -255,7 +253,7 @@ impl<T, F> FeatureEvaluator<T> for Periodogram<T, F>
255253
where
256254
T: Float,
257255
F: FeatureEvaluator<T> + From<PeriodogramPeaks> + TryInto<PeriodogramPeaks>,
258-
<F as std::convert::TryInto<PeriodogramPeaks>>::Error: Debug,
256+
<F as TryInto<PeriodogramPeaks>>::Error: Debug,
259257
{
260258
transformer_eval!();
261259
}
@@ -279,7 +277,7 @@ impl<T, F> From<Periodogram<T, F>> for PeriodogramParameters<T, F>
279277
where
280278
T: Float,
281279
F: FeatureEvaluator<T> + From<PeriodogramPeaks> + TryInto<PeriodogramPeaks>,
282-
<F as std::convert::TryInto<PeriodogramPeaks>>::Error: Debug,
280+
<F as TryInto<PeriodogramPeaks>>::Error: Debug,
283281
{
284282
fn from(f: Periodogram<T, F>) -> Self {
285283
let Periodogram {

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub use float_trait::Float;
3232

3333
mod lnerfc;
3434

35-
mod multicolor;
35+
pub mod multicolor;
3636
pub use multicolor::*;
3737

3838
mod nl_fit;

src/multicolor/features/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ pub use color_of_median::ColorOfMedian;
66

77
mod color_of_minimum;
88
pub use color_of_minimum::ColorOfMinimum;
9+
10+
mod multi_color_periodogram;
11+
pub use multi_color_periodogram::MultiColorPeriodogram;

0 commit comments

Comments
 (0)