light_curve_feature/
evaluator.rs1pub use crate::error::EvaluatorError;
2pub use crate::float_trait::Float;
3pub use crate::time_series::TimeSeries;
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)]
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}
23
24#[derive(Clone, Debug)]
25pub struct EvaluatorProperties {
26 pub info: EvaluatorInfo,
27 pub names: Vec<String>,
28 pub descriptions: Vec<String>,
29}
30
31#[enum_dispatch]
36pub trait EvaluatorInfoTrait {
37 fn get_info(&self) -> &EvaluatorInfo;
39
40 fn size_hint(&self) -> usize {
44 self.get_info().size
45 }
46
47 fn min_ts_length(&self) -> usize {
49 self.get_info().min_ts_length
50 }
51
52 fn is_t_required(&self) -> bool {
54 self.get_info().t_required
55 }
56
57 fn is_m_required(&self) -> bool {
59 self.get_info().m_required
60 }
61
62 fn is_w_required(&self) -> bool {
64 self.get_info().w_required
65 }
66
67 fn is_sorting_required(&self) -> bool {
69 self.get_info().sorting_required
70 }
71}
72
73#[enum_dispatch]
83pub trait FeatureNamesDescriptionsTrait {
84 fn get_names(&self) -> Vec<&str>;
87
88 fn get_descriptions(&self) -> Vec<&str>;
91}
92
93#[enum_dispatch]
116pub trait FeatureEvaluator<T: Float>:
117 FeatureNamesDescriptionsTrait
118 + EvaluatorInfoTrait
119 + Send
120 + Clone
121 + Debug
122 + Serialize
123 + DeserializeOwned
124 + JsonSchema
125{
126 fn eval(&self, ts: &mut TimeSeries<T>) -> Result<Vec<T>, EvaluatorError>;
128
129 fn eval_or_fill(&self, ts: &mut TimeSeries<T>, fill_value: T) -> Vec<T> {
131 match self.eval(ts) {
132 Ok(v) => v,
133 Err(_) => vec![fill_value; self.size_hint()],
134 }
135 }
136
137 fn check_ts_length(&self, ts: &TimeSeries<T>) -> Result<usize, EvaluatorError> {
139 let length = ts.lenu();
140 if length < self.min_ts_length() {
141 Err(EvaluatorError::ShortTimeSeries {
142 actual: length,
143 minimum: self.min_ts_length(),
144 })
145 } else {
146 Ok(length)
147 }
148 }
149}
150
151pub fn get_nonzero_m_std<T: Float>(ts: &mut TimeSeries<T>) -> Result<T, EvaluatorError> {
152 let std = ts.m.get_std();
153 if std.is_zero() || ts.is_plateau() {
154 Err(EvaluatorError::FlatTimeSeries)
155 } else {
156 Ok(std)
157 }
158}
159
160pub fn get_nonzero_m_std2<T: Float>(ts: &mut TimeSeries<T>) -> Result<T, EvaluatorError> {
161 let std2 = ts.m.get_std2();
162 if std2.is_zero() || ts.is_plateau() {
163 Err(EvaluatorError::FlatTimeSeries)
164 } else {
165 Ok(std2)
166 }
167}
168
169pub fn get_nonzero_reduced_chi2<T: Float>(ts: &mut TimeSeries<T>) -> Result<T, EvaluatorError> {
170 let reduced_chi2 = ts.get_m_reduced_chi2();
171 if reduced_chi2.is_zero() || ts.is_plateau() {
172 Err(EvaluatorError::FlatTimeSeries)
173 } else {
174 Ok(reduced_chi2)
175 }
176}
177
178pub trait OwnedArrays<T>
179where
180 T: Float,
181{
182 fn ts(self) -> TimeSeries<'static, T>;
183}
184
185pub struct TmArrays<T> {
186 pub t: Array1<T>,
187 pub m: Array1<T>,
188}
189
190impl<T> OwnedArrays<T> for TmArrays<T>
191where
192 T: Float,
193{
194 fn ts(self) -> TimeSeries<'static, T> {
195 TimeSeries::new_without_weight(self.t, self.m)
196 }
197}
198
199pub struct TmwArrays<T> {
200 pub t: Array1<T>,
201 pub m: Array1<T>,
202 pub w: Array1<T>,
203}
204
205impl<T> OwnedArrays<T> for TmwArrays<T>
206where
207 T: Float,
208{
209 fn ts(self) -> TimeSeries<'static, T> {
210 TimeSeries::new(self.t, self.m, self.w)
211 }
212}