light_curve_feature/
evaluator.rs1pub use crate::data::TimeSeries;
2pub use crate::error::EvaluatorError;
3pub use crate::float_trait::Float;
4
5use enum_dispatch::enum_dispatch;
6pub use lazy_static::lazy_static;
7pub use macro_const::macro_const;
8use ndarray::Array1;
9pub use schemars::JsonSchema;
10use serde::de::DeserializeOwned;
11pub use serde::{Deserialize, Serialize};
12pub use std::fmt::Debug;
13
14#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
15pub struct EvaluatorInfo {
16 pub size: usize,
17 pub min_ts_length: usize,
18 pub t_required: bool,
19 pub m_required: bool,
20 pub w_required: bool,
21 pub sorting_required: bool,
22 pub variability_required: bool,
23}
24
25#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
26pub struct EvaluatorProperties {
27 pub info: EvaluatorInfo,
28 pub names: Vec<String>,
29 pub descriptions: Vec<String>,
30}
31
32#[enum_dispatch]
33pub trait EvaluatorInfoTrait {
34 fn get_info(&self) -> &EvaluatorInfo;
36
37 fn size_hint(&self) -> usize {
41 self.get_info().size
42 }
43
44 fn min_ts_length(&self) -> usize {
46 self.get_info().min_ts_length
47 }
48
49 fn is_t_required(&self) -> bool {
51 self.get_info().t_required
52 }
53
54 fn is_m_required(&self) -> bool {
56 self.get_info().m_required
57 }
58
59 fn is_w_required(&self) -> bool {
61 self.get_info().w_required
62 }
63
64 fn is_sorting_required(&self) -> bool {
66 self.get_info().sorting_required
67 }
68
69 fn is_variability_required(&self) -> bool {
71 self.get_info().variability_required
72 }
73
74 fn check_ts<F>(&self, ts: &mut TimeSeries<F>) -> Result<(), EvaluatorError>
75 where
76 F: Float,
77 {
78 self.check_ts_length(ts)?;
79 self.check_ts_variability(ts)
80 }
81
82 fn check_ts_length<F>(&self, ts: &TimeSeries<F>) -> Result<(), EvaluatorError>
84 where
85 F: Float,
86 {
87 let length = ts.lenu();
88 if length < self.min_ts_length() {
89 Err(EvaluatorError::ShortTimeSeries {
90 actual: length,
91 minimum: self.min_ts_length(),
92 })
93 } else {
94 Ok(())
95 }
96 }
97
98 fn check_ts_variability<F>(&self, ts: &mut TimeSeries<F>) -> Result<(), EvaluatorError>
100 where
101 F: Float,
102 {
103 if self.is_variability_required() && ts.is_plateau() {
104 Err(EvaluatorError::FlatTimeSeries)
105 } else {
106 Ok(())
107 }
108 }
109}
110
111#[enum_dispatch]
112pub trait FeatureNamesDescriptionsTrait {
113 fn get_names(&self) -> Vec<&str>;
116
117 fn get_descriptions(&self) -> Vec<&str>;
120}
121
122#[enum_dispatch]
124pub trait FeatureEvaluator<T: Float>:
125 FeatureNamesDescriptionsTrait
126 + EvaluatorInfoTrait
127 + Send
128 + Clone
129 + Debug
130 + Serialize
131 + DeserializeOwned
132 + JsonSchema
133{
134 fn eval_no_ts_check(&self, ts: &mut TimeSeries<T>) -> Result<Vec<T>, EvaluatorError>;
136
137 fn eval(&self, ts: &mut TimeSeries<T>) -> Result<Vec<T>, EvaluatorError> {
139 self.check_ts(ts)?;
140 self.eval_no_ts_check(ts)
141 }
142
143 fn eval_or_fill(&self, ts: &mut TimeSeries<T>, fill_value: T) -> Vec<T> {
145 match self.eval(ts) {
146 Ok(v) => v,
147 Err(_) => vec![fill_value; self.size_hint()],
148 }
149 }
150}
151
152pub trait OwnedArrays<T>
153where
154 T: Float,
155{
156 fn ts(self) -> TimeSeries<'static, T>;
157}
158
159pub struct TmArrays<T> {
160 pub t: Array1<T>,
161 pub m: Array1<T>,
162}
163
164impl<T> OwnedArrays<T> for TmArrays<T>
165where
166 T: Float,
167{
168 fn ts(self) -> TimeSeries<'static, T> {
169 TimeSeries::new_without_weight(self.t, self.m)
170 }
171}
172
173pub struct TmwArrays<T> {
174 pub t: Array1<T>,
175 pub m: Array1<T>,
176 pub w: Array1<T>,
177}
178
179impl<T> OwnedArrays<T> for TmwArrays<T>
180where
181 T: Float,
182{
183 fn ts(self) -> TimeSeries<'static, T> {
184 TimeSeries::new(self.t, self.m, self.w)
185 }
186}