use crate::linalg::allocator::Allocator;
use crate::linalg::{DefaultAllocator, DimName, OVector};
use crate::od::msr::MeasurementType;
use hifitime::Epoch;
use indexmap::IndexSet;
use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub struct Residual<M>
where
M: DimName,
DefaultAllocator: Allocator<M>,
{
pub epoch: Epoch,
pub prefit: OVector<f64, M>,
pub postfit: OVector<f64, M>,
pub whitened_resid: OVector<f64, M>,
pub ratio: f64,
pub tracker_msr_noise: OVector<f64, M>,
pub rejected: bool,
pub tracker: Option<String>,
pub msr_types: IndexSet<MeasurementType>,
pub real_obs: OVector<f64, M>,
pub computed_obs: OVector<f64, M>,
}
impl<M> Residual<M>
where
M: DimName,
DefaultAllocator: Allocator<M>,
{
pub fn zeros() -> Self {
Self {
epoch: Epoch::from_tai_seconds(0.0),
prefit: OVector::<f64, M>::zeros(),
postfit: OVector::<f64, M>::zeros(),
whitened_resid: OVector::<f64, M>::zeros(),
tracker_msr_noise: OVector::<f64, M>::zeros(),
ratio: 0.0,
rejected: true,
tracker: None,
msr_types: IndexSet::new(),
real_obs: OVector::<f64, M>::zeros(),
computed_obs: OVector::<f64, M>::zeros(),
}
}
pub fn rejected(
epoch: Epoch,
prefit: OVector<f64, M>,
whitened_resid: OVector<f64, M>,
ratio: f64,
tracker_msr_noise: OVector<f64, M>,
real_obs: OVector<f64, M>,
computed_obs: OVector<f64, M>,
) -> Self {
Self {
epoch,
prefit,
postfit: OVector::<f64, M>::zeros() * f64::NAN,
whitened_resid,
ratio,
tracker_msr_noise,
rejected: true,
tracker: None,
msr_types: IndexSet::new(),
real_obs,
computed_obs,
}
}
pub fn accepted(
epoch: Epoch,
prefit: OVector<f64, M>,
whitened_resid: OVector<f64, M>,
postfit: OVector<f64, M>,
ratio: f64,
tracker_msr_noise: OVector<f64, M>,
real_obs: OVector<f64, M>,
computed_obs: OVector<f64, M>,
) -> Self {
Self {
epoch,
prefit,
whitened_resid,
postfit,
ratio,
tracker_msr_noise,
rejected: false,
tracker: None,
msr_types: IndexSet::new(),
real_obs,
computed_obs,
}
}
pub fn prefit(&self, msr_type: MeasurementType) -> Option<f64> {
self.msr_types
.get_index_of(&msr_type)
.map(|idx| self.prefit[idx])
}
pub fn postfit(&self, msr_type: MeasurementType) -> Option<f64> {
self.msr_types
.get_index_of(&msr_type)
.map(|idx| self.postfit[idx])
}
pub fn trk_noise(&self, msr_type: MeasurementType) -> Option<f64> {
self.msr_types
.get_index_of(&msr_type)
.map(|idx| self.tracker_msr_noise[idx])
}
pub fn real_obs(&self, msr_type: MeasurementType) -> Option<f64> {
self.msr_types
.get_index_of(&msr_type)
.map(|idx| self.real_obs[idx])
}
pub fn computed_obs(&self, msr_type: MeasurementType) -> Option<f64> {
self.msr_types
.get_index_of(&msr_type)
.map(|idx| self.computed_obs[idx])
}
pub fn whitened_resid(&self, msr_type: MeasurementType) -> Option<f64> {
self.msr_types
.get_index_of(&msr_type)
.map(|idx| self.whitened_resid[idx])
}
pub fn nis(&self) -> f64 {
self.whitened_resid.norm_squared()
}
}
impl<M> fmt::Display for Residual<M>
where
M: DimName,
DefaultAllocator: Allocator<M> + Allocator<M>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Residual of {:?} from {} at {}: ratio = {:.3}\nPrefit {} Postfit {}",
self.msr_types,
self.tracker.as_ref().unwrap_or(&"Unknown".to_string()),
self.epoch,
self.ratio,
&self.prefit,
&self.postfit
)
}
}
impl<M> fmt::LowerExp for Residual<M>
where
M: DimName,
DefaultAllocator: Allocator<M> + Allocator<M>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Prefit {:e} Postfit {:e}", &self.prefit, &self.postfit)
}
}