use nalgebra::Matrix2;
use photom::observation_dataset::observation::Observation;
pub mod diff_cor;
pub mod least_square;
pub mod obs_dataset_api;
pub mod obs_fit_data;
pub mod outlier_rejection;
pub mod single_iteration;
pub use diff_cor::{
run_differential_correction, DifferentialCorrectionConfig, DifferentialCorrectionOutput,
};
pub use least_square::{
angular_diff, rescale_covariance, solve_weighted_least_squares, DifferentialCorrectionResult,
ObservationEquation, OrbitalUncertainty,
};
pub use obs_dataset_api::FitLSQ;
pub use obs_fit_data::{ObsFitData, ObsSelection};
pub use outlier_rejection::{update_observation_selection, OutlierRejectionConfig};
pub use single_iteration::{single_iteration, SingleIterationResult};
use crate::{
cache::OutfitCache, constants::FitOrbitResult,
initial_orbit_determination::obs_dataset_api::run_iod_on_observations, IODParams, JPLEphem,
OutfitError,
};
pub fn observation_weight(obs: &Observation, rejected: bool) -> Matrix2<f64> {
if rejected {
return Matrix2::zeros();
}
let sa2 = obs.equ_coord().ra_error.powf(2.0);
let sd2 = obs.equ_coord().dec_error.powf(2.0);
Matrix2::new(1.0 / sa2, 0.0, 0.0, 1.0 / sd2)
}
pub fn differential_correction(
observations: &[Observation],
cache: &OutfitCache,
jpl: &JPLEphem,
iod_params: &IODParams,
diff_cor_config: &DifferentialCorrectionConfig,
initial_orbits: Option<&FitOrbitResult>,
rng: &mut impl rand::Rng,
) -> Result<FitOrbitResult, OutfitError> {
let initial_orbit: FitOrbitResult = match initial_orbits {
Some(FitOrbitResult::DifferentialCorrection(_)) => {
return Err(OutfitError::DifferentialCorrectionFailed(
"differential_correction expects an IOD result as initial orbit, \
got a DifferentialCorrection result"
.to_string(),
));
}
Some(orbit) => orbit.clone(),
None => run_iod_on_observations(observations, cache, jpl, iod_params, rng)?,
};
let equinoctial_elements = initial_orbit
.orbital_elements()
.to_equinoctial()?
.as_equinoctial()
.ok_or(OutfitError::InvalidConversion(
"Conversion to equinoctial elements failed".to_string(),
))?;
let obs_fit_data: Vec<ObsFitData> = observations
.iter()
.map(|obs| ObsFitData::new(obs.equ_coord().ra_error, obs.equ_coord().dec_error))
.collect();
match run_differential_correction(
observations,
&obs_fit_data,
&equinoctial_elements,
cache,
jpl,
diff_cor_config,
) {
Ok(dc_output) => {
let normalised_rms = dc_output.normalised_rms;
Ok(FitOrbitResult::DifferentialCorrection((
dc_output.into(),
normalised_rms,
)))
}
Err(_) => Ok(initial_orbit),
}
}