gnss_qc/context/
time.rs

1use crate::prelude::{ProductType, QcContext, TimeScale};
2
3use qc_traits::{Merge, TimeCorrectionError, TimeCorrectionsDB, Timeshift};
4
5impl QcContext {
6    /// Collect a [TimeCorrectionDB] from this [QcContext], that you can then
7    /// use for precise temporal correction. The database will contain
8    /// all time corrections available and described by this dataset.
9    /// This requires both navigation feature and navigation compatibility to truly be effective.
10    pub fn time_corrections_database(&self) -> Option<TimeCorrectionsDB> {
11        let mut db = Option::<TimeCorrectionsDB>::None;
12
13        if let Some(brdc) = self.brdc_navigation() {
14            if let Some(nav_db) = brdc.time_corrections_database() {
15                if let Some(db) = &mut db {
16                    db.merge_mut(&nav_db).unwrap(); // infaillble
17                } else {
18                    db = Some(nav_db);
19                }
20            }
21        }
22
23        db
24    }
25
26    /// Infaillible transposition of the temporal products to desired [TimeScale].
27    /// This only applies to the following products:
28    /// - Observation RINEX
29    /// - SP3
30    /// ```
31    /// use gnss_qc::prelude::{QcContext, TimeScale};
32    ///
33    /// let mut context = QcContext::new();
34    ///
35    /// // GPST observations
36    /// context.load_gzip_rinex_file("data/CRNX/V3/ESBC00DNK_R_20201770000_01D_30S_MO.crx.gz")
37    ///     .unwrap();
38    ///
39    /// // GPST sP3
40    /// context.load_sp3_file("data/SP3/D/example.txt")
41    ///     .unwrap();
42    ///
43    /// // convert both to GST
44    /// context.timescale_transposition_mut(TimeScale::GST);
45    /// ```
46    pub fn timescale_transposition_mut(&mut self, timescale: TimeScale) {
47        for (product_type, data) in self.blob.iter_mut() {
48            match product_type {
49                ProductType::Observation => {
50                    let rinex = data.as_mut_rinex().unwrap();
51                    rinex.timeshift_mut(timescale);
52                }
53                #[cfg(feature = "sp3")]
54                ProductType::HighPrecisionOrbit => {
55                    let sp3 = data.as_mut_sp3().unwrap();
56                    sp3.timeshift_mut(timescale);
57                }
58                _ => {}
59            }
60        }
61    }
62
63    /// Precise temporal transposition of each individual products contained in current [QcContext].
64    /// NB: transposition might not be feasible for some components, therefore
65    /// you should double check the newly obtained [QcContext].
66    ///
67    /// This may apply to your [SP3] products, if feature is activated.
68    ///
69    /// Example (1): precise RINEX transpositions
70    /// ```
71    /// use gnss_qc::prelude::{QcContext, TimeScale};
72    ///
73    /// let mut context = QcContext::new();
74    ///
75    /// // GPST observations
76    /// context.load_gzip_rinex_file("data/CRNX/V3/ESBC00DNK_R_20201770000_01D_30S_MO.crx.gz")
77    ///     .unwrap();
78    ///
79    /// // this setup is not compatible
80    /// assert!(context.time_corrections_database().is_none());
81    ///
82    /// // stack NAV RINEX
83    /// context.load_gzip_rinex_file("data/NAV/V3/ESBC00DNK_R_20201770000_01D_MN.rnx.gz")
84    ///     .unwrap();
85    ///
86    /// let database = context.time_corrections_database()
87    ///     .unwrap();
88    ///
89    /// context.precise_time_correction_mut(&database, TimeScale::GST);
90    ///
91    /// // verify we shifted all observations to GST
92    /// let transposed_obs = context.observation().unwrap();
93    ///
94    /// for t in transposed_obs.epoch_iter() {
95    ///     assert_eq!(t.time_scale, TimeScale::GST);
96    /// }
97    /// ```
98    ///
99    /// Example (2): SP3 transposition.
100    /// SP3 are totally valid in any GNSS timescale, you can use this framework
101    /// to reformat as desired !
102    ///
103    pub fn precise_time_correction_mut(
104        &mut self,
105        db: &TimeCorrectionsDB,
106        timescale: TimeScale,
107    ) -> Result<(), TimeCorrectionError> {
108        if let Some(observations) = self.observation_mut() {
109            observations.precise_correction_mut(db, timescale)?;
110        }
111
112        #[cfg(feature = "sp3")]
113        if let Some(sp3) = self.sp3_mut() {
114            sp3.precise_correction_mut(db, timescale)?;
115        }
116
117        Ok(())
118    }
119}