gnss_qc/report/
sp3.rs

1use itertools::Itertools;
2use maud::{html, Markup, Render};
3use std::collections::HashMap;
4
5use qc_traits::{Filter, FilterItem, MaskOperand, Preprocessing};
6use sp3::prelude::{Constellation, SP3, SV};
7
8use crate::report::shared::SamplingReport;
9
10pub struct SP3Page {
11    has_clock: bool,
12    has_velocity: bool,
13    has_clock_drift: bool,
14    satellites: Vec<SV>,
15    sampling: SamplingReport,
16}
17
18impl Render for SP3Page {
19    fn render(&self) -> Markup {
20        html! {
21            div class="table-container" {
22                table class="table is-bordered" {
23                    tr {
24                        th class="is-info" {
25                            "General"
26                        }
27                    }
28                    tr {
29                        th {
30                            "Velocity"
31                        }
32                        td {
33                            (self.has_velocity.to_string())
34                        }
35                    }
36                    tr {
37                        th {
38                            "Clock offset"
39                        }
40                        td {
41                            (self.has_clock.to_string())
42                        }
43                    }
44                    tr {
45                        th {
46                            "Clock drift"
47                        }
48                        td {
49                            (self.has_clock_drift.to_string())
50                        }
51                    }
52                    tr {
53                        th class="is-info" {
54                            "Satellites"
55                        }
56                        td {
57                            (self.satellites.iter().sorted().join(", "))
58                        }
59                    }
60                    tr {
61                        th class="is-info" {
62                            "Sampling"
63                        }
64                        td {
65                            (self.sampling.render())
66                        }
67                    }
68                }
69            }
70        }
71    }
72}
73
74pub struct SP3Report {
75    pub agency: String,
76    pub version: String,
77    pub coord_system: String,
78    pub orbit_fit: String,
79    pub constellation: String,
80    pub time_scale: String,
81    pub sampling: SamplingReport,
82    pub pages: HashMap<Constellation, SP3Page>,
83}
84
85impl SP3Report {
86    pub fn html_inline_menu_bar(&self) -> Markup {
87        html! {
88            a id="menu:sp3" {
89                span class="icon" {
90                    i class="fa-solid fa-satellite" {}
91                }
92                "High Precision Orbit (SP3)"
93            }
94            //ul(class="menu-list", id="menu:tabs:sp3", style="display:block") {
95            //    @ for page in self.pages.keys().sorted() {
96            //        li {
97            //            a(id=&format!("menu:sp3:{}", page), class="tab:sp3", style="margin-left:29px") {
98            //                span(class="icon") {
99            //                    i(class="fa-solid fa-satellite");
100            //                }
101            //                : page.to_string()
102            //            }
103            //        }
104            //    }
105            //}
106        }
107    }
108    pub fn new(sp3: &SP3) -> Self {
109        Self {
110            agency: sp3.header.agency.clone(),
111            version: sp3.header.version.to_string(),
112            coord_system: sp3.header.coord_system.clone(),
113            orbit_fit: sp3.header.orbit_type.to_string(),
114            time_scale: sp3.header.timescale.to_string(),
115            sampling: SamplingReport::from_sp3(sp3),
116            constellation: sp3.header.constellation.to_string(),
117            pages: {
118                let mut pages = HashMap::<Constellation, SP3Page>::new();
119                for constellation in sp3.constellations_iter() {
120                    let filter = Filter::mask(
121                        MaskOperand::Equals,
122                        FilterItem::ConstellationItem(vec![constellation]),
123                    );
124                    let focused = sp3.filter(&filter);
125                    //let epochs = focused.epoch().collect::<Vec<_>>();
126                    let satellites = focused.satellites_iter().collect::<Vec<_>>();
127                    pages.insert(
128                        constellation,
129                        SP3Page {
130                            has_clock: focused.has_satellite_clock_offset(),
131                            sampling: SamplingReport::from_sp3(&focused),
132                            has_velocity: focused.has_satellite_velocity(),
133                            has_clock_drift: focused.has_satellite_clock_drift(),
134                            satellites,
135                        },
136                    );
137                }
138                pages
139            },
140        }
141    }
142}
143
144impl Render for SP3Report {
145    fn render(&self) -> Markup {
146        html! {
147            div class="table-container" {
148                table class="table is-bordered" {
149                    tr {
150                        th {
151                            button aria-label="File revision" data-balloon-pos="right" {
152                                "File revision"
153                            }
154                        }
155                        td {
156                            (self.version)
157                        }
158                    }
159                    tr {
160                        th {
161                            button aria-label="Production Center" data-balloon-pos="right" {
162                                "Agency"
163                            }
164                        }
165                        td {
166                            (self.agency.clone())
167                        }
168                    }
169                    tr {
170                        th {
171                            button aria-label="Fitted constellations" data-balloon-pos="right" {
172                                "Constellation"
173                            }
174                        }
175                        td {
176                            (self.constellation.clone())
177                        }
178                    }
179                    tr {
180                        th {
181                            button aria-label="Timescale in which post-fit coordinates are expressed." data-balloon-pos="right" {
182                                "Timescale"
183                            }
184                        }
185                        td {
186                            (self.time_scale.clone())
187                        }
188                    }
189                    tr {
190                        th {
191                            button aria-label="Reference frame in which post-fit coordinates are expressed." data-balloon-pos="right" {
192                                "Reference Frame"
193                            }
194                        }
195                        td {
196                            (self.coord_system.clone())
197                        }
198                    }
199                    tr {
200                        th {
201                            button aria-label="Coordinates determination technique." data-balloon-pos="right" {
202                                "Orbit FIT"
203                            }
204                        }
205                        td {
206                            (self.orbit_fit.clone())
207                        }
208                    }
209                    tr {
210                        th {
211                            "Sampling"
212                        }
213                        td {
214                            (self.sampling.render())
215                        }
216                    }
217                }//table
218            }//table-container
219            @for constell in self.pages.keys().sorted() {
220                @if let Some(page) = self.pages.get(constell) {
221                    div class="table-container is-page" id=(format!("sp3:{}", constell)) style="display:block" {
222                        table class="table is-bordered" {
223                            tr {
224                                th class="is-info" {
225                                    (constell.to_string())
226                                }
227                                td {
228                                    (page.render())
229                                }
230                            }
231                        }
232                    }
233                }
234            }
235        }
236    }
237}