1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
//! Time Series basic operations /// Time Series with normalized data /// * start_time - Timestamp of the first point of the TimeSeries (seconds) /// * resolution - TimeSeries index resolution in seconds /// * data - Data points #[derive(Clone, Debug)] pub struct TimeSeries { start_time: i64, resolution: i64, data: Vec<f32>, } impl TimeSeries { /// Create a new Time Series pub fn new(start_time: i64, resolution: i64, data: Vec<f32>) -> TimeSeries { TimeSeries { start_time, resolution, data } } /// Returns the number of elements in the series. /// /// # Example /// /// ``` /// use timeseries::timeseries::TimeSeries; /// /// let ds = vec![1.0, 2.0, 3.0]; /// let ts = TimeSeries::new(0, 10, ds); /// assert_eq!(ts.len(), 3); /// ``` #[inline] pub fn len(&self) -> usize { self.data.len() } /// Return element by its time index. /// /// # Example /// /// ``` /// use timeseries::timeseries::TimeSeries; /// /// let ds = vec![1.0, 2.0, 3.0]; /// let ts = TimeSeries::new(0, 10, ds); /// assert_eq!(ts.at(10), 2.0); /// assert_eq!(ts.at(17), 2.0); /// assert_eq!(ts.at(50), 0.0); /// ``` #[inline] pub fn at(&self, idx: i64) -> f32 { let pos = self.index_to_pos(idx); self.iat(pos) } /// Return element by its integer index. Return 0 if index out of bounds. /// /// # Example /// /// ``` /// use timeseries::timeseries::TimeSeries; /// /// let ds = vec![1.0, 2.0, 3.0]; /// let ts = TimeSeries::new(0, 10, ds); /// assert_eq!(ts.iat(1), 2.0); /// assert_eq!(ts.iat(10), 0.0); /// ``` #[inline] pub fn iat(&self, pos: usize) -> f32 { if pos < self.len() { self.data[pos] } else { 0.0 } } /// Return slice of data based on index range /// /// # Example /// /// ``` /// use timeseries::timeseries::TimeSeries; /// /// let ds = vec![1.0, 2.0, 3.0, 4.0, 5.0]; /// let ts = TimeSeries::new(0, 10, ds); /// assert_eq!(ts.data_slice(0, 45), [1.0, 2.0, 3.0, 4.0]); /// ``` pub fn data_slice(&self, start_index: i64, end_index: i64) -> &[f32] { let start = self.index_to_pos(start_index); let start_pos = if start >= self.len() { self.len() - 1 } else { start }; let end = self.index_to_pos(end_index); let end_pos = if start >= self.len() { self.len() - 1 } else if end < start_pos { start_pos } else { end }; &self.data[start_pos..end_pos] } /// Convert index to integer position #[inline] fn index_to_pos(&self, idx: i64) -> usize { ((idx - self.start_time) / self.resolution) as usize } }