1   /* Copyright 2020-2025 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.orekit.files.sinex;
19  
20  import java.util.Collection;
21  import java.util.HashSet;
22  
23  import org.hipparchus.util.Pair;
24  import org.junit.jupiter.api.Assertions;
25  import org.junit.jupiter.api.BeforeAll;
26  import org.junit.jupiter.api.Test;
27  import org.orekit.Utils;
28  import org.orekit.data.DataSource;
29  import org.orekit.gnss.ObservationType;
30  import org.orekit.gnss.PredefinedObservationType;
31  import org.orekit.gnss.SatInSystem;
32  import org.orekit.gnss.SatelliteSystem;
33  import org.orekit.gnss.TimeSystem;
34  import org.orekit.time.AbsoluteDate;
35  import org.orekit.time.DateComponents;
36  import org.orekit.time.TimeComponents;
37  import org.orekit.time.TimeScale;
38  import org.orekit.time.TimeScalesFactory;
39  import org.orekit.utils.Constants;
40  
41  public class SinexBiasParserTest {
42  
43      @BeforeAll
44      public static void setUpData() {
45          // Sets the root of data to read
46          Utils.setDataRoot("gnss:sinex");
47      }
48  
49      @Test
50      public void testFirstLineDsb() {
51          // Verify the parsing of the first line for the Sinex parser in the DSB file case.
52          SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_default_description.BSX");
53          AbsoluteDate creationDate = sinexBias.getCreationDate();
54          AbsoluteDate refCreationDate = new AbsoluteDate(new DateComponents(2022, 11),
55                                                          new TimeComponents(58414),
56                                                          TimeScalesFactory.getGPS());
57          Assertions.assertEquals(creationDate, refCreationDate);
58      }
59  
60      @Test
61      public void testFirstLineDsbInUtc() {
62          // Verify the parsing of the first line for the Sinex parser in the DSB file case.
63          SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_UTC.BSX");
64          AbsoluteDate creationDate = sinexBias.getCreationDate();
65          AbsoluteDate refCreationDate = new AbsoluteDate(new DateComponents(2022, 11),
66                                                          new TimeComponents(58414),
67                                                          TimeScalesFactory.getUTC());
68          Assertions.assertEquals(creationDate, refCreationDate);
69      }
70  
71      @Test
72      public void testDsbDescriptionSat() {
73          SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_trunc_sat.BSX");
74          // DSB Description test
75          BiasDescription dcbDesc = sinexBias.getDescription();
76          TimeSystem timeSystem = dcbDesc.getTimeSystem();
77          String biasMode = dcbDesc.getBiasMode();
78          String determinationMethod = dcbDesc.getDeterminationMethod();
79          int observationSampling = dcbDesc.getObservationSampling();
80          int parameterSpacing = dcbDesc.getParameterSpacing();
81          Assertions.assertEquals(timeSystem, TimeSystem.GPS);
82          Assertions.assertEquals(biasMode, "RELATIVE");
83          Assertions.assertEquals(determinationMethod, "INTER-FREQUENCY_BIAS_ESTIMATION");
84          Assertions.assertEquals(parameterSpacing, 86400);
85          Assertions.assertEquals(observationSampling, 30);
86      }
87      
88      @Test
89      public void testDsbDescriptionStation() {
90          SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_trunc_sat.BSX");
91          // DSB Description test
92          BiasDescription dcbDesc = sinexBias.getDescription();
93          TimeSystem timeSystem = dcbDesc.getTimeSystem();
94          String biasMode = dcbDesc.getBiasMode();
95          String determinationMethod = dcbDesc.getDeterminationMethod();
96          int observationSampling = dcbDesc.getObservationSampling();
97          int parameterSpacing = dcbDesc.getParameterSpacing();
98          Assertions.assertEquals(timeSystem, TimeSystem.GPS);
99          Assertions.assertEquals(biasMode, "RELATIVE");
100         Assertions.assertEquals(determinationMethod, "INTER-FREQUENCY_BIAS_ESTIMATION");
101         Assertions.assertEquals(parameterSpacing, 86400);
102         Assertions.assertEquals(observationSampling, 30);
103     }
104     
105     @Test
106     public void testDsbfile() {
107         SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_trunc_sat.BSX");
108         SatelliteDifferentialSignalBias satDsb = sinexBias.getSatellitesDsb().get(new SatInSystem("G01"));
109         DifferentialSignalBias dsb = satDsb.getDsb();
110         Assertions.assertTrue(sinexBias.getSatellitesOsb().isEmpty());
111         Assertions.assertTrue(sinexBias.getStationsOsb().isEmpty());
112         
113         // Observation Pair test
114         HashSet<Pair<ObservationType, ObservationType>> ObsPairs = dsb.getAvailableObservationPairs();
115         
116         // Defining the observation pair present in the truncated file.
117         Pair<ObservationType, ObservationType> OP1 = new Pair<>(PredefinedObservationType.C1C, PredefinedObservationType.C1W);
118         Pair<ObservationType, ObservationType> OP2 = new Pair<>(PredefinedObservationType.C1C, PredefinedObservationType.C2W);
119         Pair<ObservationType, ObservationType> OP3 = new Pair<>(PredefinedObservationType.C1C, PredefinedObservationType.C5Q);
120         Pair<ObservationType, ObservationType> OP4 = new Pair<>(PredefinedObservationType.C2W, PredefinedObservationType.C2L);
121         
122         HashSet<Pair<ObservationType, ObservationType>> observationSetsRef = new HashSet<>();
123         observationSetsRef.add(OP1);
124         observationSetsRef.add(OP2);
125         observationSetsRef.add(OP3);
126         observationSetsRef.add(OP4);
127 
128         // Check
129         Assertions.assertEquals(ObsPairs, observationSetsRef);
130         
131         // Defining observation codes for further checks.
132         ObservationType Obs1 = PredefinedObservationType.C1C;
133         ObservationType Obs2 = PredefinedObservationType.C1W;
134         
135         // Minimum Date test
136         AbsoluteDate refFirstDate = new AbsoluteDate(new DateComponents(2021, 274),
137                                                      TimeComponents.H00,
138                                                      TimeScalesFactory.getGPS());
139         AbsoluteDate firstDate =  dsb.getMinimumValidDateForObservationPair(Obs1, Obs2);
140         
141         Assertions.assertEquals(refFirstDate, firstDate);
142         
143         // Max Date Test
144         AbsoluteDate refLastDate = new AbsoluteDate(new DateComponents(2021, 283),
145                                                     TimeComponents.H00,
146                                                     TimeScalesFactory.getGPS());
147         AbsoluteDate lastDate =  dsb.getMaximumValidDateForObservationPair(Obs1, Obs2);
148         
149         Assertions.assertEquals(refLastDate, lastDate);
150         
151         // Value test for Satellites
152         AbsoluteDate refDate = new AbsoluteDate(new DateComponents(2021, 280),
153                                                 new TimeComponents(43200),
154                                                 TimeScalesFactory.getGPS());
155         
156         double valueDsb = dsb.getBias(Obs1, Obs2, refDate);
157         double valueDsbReal = -1.0697e-9 * Constants.SPEED_OF_LIGHT;
158         
159         Assertions.assertEquals(valueDsbReal, valueDsb, 1e-5);
160         
161         // Value Test for a Station
162         StationDifferentialSignalBias StationDifferentialSignalBias = sinexBias.getStationsDsb().get("ALIC");
163         DifferentialSignalBias differentialSignalBiasTestStation = StationDifferentialSignalBias.getDsb(SatelliteSystem.parseSatelliteSystem("R"));
164 
165         AbsoluteDate refDateStation = new AbsoluteDate(new DateComponents(2021, 300),
166                                                        new TimeComponents(43200),
167                                                        TimeScalesFactory.getGPS());
168         
169         double valueDsbStation = differentialSignalBiasTestStation.getBias(PredefinedObservationType.C1C,
170                                                        PredefinedObservationType.C1P,
171                                                        refDateStation);
172         double valueDsbRealStation = -0.6458e-9 * Constants.SPEED_OF_LIGHT;
173         
174         Assertions.assertEquals(valueDsbRealStation, valueDsbStation, 1e-13);
175         
176                 
177         // Test getSatelliteSystem
178         Assertions.assertEquals(satDsb.getSatellite().getSystem(), SatelliteSystem.GPS);
179         
180         // Test getPRN
181         Assertions.assertEquals(1, satDsb.getSatellite().getPRN());
182         
183     }
184 
185     @Test
186     public void testDsbFileStation() {
187         SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_trunc_sat.BSX");
188         String stationIdRef = "AGGO";
189         StationDifferentialSignalBias DSBTest = sinexBias.getStationsDsb().get(stationIdRef);
190          
191         // Test getStationId : Station Case
192         Assertions.assertEquals(stationIdRef, DSBTest.getSiteCode());
193          
194         final Collection<SatelliteSystem> availableSystems = DSBTest.getAvailableSatelliteSystems();
195         Assertions.assertEquals(2, availableSystems.size());
196         Assertions.assertTrue(availableSystems.contains(SatelliteSystem.GPS));
197         Assertions.assertTrue(availableSystems.contains(SatelliteSystem.GALILEO));
198 
199     }
200 
201     @Test
202     public void testOsbSatellite() {
203         SinexBias sinexBias = load("/sinex/code.bia");
204         SatelliteObservableSpecificSignalBias satOsb = sinexBias.getSatellitesOsb().get(new SatInSystem("E08"));
205         ObservableSpecificSignalBias osb = satOsb.getOsb();
206         Assertions.assertTrue(sinexBias.getSatellitesDsb().isEmpty());
207         Assertions.assertTrue(sinexBias.getStationsDsb().isEmpty());
208 
209         final TimeSystem ts = sinexBias.getDescription().getTimeSystem();
210         Assertions.assertEquals(TimeSystem.GPS, ts);
211         final TimeScale timeScale = ts.getTimeScale(TimeScalesFactory.getTimeScales());
212 
213         // Observations test
214         HashSet<ObservationType> types = osb.getAvailableObservations();
215         Assertions.assertEquals(4, types.size());
216         Assertions.assertTrue(types.contains(PredefinedObservationType.C1C));
217         Assertions.assertTrue(types.contains(PredefinedObservationType.C1X));
218         Assertions.assertTrue(types.contains(PredefinedObservationType.C5Q));
219         Assertions.assertTrue(types.contains(PredefinedObservationType.C5X));
220 
221         // Minimum Date test
222         AbsoluteDate refFirstDate = new AbsoluteDate(new DateComponents(2024, 237),
223                                                      TimeComponents.H00,
224                                                      timeScale);
225         AbsoluteDate firstDate =  osb.getMinimumValidDateForObservation(PredefinedObservationType.C5X);
226         Assertions.assertEquals(refFirstDate, firstDate);
227 
228         // Max Date Test
229         AbsoluteDate refLastDate = new AbsoluteDate(new DateComponents(2024, 267),
230                                                     TimeComponents.H00,
231                                                     timeScale);
232         AbsoluteDate lastDate =  osb.getMaximumValidDateForObservation(PredefinedObservationType.C5X);
233         Assertions.assertEquals(refLastDate, lastDate);
234 
235         double valueOsb = osb.getBias(PredefinedObservationType.C5X,
236                                       new AbsoluteDate(new DateComponents(2024, 250),
237                                                        TimeComponents.H00,
238                                                        timeScale));
239         double valueOsbReal = -6.7298e-9 * Constants.SPEED_OF_LIGHT;
240 
241         Assertions.assertEquals(valueOsbReal, valueOsb, 1e-5);
242 
243     }
244 
245     @Test
246     public void testOsbStation() {
247         SinexBias sinexBias = load("/sinex/station.bia");
248         StationObservableSpecificSignalBias staOsb = sinexBias.getStationsOsb().get("TUKT");
249         ObservableSpecificSignalBias osb = staOsb.getOsb(SatelliteSystem.GALILEO);
250         Assertions.assertTrue(sinexBias.getSatellitesDsb().isEmpty());
251         Assertions.assertTrue(sinexBias.getStationsDsb().isEmpty());
252 
253         final TimeSystem ts = sinexBias.getDescription().getTimeSystem();
254         Assertions.assertEquals(TimeSystem.GALILEO, ts);
255         final TimeScale timeScale = ts.getTimeScale(TimeScalesFactory.getTimeScales());
256 
257         Assertions.assertEquals(1, staOsb.getAvailableSatelliteSystems().size());
258         Assertions.assertTrue(staOsb.getAvailableSatelliteSystems().contains(SatelliteSystem.GALILEO));
259         Assertions.assertEquals("TUKT", staOsb.getSiteCode());
260 
261         // Observations test
262         HashSet<ObservationType> types = osb.getAvailableObservations();
263         Assertions.assertEquals(3, types.size());
264         Assertions.assertTrue(types.contains(PredefinedObservationType.C1C));
265         Assertions.assertTrue(types.contains(PredefinedObservationType.C1X));
266         Assertions.assertTrue(types.contains(PredefinedObservationType.C6A));
267 
268         // Minimum Date test
269         AbsoluteDate refFirstDate = new AbsoluteDate(new DateComponents(2024, 237),
270                                                      TimeComponents.H00,
271                                                      timeScale);
272         AbsoluteDate firstDate =  osb.getMinimumValidDateForObservation(PredefinedObservationType.C1C);
273         Assertions.assertEquals(refFirstDate, firstDate);
274 
275         // Max Date Test
276         AbsoluteDate refLastDate = new AbsoluteDate(new DateComponents(2024, 267),
277                                                     TimeComponents.H00,
278                                                     timeScale);
279         AbsoluteDate lastDate =  osb.getMaximumValidDateForObservation(PredefinedObservationType.C1X);
280         Assertions.assertEquals(refLastDate, lastDate);
281 
282         double valueOsb = osb.getBias(PredefinedObservationType.C6A,
283                                       new AbsoluteDate(new DateComponents(2024, 250),
284                                                        TimeComponents.H00,
285                                                        timeScale));
286         double valueOsbReal = -18.5167e-9 * Constants.SPEED_OF_LIGHT;
287 
288         Assertions.assertEquals(valueOsbReal, valueOsb, 1e-5);
289 
290         final double phaseBias = sinexBias.
291                                  getStationsOsb().
292                                  get("BRUX").
293                                  getOsb(SatelliteSystem.GALILEO).
294                                  getBias(PredefinedObservationType.L6A,
295                                          new AbsoluteDate(new DateComponents(2024, 250), TimeComponents.H00, timeScale));
296         Assertions.assertEquals(1.7e-3, phaseBias, 1.0e-15);
297 
298     }
299 
300     private SinexBias load(final String name) {
301         return new SinexBiasParser(TimeScalesFactory.getTimeScales(), SinexBiasParser::defaultTypeBuilder).
302                parse(new DataSource(name, () -> SinexParserTest.class.getResourceAsStream(name)));
303     }
304 
305 }