doris_rs/record/
measurement.rs

1#[cfg(doc)]
2use crate::prelude::{TimeScale, DORIS};
3
4use crate::prelude::{ClockOffset, GroundStation, Matcher, Observable, Observation};
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use itertools::Itertools;
10use std::collections::BTreeMap;
11
12/// [ObservationKey] is used to store [GroundStation]s observations uniquely
13#[derive(Clone, Debug, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct ObservationKey {
16    /// [GroundStation] being observed
17    pub station: GroundStation,
18
19    /// [Observable] determines the physics and measurement unit
20    pub observable: Observable,
21}
22
23/// [DORIS] Measurements (also referred to as "Observations") of a [GroundStation]
24#[derive(Clone, Debug, Default, PartialEq)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26pub struct Measurements {
27    /// Satellite (=measurement system) [ClockOffset].
28    pub satellite_clock_offset: Option<ClockOffset>,
29
30    /// Observations indexed [Observable]s, measurement unit varies.
31    pub observations: BTreeMap<ObservationKey, Observation>,
32}
33
34impl Measurements {
35    /// Add a new observation to this set of [Measurements]  
36    pub fn add_observation(
37        &mut self,
38        station: GroundStation,
39        observable: Observable,
40        observation: Observation,
41    ) {
42        self.observations.insert(
43            ObservationKey {
44                station,
45                observable,
46            },
47            observation,
48        );
49    }
50
51    /// Updates this set of [Measurements] with a new observation
52    pub fn with_observation(
53        &self,
54        station: GroundStation,
55        observable: Observable,
56        observation: Observation,
57    ) -> Self {
58        let mut s = self.clone();
59        s.observations.insert(
60            ObservationKey {
61                station,
62                observable,
63            },
64            observation,
65        );
66        s
67    }
68
69    /// Returns list of [Observable]s measured at this epoch, regardless of the observed site.
70    pub fn observables(&self) -> Box<dyn Iterator<Item = Observable> + '_> {
71        Box::new(self.observations.keys().map(|k| k.observable).unique())
72    }
73
74    /// Returns list of [Observable]s measured for this given site at attached epoch.
75    pub fn station_observables<'a>(
76        &'a self,
77        matcher: &'a Matcher<'a>,
78    ) -> Box<dyn Iterator<Item = Observable> + '_> {
79        Box::new(
80            self.observations
81                .keys()
82                .filter_map(|k| {
83                    if k.station.matches(matcher) {
84                        Some(k.observable)
85                    } else {
86                        None
87                    }
88                })
89                .unique(),
90        )
91    }
92
93    /// Copies and returns [Measurements] with updated [ClockOffset]
94    pub fn with_satellite_clock_offset(&self, clock_offset: ClockOffset) -> Self {
95        let mut s = self.clone();
96        s.satellite_clock_offset = Some(clock_offset);
97        s
98    }
99}