#[cfg(doc)]
use crate::prelude::{TimeScale, DORIS};
use crate::prelude::{ClockOffset, GroundStation, Matcher, Observable, Observation};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use itertools::Itertools;
use std::collections::BTreeMap;
#[derive(Clone, Debug, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ObservationKey {
pub station: GroundStation,
pub observable: Observable,
}
#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Measurements {
pub satellite_clock_offset: Option<ClockOffset>,
pub observations: BTreeMap<ObservationKey, Observation>,
}
impl Measurements {
pub fn add_observation(
&mut self,
station: GroundStation,
observable: Observable,
observation: Observation,
) {
self.observations.insert(
ObservationKey {
station,
observable,
},
observation,
);
}
pub fn with_observation(
&self,
station: GroundStation,
observable: Observable,
observation: Observation,
) -> Self {
let mut s = self.clone();
s.observations.insert(
ObservationKey {
station,
observable,
},
observation,
);
s
}
pub fn observables(&self) -> Box<dyn Iterator<Item = Observable> + '_> {
Box::new(self.observations.keys().map(|k| k.observable).unique())
}
pub fn station_observables<'a>(
&'a self,
matcher: &'a Matcher<'a>,
) -> Box<dyn Iterator<Item = Observable> + '_> {
Box::new(
self.observations
.keys()
.filter_map(|k| {
if k.station.matches(matcher) {
Some(k.observable)
} else {
None
}
})
.unique(),
)
}
pub fn with_satellite_clock_offset(&self, clock_offset: ClockOffset) -> Self {
let mut s = self.clone();
s.satellite_clock_offset = Some(clock_offset);
s
}
}