rinex 0.22.0

RINEX file parsing, analysis and production
Documentation
use crate::{
    observation::{ObsKey, Observations},
    prelude::{Duration, Header, Rinex, TimeScale},
};

use qc_traits::{TimeCorrectionError, TimeCorrectionsDB, Timeshift};

use std::collections::BTreeMap;

impl Timeshift for Header {
    fn timeshift(&self, timescale: TimeScale) -> Self
    where
        Self: Sized,
    {
        let mut s = self.clone();
        s.timeshift_mut(timescale);
        s
    }

    fn timeshift_mut(&mut self, timescale: TimeScale) {
        let one_us = Duration::from_microseconds(1.0);

        if let Some(obs) = &mut self.obs {
            if let Some(epoch) = &mut obs.timeof_first_obs {
                *epoch = epoch.to_time_scale(timescale).round(one_us);
            }

            if let Some(epoch) = &mut obs.timeof_last_obs {
                *epoch = epoch.to_time_scale(timescale).round(one_us);
            }
        }
    }

    fn precise_correction(
        &self,
        db: &TimeCorrectionsDB,
        timescale: TimeScale,
    ) -> Result<Self, TimeCorrectionError>
    where
        Self: Sized,
    {
        let mut s = self.clone();
        s.precise_correction_mut(db, timescale)?;
        Ok(s)
    }

    fn precise_correction_mut(
        &mut self,
        db: &TimeCorrectionsDB,
        timescale: TimeScale,
    ) -> Result<(), TimeCorrectionError> {
        let one_us = Duration::from_microseconds(1.0);

        if let Some(obs) = &mut self.obs {
            if let Some(epoch) = &mut obs.timeof_first_obs {
                *epoch = db
                    .precise_epoch_correction(*epoch, timescale)
                    .ok_or(TimeCorrectionError::NoCorrectionAvailable(
                        epoch.time_scale,
                        timescale,
                    ))?
                    .round(one_us);
            }

            if let Some(epoch) = &mut obs.timeof_last_obs {
                *epoch = db
                    .precise_epoch_correction(*epoch, timescale)
                    .ok_or(TimeCorrectionError::NoCorrectionAvailable(
                        epoch.time_scale,
                        timescale,
                    ))?
                    .round(one_us);
            }
        }

        Ok(())
    }
}

impl Timeshift for Rinex {
    fn timeshift(&self, timescale: TimeScale) -> Self
    where
        Self: Sized,
    {
        let mut s = self.clone();
        s.timeshift_mut(timescale);
        s
    }

    fn timeshift_mut(&mut self, timescale: TimeScale) {
        self.header.timeshift_mut(timescale);

        if let Some(obs_rec) = self.record.as_mut_obs() {
            let mut new_rec = BTreeMap::<ObsKey, Observations>::new();

            for (k, values) in obs_rec.iter() {
                let transposed = k.epoch.to_time_scale(timescale);
                let mut key = k.clone();
                key.epoch = transposed;
                new_rec.insert(key, values.clone());
            }

            *obs_rec = new_rec;
        }
    }

    fn precise_correction(
        &self,
        db: &TimeCorrectionsDB,
        timescale: TimeScale,
    ) -> Result<Self, TimeCorrectionError>
    where
        Self: Sized,
    {
        let mut s = self.clone();
        s.precise_correction_mut(db, timescale)?;
        Ok(s)
    }

    fn precise_correction_mut(
        &mut self,
        db: &TimeCorrectionsDB,
        timescale: TimeScale,
    ) -> Result<(), TimeCorrectionError> {
        self.header.precise_correction_mut(db, timescale)?;

        if let Some(obs_rec) = self.record.as_mut_obs() {
            let mut new_rec = BTreeMap::<ObsKey, Observations>::new();

            for (k, values) in obs_rec.iter() {
                let transposed = db.precise_epoch_correction(k.epoch, timescale).ok_or(
                    TimeCorrectionError::NoCorrectionAvailable(k.epoch.time_scale, timescale),
                )?;

                let mut key = k.clone();
                key.epoch = transposed;
                new_rec.insert(key, values.clone());
            }

            *obs_rec = new_rec;
        }

        Ok(())
    }
}