nyx_space/od/msr/
measurement.rs1use super::MeasurementType;
20use hifitime::Epoch;
21use indexmap::{IndexMap, IndexSet};
22use log::debug;
23use nalgebra::{allocator::Allocator, DefaultAllocator, DimName, OVector};
24use std::fmt;
25
26#[cfg(feature = "python")]
27use pyo3::prelude::*;
28
29#[cfg_attr(feature = "python", pyclass, pyo3(module = "nyx_space.od"))]
34#[derive(Clone, Debug)]
35pub struct Measurement {
36 pub tracker: String,
38 pub epoch: Epoch,
40 pub data: IndexMap<MeasurementType, f64>,
42 pub rejected: bool,
44}
45
46#[cfg_attr(feature = "python", pymethods)]
47impl Measurement {
48 pub fn correct(&mut self, msr_type: MeasurementType, correction: f64) {
50 if let Some(cur_value) = self.data.get_mut(&msr_type) {
51 let new_value = *cur_value + correction;
52 debug!("corrected {msr_type:?} from {cur_value} to {new_value}");
53 *cur_value = new_value;
54 }
55 }
56
57 pub fn push(&mut self, msr_type: MeasurementType, msr_value: f64) {
58 self.data.insert(msr_type, msr_value);
59 }
60}
61
62impl Measurement {
63 pub fn new(tracker: String, epoch: Epoch) -> Self {
64 Self {
65 tracker,
66 epoch,
67 data: IndexMap::new(),
68 rejected: false,
69 }
70 }
71
72 pub fn with(mut self, msr_type: MeasurementType, msr_value: f64) -> Self {
73 self.push(msr_type, msr_value);
74 self
75 }
76
77 pub fn observation<S: DimName>(&self, types: &IndexSet<MeasurementType>) -> OVector<f64, S>
81 where
82 DefaultAllocator: Allocator<S>,
83 {
84 let mut obs = OVector::zeros();
86 for (i, t) in types.iter().enumerate() {
87 if let Some(msr_value) = self.data.get(t) {
88 obs[i] = *msr_value;
89 }
90 }
91 obs
92 }
93
94 pub fn availability(&self, types: &IndexSet<MeasurementType>) -> Vec<bool> {
96 let mut rtn = vec![false; types.len()];
97 for (i, t) in types.iter().enumerate() {
98 if self.data.contains_key(t) {
99 rtn[i] = true;
100 }
101 }
102 rtn
103 }
104}
105
106impl fmt::Display for Measurement {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 let msrs = self
109 .data
110 .iter()
111 .map(|(msr_type, msr_value)| format!("{msr_type:?} = {msr_value} {}", msr_type.unit()))
112 .collect::<Vec<String>>()
113 .join(", ");
114
115 write!(f, "{} measured {} on {}", self.tracker, msrs, self.epoch)
116 }
117}
118
119impl PartialEq for Measurement {
120 fn eq(&self, other: &Self) -> bool {
121 self.tracker == other.tracker
122 && self.epoch == other.epoch
123 && self.data.iter().all(|(key, &value)| {
124 if let Some(&other_value) = other.data.get(key) {
125 (value - other_value).abs() < 1e-10
126 } else {
127 false
128 }
129 })
130 }
131}