augurs_core/
forecast.rs

1/// Forecast intervals.
2#[derive(Clone, Debug)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4pub struct ForecastIntervals {
5    /// The confidence level for the intervals.
6    pub level: f64,
7    /// The lower prediction intervals.
8    pub lower: Vec<f64>,
9    /// The upper prediction intervals.
10    pub upper: Vec<f64>,
11}
12
13impl ForecastIntervals {
14    /// Return empty forecast intervals.
15    pub fn empty(level: f64) -> ForecastIntervals {
16        Self {
17            level,
18            lower: Vec::new(),
19            upper: Vec::new(),
20        }
21    }
22
23    /// Return empty forecast intervals with the specified capacity.
24    pub fn with_capacity(level: f64, capacity: usize) -> ForecastIntervals {
25        Self {
26            level,
27            lower: Vec::with_capacity(capacity),
28            upper: Vec::with_capacity(capacity),
29        }
30    }
31}
32
33/// A forecast containing point forecasts and, optionally, prediction intervals.
34#[derive(Clone, Debug)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36pub struct Forecast {
37    /// The point forecasts.
38    pub point: Vec<f64>,
39    /// The forecast intervals, if requested and supported
40    /// by the trend model.
41    pub intervals: Option<ForecastIntervals>,
42}
43
44impl Forecast {
45    /// Return an empty forecast.
46    pub fn empty() -> Forecast {
47        Self {
48            point: Vec::new(),
49            intervals: None,
50        }
51    }
52
53    /// Return an empty forecast with the specified capacity.
54    pub fn with_capacity(capacity: usize) -> Forecast {
55        Self {
56            point: Vec::with_capacity(capacity),
57            intervals: None,
58        }
59    }
60
61    /// Return an empty forecast with the specified capacity and level.
62    pub fn with_capacity_and_level(capacity: usize, level: f64) -> Forecast {
63        Self {
64            point: Vec::with_capacity(capacity),
65            intervals: Some(ForecastIntervals::with_capacity(level, capacity)),
66        }
67    }
68
69    /// Chain two forecasts together.
70    ///
71    /// This can be useful after producing in-sample and out-of-sample forecasts
72    /// to combine them into a single forecast.
73    pub fn chain(self, other: Self) -> Self {
74        let mut out = Self::empty();
75        out.point.extend(self.point);
76        out.point.extend(other.point);
77        if let Some(mut intervals) = self.intervals {
78            if let Some(other_intervals) = other.intervals {
79                intervals.lower.extend(other_intervals.lower);
80                intervals.upper.extend(other_intervals.upper);
81            }
82            out.intervals = Some(intervals);
83        } else if let Some(other_intervals) = other.intervals {
84            out.intervals = Some(other_intervals);
85        }
86        out
87    }
88}