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  import org.orekit.utils.TimeSpanMap;
41  
42  public class SinexBiasParserTest {
43  
44      @BeforeAll
45      public static void setUpData() {
46          // Sets the root of data to read
47          Utils.setDataRoot("gnss:sinex");
48      }
49  
50      @Test
51      public void testFirstLineDsb() {
52          // Verify the parsing of the first line for the Sinex parser in the DSB file case.
53          SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_default_description.BSX");
54          AbsoluteDate creationDate = sinexBias.getCreationDate();
55          AbsoluteDate refCreationDate = new AbsoluteDate(new DateComponents(2022, 11),
56                                                          new TimeComponents(58414),
57                                                          TimeScalesFactory.getGPS());
58          Assertions.assertEquals(creationDate, refCreationDate);
59      }
60  
61      @Test
62      public void testFirstLineDsbInUtc() {
63          // Verify the parsing of the first line for the Sinex parser in the DSB file case.
64          SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_UTC.BSX");
65          AbsoluteDate creationDate = sinexBias.getCreationDate();
66          AbsoluteDate refCreationDate = new AbsoluteDate(new DateComponents(2022, 11),
67                                                          new TimeComponents(58414),
68                                                          TimeScalesFactory.getUTC());
69          Assertions.assertEquals(creationDate, refCreationDate);
70      }
71  
72      @Test
73      public void testDsbDescriptionSat() {
74          SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_trunc_sat.BSX");
75          // DSB Description test
76          BiasDescription dcbDesc = sinexBias.getDescription();
77          TimeSystem timeSystem = dcbDesc.getTimeSystem();
78          String biasMode = dcbDesc.getBiasMode();
79          String determinationMethod = dcbDesc.getDeterminationMethod();
80          int observationSampling = dcbDesc.getObservationSampling();
81          int parameterSpacing = dcbDesc.getParameterSpacing();
82          Assertions.assertEquals(TimeSystem.GPS, timeSystem);
83          Assertions.assertEquals("RELATIVE", biasMode);
84          Assertions.assertEquals("INTER-FREQUENCY_BIAS_ESTIMATION", determinationMethod);
85          Assertions.assertEquals(86400, parameterSpacing);
86          Assertions.assertEquals(30, observationSampling);
87      }
88  
89      @Test
90      public void testDsbDescriptionStation() {
91          SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_trunc_sat.BSX");
92          // DSB Description test
93          BiasDescription dcbDesc = sinexBias.getDescription();
94          TimeSystem timeSystem = dcbDesc.getTimeSystem();
95          String biasMode = dcbDesc.getBiasMode();
96          String determinationMethod = dcbDesc.getDeterminationMethod();
97          int observationSampling = dcbDesc.getObservationSampling();
98          int parameterSpacing = dcbDesc.getParameterSpacing();
99          Assertions.assertEquals(TimeSystem.GPS, timeSystem);
100         Assertions.assertEquals("RELATIVE", biasMode);
101         Assertions.assertEquals("INTER-FREQUENCY_BIAS_ESTIMATION", determinationMethod);
102         Assertions.assertEquals(86400, parameterSpacing);
103         Assertions.assertEquals(30, observationSampling);
104     }
105 
106     @Test
107     public void testDsbfile() {
108         SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_trunc_sat.BSX");
109         SatelliteDifferentialSignalBias satDsb = sinexBias.getSatellitesDsb().get(new SatInSystem("G01"));
110         DifferentialSignalBias dsb = satDsb.getDsb();
111         Assertions.assertTrue(sinexBias.getSatellitesOsb().isEmpty());
112         Assertions.assertTrue(sinexBias.getStationsOsb().isEmpty());
113 
114         // Observation Pair test
115         HashSet<Pair<ObservationType, ObservationType>> ObsPairs = dsb.getAvailableObservationPairs();
116 
117         // Defining the observation pair present in the truncated file.
118         Pair<ObservationType, ObservationType> OP1 = new Pair<>(PredefinedObservationType.C1C, PredefinedObservationType.C1W);
119         Pair<ObservationType, ObservationType> OP2 = new Pair<>(PredefinedObservationType.C1C, PredefinedObservationType.C2W);
120         Pair<ObservationType, ObservationType> OP3 = new Pair<>(PredefinedObservationType.C1C, PredefinedObservationType.C5Q);
121         Pair<ObservationType, ObservationType> OP4 = new Pair<>(PredefinedObservationType.C2W, PredefinedObservationType.C2L);
122 
123         HashSet<Pair<ObservationType, ObservationType>> observationSetsRef = new HashSet<>();
124         observationSetsRef.add(OP1);
125         observationSetsRef.add(OP2);
126         observationSetsRef.add(OP3);
127         observationSetsRef.add(OP4);
128 
129         // Check
130         Assertions.assertEquals(ObsPairs, observationSetsRef);
131 
132         // Defining observation codes for further checks.
133         ObservationType Obs1 = PredefinedObservationType.C1C;
134         ObservationType Obs2 = PredefinedObservationType.C1W;
135 
136         // Minimum Date test
137         AbsoluteDate refFirstDate = new AbsoluteDate(new DateComponents(2021, 274),
138                                                      TimeComponents.H00,
139                                                      TimeScalesFactory.getGPS());
140         AbsoluteDate firstDate =  dsb.getMinimumValidDateForObservationPair(Obs1, Obs2);
141 
142         Assertions.assertEquals(refFirstDate, firstDate);
143 
144         // Max Date Test
145         AbsoluteDate refLastDate = new AbsoluteDate(new DateComponents(2021, 283),
146                                                     TimeComponents.H00,
147                                                     TimeScalesFactory.getGPS());
148         AbsoluteDate lastDate =  dsb.getMaximumValidDateForObservationPair(Obs1, Obs2);
149 
150         Assertions.assertEquals(refLastDate, lastDate);
151 
152         // Value test for Satellites
153         AbsoluteDate refDate = new AbsoluteDate(new DateComponents(2021, 280),
154                                                 new TimeComponents(43200),
155                                                 TimeScalesFactory.getGPS());
156 
157         double valueDsb = dsb.getBias(Obs1, Obs2, refDate);
158         double valueDsbReal = -1.0697e-9 * Constants.SPEED_OF_LIGHT;
159 
160         Assertions.assertEquals(valueDsbReal, valueDsb, 1e-5);
161 
162         final TimeSpanMap<Double> tsm =
163             dsb.getTimeSpanMap(PredefinedObservationType.C1C, PredefinedObservationType.C5Q);
164         tsm.getFirstNonNullSpan().getStartTransition().resetDate(AbsoluteDate.PAST_INFINITY, true);
165         tsm.getFirstNonNullSpan().getEndTransition().resetDate(AbsoluteDate.FUTURE_INFINITY, true);
166         Assertions.assertEquals(AbsoluteDate.PAST_INFINITY,
167                                 dsb.getMinimumValidDateForObservationPair(PredefinedObservationType.C1C,
168                                                                           PredefinedObservationType.C5Q));
169         Assertions.assertEquals(AbsoluteDate.FUTURE_INFINITY,
170                                 dsb.getMaximumValidDateForObservationPair(PredefinedObservationType.C1C,
171                                                                           PredefinedObservationType.C5Q));
172 
173         // Value Test for a Station
174         StationDifferentialSignalBias StationDifferentialSignalBias = sinexBias.getStationsDsb().get("ALIC");
175         DifferentialSignalBias differentialSignalBiasTestStation = StationDifferentialSignalBias.getDsb(SatelliteSystem.parseSatelliteSystem("R"));
176 
177         AbsoluteDate refDateStation = new AbsoluteDate(new DateComponents(2021, 300),
178                                                        new TimeComponents(43200),
179                                                        TimeScalesFactory.getGPS());
180 
181         double valueDsbStation = differentialSignalBiasTestStation.getBias(PredefinedObservationType.C1C,
182                                                        PredefinedObservationType.C1P,
183                                                        refDateStation);
184         double valueDsbRealStation = -0.6458e-9 * Constants.SPEED_OF_LIGHT;
185 
186         Assertions.assertEquals(valueDsbRealStation, valueDsbStation, 1e-13);
187 
188         // Test getSatelliteSystem
189         Assertions.assertEquals(SatelliteSystem.GPS, satDsb.getSatellite().getSystem());
190 
191         // Test getPRN
192         Assertions.assertEquals(1, satDsb.getSatellite().getPRN());
193 
194     }
195 
196     @Test
197     public void testDsbFileStation() {
198         SinexBias sinexBias = load("/sinex/DLR0MGXFIN_20212740000_03L_01D_DSB_trunc_sat.BSX");
199         String stationIdRef = "AGGO";
200         StationDifferentialSignalBias DSBTest = sinexBias.getStationsDsb().get(stationIdRef);
201 
202         // Test getStationId : Station Case
203         Assertions.assertEquals(stationIdRef, DSBTest.getSiteCode());
204 
205         final Collection<SatelliteSystem> availableSystems = DSBTest.getAvailableSatelliteSystems();
206         Assertions.assertEquals(2, availableSystems.size());
207         Assertions.assertTrue(availableSystems.contains(SatelliteSystem.GPS));
208         Assertions.assertTrue(availableSystems.contains(SatelliteSystem.GALILEO));
209 
210     }
211 
212     @Test
213     public void testOsbSatellite() {
214         SinexBias sinexBias = load("/sinex/code.bia");
215         SatelliteObservableSpecificSignalBias satOsb = sinexBias.getSatellitesOsb().get(new SatInSystem("E08"));
216         ObservableSpecificSignalBias osb = satOsb.getOsb();
217         Assertions.assertTrue(sinexBias.getSatellitesDsb().isEmpty());
218         Assertions.assertTrue(sinexBias.getStationsDsb().isEmpty());
219 
220         final TimeSystem ts = sinexBias.getDescription().getTimeSystem();
221         Assertions.assertEquals(TimeSystem.GPS, ts);
222         final TimeScale timeScale = ts.getTimeScale(TimeScalesFactory.getTimeScales());
223 
224         // Observations test
225         HashSet<ObservationType> types = osb.getAvailableObservations();
226         Assertions.assertEquals(4, types.size());
227         Assertions.assertTrue(types.contains(PredefinedObservationType.C1C));
228         Assertions.assertTrue(types.contains(PredefinedObservationType.C1X));
229         Assertions.assertTrue(types.contains(PredefinedObservationType.C5Q));
230         Assertions.assertTrue(types.contains(PredefinedObservationType.C5X));
231 
232         // Minimum Date test
233         AbsoluteDate refFirstDate = new AbsoluteDate(new DateComponents(2024, 237),
234                                                      TimeComponents.H00,
235                                                      timeScale);
236         AbsoluteDate firstDate =  osb.getMinimumValidDateForObservation(PredefinedObservationType.C5X);
237         Assertions.assertEquals(refFirstDate, firstDate);
238 
239         // Max Date Test
240         AbsoluteDate refLastDate = new AbsoluteDate(new DateComponents(2024, 267),
241                                                     TimeComponents.H00,
242                                                     timeScale);
243         AbsoluteDate lastDate =  osb.getMaximumValidDateForObservation(PredefinedObservationType.C5X);
244         Assertions.assertEquals(refLastDate, lastDate);
245 
246         double valueOsb = osb.getBias(PredefinedObservationType.C5X,
247                                       new AbsoluteDate(new DateComponents(2024, 250),
248                                                        TimeComponents.H00,
249                                                        timeScale));
250         double valueOsbReal = -6.7298e-9 * Constants.SPEED_OF_LIGHT;
251 
252         Assertions.assertEquals(valueOsbReal, valueOsb, 1e-5);
253 
254         final TimeSpanMap<Double> tsm = osb.getTimeSpanMap(PredefinedObservationType.C5X);
255         tsm.getFirstTransition().resetDate(AbsoluteDate.PAST_INFINITY, true);
256         tsm.getFirstTransition().resetDate(AbsoluteDate.FUTURE_INFINITY, true);
257         Assertions.assertEquals(AbsoluteDate.PAST_INFINITY,
258                                 osb.getMinimumValidDateForObservation(PredefinedObservationType.C5X));
259         Assertions.assertEquals(AbsoluteDate.FUTURE_INFINITY,
260                                 osb.getMaximumValidDateForObservation(PredefinedObservationType.C5X));
261 
262     }
263 
264     @Test
265     public void testOsbStation() {
266         SinexBias sinexBias = load("/sinex/station.bia");
267         StationObservableSpecificSignalBias staOsb = sinexBias.getStationsOsb().get("TUKT");
268         ObservableSpecificSignalBias osb = staOsb.getOsb(SatelliteSystem.GALILEO);
269         Assertions.assertTrue(sinexBias.getSatellitesDsb().isEmpty());
270         Assertions.assertTrue(sinexBias.getStationsDsb().isEmpty());
271 
272         final TimeSystem ts = sinexBias.getDescription().getTimeSystem();
273         Assertions.assertEquals(TimeSystem.GALILEO, ts);
274         final TimeScale timeScale = ts.getTimeScale(TimeScalesFactory.getTimeScales());
275 
276         Assertions.assertEquals(1, staOsb.getAvailableSatelliteSystems().size());
277         Assertions.assertTrue(staOsb.getAvailableSatelliteSystems().contains(SatelliteSystem.GALILEO));
278         Assertions.assertEquals("TUKT", staOsb.getSiteCode());
279 
280         // Observations test
281         HashSet<ObservationType> types = osb.getAvailableObservations();
282         Assertions.assertEquals(3, types.size());
283         Assertions.assertTrue(types.contains(PredefinedObservationType.C1C));
284         Assertions.assertTrue(types.contains(PredefinedObservationType.C1X));
285         Assertions.assertTrue(types.contains(PredefinedObservationType.C6A));
286 
287         // Minimum Date test
288         AbsoluteDate refFirstDate = new AbsoluteDate(new DateComponents(2024, 237),
289                                                      TimeComponents.H00,
290                                                      timeScale);
291         AbsoluteDate firstDate =  osb.getMinimumValidDateForObservation(PredefinedObservationType.C1C);
292         Assertions.assertEquals(refFirstDate, firstDate);
293 
294         // Max Date Test
295         AbsoluteDate refLastDate = new AbsoluteDate(new DateComponents(2024, 267),
296                                                     TimeComponents.H00,
297                                                     timeScale);
298         AbsoluteDate lastDate =  osb.getMaximumValidDateForObservation(PredefinedObservationType.C1X);
299         Assertions.assertEquals(refLastDate, lastDate);
300 
301         double valueOsb = osb.getBias(PredefinedObservationType.C6A,
302                                       new AbsoluteDate(new DateComponents(2024, 250),
303                                                        TimeComponents.H00,
304                                                        timeScale));
305         double valueOsbReal = -18.5167e-9 * Constants.SPEED_OF_LIGHT;
306 
307         Assertions.assertEquals(valueOsbReal, valueOsb, 1e-5);
308 
309         final double phaseBias = sinexBias.
310                                  getStationsOsb().
311                                  get("BRUX").
312                                  getOsb(SatelliteSystem.GALILEO).
313                                  getBias(PredefinedObservationType.L6A,
314                                          new AbsoluteDate(new DateComponents(2024, 250), TimeComponents.H00, timeScale));
315         Assertions.assertEquals(1.7e-3, phaseBias, 1.0e-15);
316 
317     }
318 
319     private SinexBias load(final String name) {
320         return new SinexBiasParser(TimeScalesFactory.getTimeScales(), SinexBiasParser::defaultTypeBuilder).
321                parse(new DataSource(name, () -> SinexParserTest.class.getResourceAsStream(name)));
322     }
323 
324 }