1use crate::linalg::allocator::Allocator;
20use crate::linalg::{DefaultAllocator, DimName, OVector};
21use crate::od::msr::MeasurementType;
22use hifitime::Epoch;
23use indexmap::IndexSet;
24use std::fmt;
25
26#[derive(Debug, Clone, PartialEq)]
28pub struct Residual<M>
29where
30 M: DimName,
31 DefaultAllocator: Allocator<M>,
32{
33 pub epoch: Epoch,
35 pub prefit: OVector<f64, M>,
37 pub postfit: OVector<f64, M>,
39 pub ratio: f64,
43 pub tracker_msr_noise: OVector<f64, M>,
45 pub rejected: bool,
47 pub tracker: Option<String>,
49 pub msr_types: IndexSet<MeasurementType>,
51 pub real_obs: OVector<f64, M>,
53 pub computed_obs: OVector<f64, M>,
55}
56
57impl<M> Residual<M>
58where
59 M: DimName,
60 DefaultAllocator: Allocator<M>,
61{
62 pub fn zeros() -> Self {
64 Self {
65 epoch: Epoch::from_tai_seconds(0.0),
66 prefit: OVector::<f64, M>::zeros(),
67 postfit: OVector::<f64, M>::zeros(),
68 tracker_msr_noise: OVector::<f64, M>::zeros(),
69 ratio: 0.0,
70 rejected: true,
71 tracker: None,
72 msr_types: IndexSet::new(),
73 real_obs: OVector::<f64, M>::zeros(),
74 computed_obs: OVector::<f64, M>::zeros(),
75 }
76 }
77
78 pub fn rejected(
80 epoch: Epoch,
81 prefit: OVector<f64, M>,
82 ratio: f64,
83 tracker_msr_covar: OVector<f64, M>,
84 real_obs: OVector<f64, M>,
85 computed_obs: OVector<f64, M>,
86 ) -> Self {
87 Self {
88 epoch,
89 prefit,
90 postfit: OVector::<f64, M>::zeros(),
91 ratio,
92 tracker_msr_noise: tracker_msr_covar.map(|x| x.sqrt()),
93 rejected: true,
94 tracker: None,
95 msr_types: IndexSet::new(),
96 real_obs,
97 computed_obs,
98 }
99 }
100
101 pub fn accepted(
102 epoch: Epoch,
103 prefit: OVector<f64, M>,
104 postfit: OVector<f64, M>,
105 ratio: f64,
106 tracker_msr_covar: OVector<f64, M>,
107 real_obs: OVector<f64, M>,
108 computed_obs: OVector<f64, M>,
109 ) -> Self {
110 Self {
111 epoch,
112 prefit,
113 postfit,
114 ratio,
115 tracker_msr_noise: tracker_msr_covar.map(|x| x.sqrt()),
116 rejected: false,
117 tracker: None,
118 msr_types: IndexSet::new(),
119 real_obs,
120 computed_obs,
121 }
122 }
123
124 pub fn prefit(&self, msr_type: MeasurementType) -> Option<f64> {
126 self.msr_types
127 .get_index_of(&msr_type)
128 .map(|idx| self.prefit[idx])
129 }
130
131 pub fn postfit(&self, msr_type: MeasurementType) -> Option<f64> {
133 self.msr_types
134 .get_index_of(&msr_type)
135 .map(|idx| self.postfit[idx])
136 }
137
138 pub fn trk_noise(&self, msr_type: MeasurementType) -> Option<f64> {
140 self.msr_types
141 .get_index_of(&msr_type)
142 .map(|idx| self.tracker_msr_noise[idx])
143 }
144
145 pub fn real_obs(&self, msr_type: MeasurementType) -> Option<f64> {
147 self.msr_types
148 .get_index_of(&msr_type)
149 .map(|idx| self.real_obs[idx])
150 }
151
152 pub fn computed_obs(&self, msr_type: MeasurementType) -> Option<f64> {
154 self.msr_types
155 .get_index_of(&msr_type)
156 .map(|idx| self.computed_obs[idx])
157 }
158}
159
160impl<M> fmt::Display for Residual<M>
161where
162 M: DimName,
163 DefaultAllocator: Allocator<M> + Allocator<M>,
164{
165 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
166 write!(
167 f,
168 "Residual of {:?} from {} at {}: ratio = {:.3}\nPrefit {} Postfit {}",
169 self.msr_types,
170 self.tracker.as_ref().unwrap_or(&"Unknown".to_string()),
171 self.epoch,
172 self.ratio,
173 &self.prefit,
174 &self.postfit
175 )
176 }
177}
178
179impl<M> fmt::LowerExp for Residual<M>
180where
181 M: DimName,
182 DefaultAllocator: Allocator<M> + Allocator<M>,
183{
184 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185 write!(f, "Prefit {:e} Postfit {:e}", &self.prefit, &self.postfit)
186 }
187}