light_curve_feature/features/
linear_fit.rs1use crate::evaluator::*;
2use crate::straight_line_fit::fit_straight_line;
3
4macro_const! {
5 const DOC: &str = r"
6Slope, its error and reduced $\chi^2$ of the light curve in the linear fit
7
8Least squares fit of the linear stochastic model with Gaussian noise described by observation
9errors $\{\delta_i\}$:
10$$
11m_i = c + \mathrm{slope} t_i + \delta_i \varepsilon_i
12$$
13where $c$ is a constant,
14$\{\varepsilon_i\}$ are standard distributed random variables.
15
16Feature values are $\mathrm{slope}$, $\sigma_\mathrm{slope}$ and
17$\frac{\sum{((m_i - c - \mathrm{slope} t_i) / \delta_i)^2}}{N - 2}$.
18
19- Depends on: **time**, **magnitude**, **magnitude error**
20- Minimum number of observations: **3**
21- Number of features: **3**
22";
23}
24
25#[doc = DOC!()]
26#[derive(Clone, Default, Debug, Serialize, Deserialize, JsonSchema)]
27pub struct LinearFit {}
28
29impl LinearFit {
30 pub fn new() -> Self {
31 Self {}
32 }
33
34 pub const fn doc() -> &'static str {
35 DOC
36 }
37}
38
39lazy_info!(
40 LINEAR_FIT_INFO,
41 LinearFit,
42 size: 3,
43 min_ts_length: 3,
44 t_required: true,
45 m_required: true,
46 w_required: true,
47 sorting_required: true,
48);
49
50impl FeatureNamesDescriptionsTrait for LinearFit {
51 fn get_names(&self) -> Vec<&str> {
52 vec![
53 "linear_fit_slope",
54 "linear_fit_slope_sigma",
55 "linear_fit_reduced_chi2",
56 ]
57 }
58
59 fn get_descriptions(&self) -> Vec<&str> {
60 vec![
61 "slope of linear fit",
62 "error of slope of linear fit",
63 "linear fit quality (reduced chi2)",
64 ]
65 }
66}
67
68impl<T> FeatureEvaluator<T> for LinearFit
69where
70 T: Float,
71{
72 fn eval(&self, ts: &mut TimeSeries<T>) -> Result<Vec<T>, EvaluatorError> {
73 self.check_ts_length(ts)?;
74 let result = fit_straight_line(ts, true);
75 Ok(vec![
76 result.slope,
77 T::sqrt(result.slope_sigma2),
78 result.reduced_chi2,
79 ])
80 }
81}
82
83#[cfg(test)]
84#[allow(clippy::unreadable_literal)]
85#[allow(clippy::excessive_precision)]
86mod tests {
87 use super::*;
88 use crate::tests::*;
89
90 check_feature!(LinearFit);
91
92 feature_test!(
93 linear_fit,
94 [LinearFit::default()],
95 [1.0544186045473263, 0.7963978113902943, 0.013781209302325587],
96 [0.0_f32, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
97 [
98 0.0_f32, 0.01, 0.04, 0.09, 0.16, 0.25, 0.36, 0.49, 0.64, 0.81, 1.0
99 ],
100 [1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0],
101 );
102}