1   /* Copyright 2002-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  package org.orekit.files.rinex.observation;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.concurrent.atomic.AtomicBoolean;
24  
25  import org.hipparchus.exception.LocalizedCoreFormats;
26  import org.hipparchus.geometry.euclidean.threed.Vector3D;
27  import org.hipparchus.util.FastMath;
28  import org.junit.jupiter.api.Assertions;
29  import org.junit.jupiter.api.BeforeEach;
30  import org.junit.jupiter.api.Test;
31  import org.orekit.Utils;
32  import org.orekit.data.DataSource;
33  import org.orekit.data.UnixCompressFilter;
34  import org.orekit.errors.OrekitException;
35  import org.orekit.errors.OrekitMessages;
36  import org.orekit.files.rinex.AppliedDCBS;
37  import org.orekit.files.rinex.AppliedPCVS;
38  import org.orekit.files.rinex.HatanakaCompressFilter;
39  import org.orekit.gnss.GnssSignal;
40  import org.orekit.gnss.MeasurementType;
41  import org.orekit.gnss.ObservationType;
42  import org.orekit.gnss.PredefinedObservationType;
43  import org.orekit.gnss.SatelliteSystem;
44  import org.orekit.time.AbsoluteDate;
45  import org.orekit.time.ClockOffset;
46  import org.orekit.time.ConstantOffsetTimeScale;
47  import org.orekit.time.SampledClockModel;
48  import org.orekit.time.TimeOffset;
49  import org.orekit.time.TimeScale;
50  import org.orekit.time.TimeScalesFactory;
51  
52  public class RinexObservationParserTest {
53  
54      @BeforeEach
55      public void setUp() {
56          // Sets the root of data to read
57          Utils.setDataRoot("regular-data");
58      }
59  
60      @Test
61      public void testDefaultLoadRinex2() {
62          final RinexObservation ro = load("rinex/aiub0000.00o");
63          Assertions.assertEquals(24, ro.getObservationDataSets().size());
64          final SampledClockModel clockModel = ro.extractClockModel(2);
65          Assertions.assertEquals(6, clockModel.getCache().getAll().size());
66          final ClockOffset offset =
67              clockModel.getOffset(new AbsoluteDate(2001, 3, 24, 13, 11, 57.0,
68                                                    TimeScalesFactory.getGPS()));
69          Assertions.assertEquals(-0.123456888, offset.getOffset(),       1.0e-15);
70          Assertions.assertEquals(-1.1e-8,      offset.getRate(),         1.0e-18);
71          Assertions.assertEquals( 0.0,         offset.getAcceleration(), 1.0e-20);
72      }
73  
74      @Test
75      public void testDefaultLoadRinex3() {
76          Utils.setDataRoot("regular-data:rinex");
77          final RinexObservation ro = load("rinex/brca083.06o");
78          Assertions.assertEquals(5, ro.getObservationDataSets().size());
79          Assertions.assertNull(ro.extractClockModel(2));
80      }
81  
82      @Test
83      public void testReadError() {
84          try {
85              new RinexObservationParser().parse(new DataSource("read-error", () -> new InputStream() {
86                  public int read() throws IOException {
87                      throw new IOException("boo!");
88                  }
89              }));
90              Assertions.fail("an exception should have been thrown");
91          } catch (OrekitException oe) {
92              Assertions.assertEquals(LocalizedCoreFormats.SIMPLE_MESSAGE, oe.getSpecifier());
93              Assertions.assertEquals("boo!", oe.getParts()[0]);
94              Assertions.assertInstanceOf(IOException.class, oe.getCause());
95          }
96      }
97  
98      @Test
99      public void testWrongVersion() {
100         try {
101             load("rinex/unknown-version.06o");
102             Assertions.fail("an exception should have been thrown");
103         } catch (OrekitException oe) {
104             Assertions.assertEquals(OrekitMessages.UNSUPPORTED_FILE_FORMAT_VERSION, oe.getSpecifier());
105             Assertions.assertEquals(9.99, (Double) oe.getParts()[0], 0.001);
106         }
107     }
108 
109     @Test
110     public void testWrongFileType() {
111         try {
112             load("rinex/unknown-type.06o");
113             Assertions.fail("an exception should have been thrown");
114         } catch (OrekitException oe) {
115             Assertions.assertEquals(OrekitMessages.WRONG_PARSING_TYPE, oe.getSpecifier());
116         }
117     }
118 
119     @Test
120     public void testShortFirstLine() {
121         try {
122             load("rinex/short-first-line.06o");
123             Assertions.fail("an exception should have been thrown");
124         } catch (OrekitException oe) {
125             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
126             Assertions.assertEquals(1, ((Integer) oe.getParts()[0]).intValue());
127         }
128     }
129 
130     @Test
131     public void testWrongFirstLabel() {
132         try {
133             load("rinex/unknown-first-label.06o");
134             Assertions.fail("an exception should have been thrown");
135         } catch (OrekitException oe) {
136             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
137             Assertions.assertEquals(1, ((Integer) oe.getParts()[0]).intValue());
138         }
139     }
140 
141     @Test
142     public void testRinex2OptionalRecords() {
143         final RinexObservation loaded = load("rinex/cccc0000.07o");
144         final RinexObservationHeader   header = loaded.getHeader();
145         Assertions.assertEquals(0.0,
146                             Vector3D.distance(new Vector3D(1.1111, 2.2222,  3.3333),
147                                               header.getAntennaReferencePoint()),
148                             1.0e-15);
149         Assertions.assertEquals(0.0,
150                             Vector3D.distance(new Vector3D(9.9999, 8.8888, 7.7777),
151                                               header.getAntennaBSight()),
152                             1.0e-15);
153         Assertions.assertEquals(0.0,
154                             Vector3D.distance(new Vector3D(0.1455, -0.3421, 0.0024),
155                                               header.getCenterMass()),
156                             1.0e-15);
157         Assertions.assertEquals(0.0,
158                             new AbsoluteDate(2007, 9, 29, 0, 0,  0.0, TimeScalesFactory.getGPS()).
159                             durationFrom(header.getTFirstObs()),
160                             1.0e-15);
161         Assertions.assertEquals(0.0,
162                             new AbsoluteDate(2007, 9, 29, 0, 0, 30.0, TimeScalesFactory.getGPS()).
163                             durationFrom(header.getTLastObs()),
164                             1.0e-15);
165     }
166 
167     @Test
168     public void testRinex3OptionalRecords() {
169         final RinexObservation loaded = load("rinex/dddd0000.01o");
170         final RinexObservationHeader   header = loaded.getHeader();
171         Assertions.assertEquals(0.0,
172                             Vector3D.distance(new Vector3D(1.1111, 2.2222,  3.3333),
173                                               header.getAntennaReferencePoint()),
174                             1.0e-15);
175         Assertions.assertEquals(0.0,
176                             Vector3D.distance(new Vector3D(0.1111, 0.2222, 0.3333),
177                                               header.getAntennaPhaseCenter()),
178                             1.0e-15);
179         Assertions.assertEquals(0.0,
180                             Vector3D.distance(new Vector3D(9.9999, 8.8888, 7.7777),
181                                               header.getAntennaBSight()),
182                             1.0e-15);
183         Assertions.assertEquals(0.0,
184                             Vector3D.distance(new Vector3D(6.6666, 5.5555, 4.4444),
185                                               header.getAntennaZeroDirection()),
186                             1.0e-15);
187         Assertions.assertEquals(0.1010,
188                             FastMath.toDegrees(header.getAntennaAzimuth()),
189                             1.0e-15);
190         Assertions.assertEquals(0.0,
191                             Vector3D.distance(new Vector3D(0.1455, -0.3421, 0.0024),
192                                               header.getCenterMass()),
193                             1.0e-15);
194         Assertions.assertEquals(0.0,
195                             new AbsoluteDate(2018, 1, 29,  0,  0,  0.0, TimeScalesFactory.getGPS()).
196                             durationFrom(header.getTFirstObs()),
197                             1.0e-15);
198         Assertions.assertEquals(0.0,
199                             new AbsoluteDate(2018, 1, 29, 23, 59, 45.0, TimeScalesFactory.getGPS()).
200                             durationFrom(header.getTLastObs()),
201                             1.0e-15);
202     }
203 
204     @Test
205     public void testCustomSystem() {
206         final String name = "rinex/custom-system.01o";
207         final DataSource dataSource = new DataSource(name, () -> Utils.class.getClassLoader().getResourceAsStream(name));
208         final AtomicBoolean found = new AtomicBoolean(false);
209         final RinexObservation loaded = new RinexObservationParser(CustomType::new,
210                                                                    (system, timeScales) -> {
211                                                                        Assertions.assertEquals(SatelliteSystem.USER_DEFINED_K, system);
212                                                                        found.set(true);
213                                                                        return new ConstantOffsetTimeScale(system.name(),
214                                                                                                           new TimeOffset(45, TimeOffset.SECOND));
215                                                                    },
216                                                                    TimeScalesFactory.getTimeScales()).
217                                         parse(dataSource);
218         Assertions.assertTrue(found.get());
219         final Map<SatelliteSystem, List<ObservationType>> map = loaded.getHeader().getTypeObs();
220         Assertions.assertEquals(1, map.size());
221         final List<ObservationType> types = map.get(SatelliteSystem.USER_DEFINED_K);
222         Assertions.assertEquals(2, types.size());
223         Assertions.assertEquals("X1C", types.get(0).getName());
224         Assertions.assertEquals(MeasurementType.TWO_WAY_TIME_TRANSFER, types.get(0).getMeasurementType());
225         Assertions.assertEquals(1.0, types.get(0).getSignal(SatelliteSystem.USER_DEFINED_K).getRatio(), 1.0e-15);
226         Assertions.assertEquals("U09", types.get(0).getSignal(SatelliteSystem.USER_DEFINED_K).getName());
227         Assertions.assertEquals(SatelliteSystem.USER_DEFINED_K, types.get(0).getSignal(SatelliteSystem.USER_DEFINED_K).getSatelliteSystem());
228         Assertions.assertEquals(GnssSignal.F0, types.get(0).getSignal(SatelliteSystem.USER_DEFINED_K).getFrequency(), 1.0);
229         Assertions.assertNull(types.get(0).getSignal(SatelliteSystem.USER_DEFINED_A));
230         Assertions.assertNull(types.get(0).getSignal(SatelliteSystem.GALILEO));
231         Assertions.assertEquals("Y1C", types.get(1).getName());
232         Assertions.assertEquals(MeasurementType.CARRIER_PHASE, types.get(1).getMeasurementType());
233     }
234 
235     @Test
236     public void testRinex2Header() {
237 
238         //Tests Rinex 2 with only GPS Constellation
239         final RinexObservation loaded = load("rinex/jnu10110.17o");
240         Assertions.assertEquals(44, loaded.getObservationDataSets().size());
241         final RinexObservationHeader header = loaded.getHeader();
242 
243         Assertions.assertEquals(2.11, header.getFormatVersion(), 1.0e-15);
244         Assertions.assertEquals(SatelliteSystem.GPS,    header.getSatelliteSystem());
245         Assertions.assertEquals("JNU1",                 header.getMarkerName());
246         Assertions.assertNull(header.getMarkerNumber());
247         Assertions.assertEquals("Nathan Vary",          header.getObserverName());
248         Assertions.assertEquals("FAA",                  header.getAgencyName());
249         Assertions.assertEquals("82C1",                 header.getReceiverNumber());
250         Assertions.assertEquals("NOV WAASGII",          header.getReceiverType());
251         Assertions.assertEquals("",                     header.getReceiverVersion());
252         Assertions.assertEquals("",                     header.getAntennaNumber());
253         Assertions.assertEquals("MPL_WAAS_2225NW NONE", header.getAntennaType());
254         Assertions.assertEquals(-2354253.7610,          header.getApproxPos().getX(),      1.0e-4);
255         Assertions.assertEquals(-2388550.5590,          header.getApproxPos().getY(),      1.0e-4);
256         Assertions.assertEquals(5407042.5010,           header.getApproxPos().getZ(),      1.0e-4);
257         Assertions.assertEquals(0.0,                    header.getAntennaHeight(),         1.0e-4);
258         Assertions.assertEquals(0.0,                    header.getEccentricities().getX(), 1.0e-4);
259         Assertions.assertEquals(0.0,                    header.getEccentricities().getY(), 1.0e-4);
260         Assertions.assertEquals(30.0,                   header.getInterval(), 1.0e-15);
261         Assertions.assertFalse(header.getClockOffsetApplied());
262         Assertions.assertEquals(18,                     header.getLeapSeconds());
263         Assertions.assertEquals(loaded.getObservationDataSets().get(0).getRcvrClkOffset(),
264                                 new AbsoluteDate(2017, 1, 11, TimeScalesFactory.getGPS()).durationFrom(header.getTFirstObs()),
265                                 1.0e-15);
266         Assertions.assertTrue(Double.isInfinite(header.getTLastObs().durationFrom(header.getTFirstObs())));
267 
268     }
269 
270     @Test
271     public void testRinex3Header() {
272 
273         //Tests Rinex 3 with Multiple Constellations
274         final RinexObservation loaded = load("rinex/aaaa0000.00o");
275         final RinexObservationHeader header = loaded.getHeader();
276 
277         Assertions.assertEquals(3.02, header.getFormatVersion(), 1.0e-15);
278         Assertions.assertEquals(SatelliteSystem.MIXED,  header.getSatelliteSystem());
279         Assertions.assertEquals("RDLT",                 header.getMarkerName());
280         Assertions.assertEquals("RDLT",                 header.getMarkerNumber());
281         Assertions.assertEquals("OBS",                  header.getObserverName());
282         Assertions.assertEquals("AGENCY",               header.getAgencyName());
283         Assertions.assertEquals("5035K69749",           header.getReceiverNumber());
284         Assertions.assertEquals("Trimble NetR9",        header.getReceiverType());
285         Assertions.assertEquals("5.03",                 header.getReceiverVersion());
286         Assertions.assertEquals("1912118081",           header.getAntennaNumber());
287         Assertions.assertEquals("TRM57971.00     NONE", header.getAntennaType());
288         Assertions.assertEquals(2104228.6921,           header.getApproxPos().getX(),      1.0e-4);
289         Assertions.assertEquals(-5642017.3992,          header.getApproxPos().getY(),      1.0e-4);
290         Assertions.assertEquals(2095406.0835,           header.getApproxPos().getZ(),      1.0e-4);
291         Assertions.assertEquals(0.0,                    header.getAntennaHeight(),         1.0e-4);
292         Assertions.assertEquals(0.0,                    header.getEccentricities().getX(), 1.0e-4);
293         Assertions.assertEquals(0.0,                    header.getEccentricities().getY(), 1.0e-4);
294         Assertions.assertNull(header.getAntennaReferencePoint());
295         Assertions.assertNull(header.getObservationCode());
296         Assertions.assertNull(header.getAntennaPhaseCenter());
297         Assertions.assertNull(header.getAntennaBSight());
298         Assertions.assertTrue(Double.isNaN(header.getAntennaAzimuth()));
299         Assertions.assertNull(header.getAntennaZeroDirection());
300         Assertions.assertNull(header.getCenterMass());
301         Assertions.assertEquals("DBHZ",                  header.getSignalStrengthUnit());
302         Assertions.assertEquals(15.0,                    header.getInterval(), 1.0e-15);
303         Assertions.assertFalse(header.getClockOffsetApplied());
304         Assertions.assertEquals(0,                       header.getListAppliedDCBS().size());
305         Assertions.assertEquals(0,                       header.getListAppliedPCVS().size());
306         Assertions.assertEquals(3,                       header.getPhaseShiftCorrections().size());
307         Assertions.assertEquals(SatelliteSystem.GPS,     header.getPhaseShiftCorrections().get(0).getSatelliteSystem());
308         Assertions.assertEquals(PredefinedObservationType.L2X, header.getPhaseShiftCorrections().get(0).getTypeObs());
309         Assertions.assertTrue(header.getPhaseShiftCorrections().get(0).getSatsCorrected().isEmpty());
310         Assertions.assertEquals(-0.25000,                header.getPhaseShiftCorrections().get(0).getCorrection(), 1.0e-5);
311         Assertions.assertEquals(SatelliteSystem.GLONASS, header.getPhaseShiftCorrections().get(1).getSatelliteSystem());
312         Assertions.assertEquals(PredefinedObservationType.L1P,      header.getPhaseShiftCorrections().get(1).getTypeObs());
313         Assertions.assertEquals(+0.25000,                header.getPhaseShiftCorrections().get(1).getCorrection(), 1.0e-5);
314         Assertions.assertEquals(SatelliteSystem.GLONASS, header.getPhaseShiftCorrections().get(2).getSatelliteSystem());
315         Assertions.assertEquals(PredefinedObservationType.L2C,      header.getPhaseShiftCorrections().get(2).getTypeObs());
316         Assertions.assertEquals(-0.25000,                header.getPhaseShiftCorrections().get(2).getCorrection(), 1.0e-5);
317         Assertions.assertEquals( 0,                      header.getLeapSeconds());
318         Assertions.assertEquals( 0,                      header.getLeapSecondsFuture());
319         Assertions.assertEquals( 0,                      header.getLeapSecondsWeekNum());
320         Assertions.assertEquals( 0,                      header.getLeapSecondsDayNum());
321         Assertions.assertEquals(0.0, new AbsoluteDate(2016, 1, 11, TimeScalesFactory.getGPS()).durationFrom(header.getTFirstObs()), 1.0e-15);
322         Assertions.assertTrue(Double.isInfinite(header.getTLastObs().durationFrom(header.getTFirstObs())));
323 
324     }
325 
326     @Test
327     public void testGPSFile() {
328 
329         //Tests Rinex 2 with only GPS Constellation
330         final List<ObservationDataSet> list = load("rinex/jnu10110.17o").getObservationDataSets();
331         String[] typesobs = {"L1","L2","P1","P2","C1","S1","S2"};
332 
333         Assertions.assertEquals(44, list.size());
334 
335         checkObservation(list.get(0), false,
336                          2017, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
337                          SatelliteSystem.GPS, 2, -0.03,
338                          typesobs, PredefinedObservationType.L1, 124458652.886, 4, 0);
339         checkObservation(list.get(0), false,
340                          2017, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
341                          SatelliteSystem.GPS, 2, -0.03,
342                          typesobs, PredefinedObservationType.P1, Double.NaN, 0, 0);
343         checkObservation(list.get(3), false,
344                          2017, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
345                          SatelliteSystem.GPS, 6, -0.03,
346                          typesobs, PredefinedObservationType.S2, 42.300, 4, 0);
347         checkObservation(list.get(11), false,
348                          2017, 1, 11, 0, 0, 30, TimeScalesFactory.getGPS(),
349                          SatelliteSystem.GPS, 2, -0.08,
350                          typesobs, PredefinedObservationType.C1, 23688342.361, 4, 0);
351         checkObservation(list.get(23), false,
352                          2017, 1, 11, 0, 1, 0, TimeScalesFactory.getGPS(),
353                          SatelliteSystem.GPS, 3, 0,
354                          typesobs, PredefinedObservationType.P2, 25160656.959, 4, 0);
355         checkObservation(list.get(23), false,
356                          2017, 1, 11, 0, 1, 0, TimeScalesFactory.getGPS(),
357                          SatelliteSystem.GPS, 3, 0,
358                          typesobs, PredefinedObservationType.P1, Double.NaN, 0, 0);
359         checkObservation(list.get(43), false,
360                          2017, 1, 11, 0, 1, 30, TimeScalesFactory.getGPS(),
361                          SatelliteSystem.GPS, 30, 0,
362                          typesobs, PredefinedObservationType.S1, 41.6, 4, 0);
363 
364     }
365 
366     @Test
367     public void testMoreThan12Sats() {
368         final List<ObservationDataSet> ods = loadCompressed("rinex/bogi1210.09d.Z").getObservationDataSets();
369         Assertions.assertEquals(135, ods.size());
370         AbsoluteDate lastEpoch = null;
371         int[] satsPerEpoch = { 16, 15, 15, 15, 15, 15, 15, 14, 15 };
372         int epochCount = 0;
373         int n = 0;
374         for (final ObservationDataSet ds : ods) {
375             if (lastEpoch != null && ds.getDate().durationFrom(lastEpoch) > 1.0e-3) {
376                 Assertions.assertEquals(satsPerEpoch[epochCount], n);
377                 ++epochCount;
378                 n = 0;
379             }
380             ++n;
381             lastEpoch = ds.getDate();
382         }
383         Assertions.assertEquals(satsPerEpoch[epochCount], n);
384         Assertions.assertEquals(satsPerEpoch.length, epochCount + 1);
385     }
386 
387     @Test
388     public void testGPSGlonassFile() {
389         //Tests Rinex 2 with GPS and GLONASS Constellations
390         List<ObservationDataSet> list = load("rinex/aiub0000.00o").getObservationDataSets();
391         String[] typesobs2 = {"P1","L1","L2","P2"};
392 
393         Assertions.assertEquals(24, list.size());
394 
395         checkObservation(list.get(0), true,
396                          2001, 3, 24, 13, 10, 36, TimeScalesFactory.getGPS(),
397                          SatelliteSystem.GPS, 12, -.123456789,
398                          typesobs2, PredefinedObservationType.P1, 23629347.915, 0, 0);
399         checkObservation(list.get(1), true,
400                          2001, 3, 24, 13, 10, 36, TimeScalesFactory.getGPS(),
401                          SatelliteSystem.GPS, 9, -.123456789,
402                          typesobs2, PredefinedObservationType.L1, -0.12, 0, 9);
403         checkObservation(list.get(2), true,
404                          2001, 3, 24, 13, 10, 36, TimeScalesFactory.getGPS(),
405                          SatelliteSystem.GPS, 6, -.123456789,
406                          typesobs2, PredefinedObservationType.P2, 20607605.848, 4, 4);
407         checkObservation(list.get(3), true,
408                          2001, 3, 24, 13, 10, 54, TimeScalesFactory.getGPS(),
409                          SatelliteSystem.GPS, 12, -.123456789,
410                          typesobs2, PredefinedObservationType.L2, -41981.375, 0, 0);
411         checkObservation(list.get(6), true,
412                          2001, 3, 24, 13, 10, 54, TimeScalesFactory.getGPS(),
413                          SatelliteSystem.GLONASS, 21, -.123456789,
414                          typesobs2, PredefinedObservationType.P1, 21345678.576, 0, 0);
415         checkObservation(list.get(7), true,
416                          2001, 3, 24, 13, 10, 54, TimeScalesFactory.getGPS(),
417                          SatelliteSystem.GLONASS, 22, -.123456789,
418                          typesobs2, PredefinedObservationType.P2, Double.NaN, 0, 0);
419         checkObservation(list.get(23), true,
420                          2001, 3, 24, 13, 14, 48, TimeScalesFactory.getGPS(),
421                          SatelliteSystem.GPS, 6, -.123456234,
422                          typesobs2, PredefinedObservationType.L1, 267583.678, 1, 7);
423 
424     }
425 
426     @Test
427     public void testMultipleConstellationsFile() {
428         //Tests Rinex 3 with Multiple Constellations
429         List<ObservationDataSet> list = load("rinex/aaaa0000.00o").getObservationDataSets();
430 
431         String[] typesobsG = {"C1C","L1C","S1C","C2W","L2W","S2W","C2X","L2X","S2X","C5X","L5X","S5X"};
432         String[] typesobsR = {"C1C","L1C","S1C","C1P","L1P","S1P","C2C","L2C","S2C","C2P","L2P","S2P"};
433         String[] typesobsE = {"C1X","L1X","S1X","C5X","L5X","S5X","C7X","L7X","S7X","C8X","L8X","S8X"};
434         String[] typesobsC = {"C1I","L1I","S1I","C7I","L7I","S7I","C6I","L6I","S6I"};
435         Assertions.assertEquals(51, list.size());
436         checkObservation(list.get(0), false,
437                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
438                          SatelliteSystem.GLONASS, 10, 0.0,
439                          typesobsR, PredefinedObservationType.C1C, 23544632.969, 0, 6);
440         checkObservation(list.get(1), false,
441                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
442                          SatelliteSystem.GPS, 27, 0.0,
443                          typesobsG, PredefinedObservationType.C1C, 22399181.883, 0, 7);
444         checkObservation(list.get(9), false,
445                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
446                          SatelliteSystem.GPS, 3, 0.0,
447                          typesobsG, PredefinedObservationType.S5X,         47.600, 0, 0);
448         checkObservation(list.get(10), false,
449                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
450                          SatelliteSystem.GALILEO, 14, 0.0,
451                          typesobsE, PredefinedObservationType.L8X, 76221970.869, 0, 8);
452         checkObservation(list.get(25), false,
453                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
454                          SatelliteSystem.BEIDOU, 12, 0.0,
455                          typesobsC, PredefinedObservationType.S7I, 31.100, 0, 0);
456         checkObservation(list.get(25), false,
457                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
458                          SatelliteSystem.BEIDOU, 12, 0.0,
459                          typesobsC, PredefinedObservationType.S7I, 31.100, 0, 0);
460         checkObservation(list.get(50), false,
461                          2016, 1, 11, 0, 0, 15, TimeScalesFactory.getGPS(),
462                          SatelliteSystem.BEIDOU, 11, 0.0,
463                          typesobsC, PredefinedObservationType.C7I, 23697971.738, 0, 7);
464     }
465 
466     @Test
467     public void testMultipleConstellationsGlonassScaleFactorFile() {
468         //Tests Rinex 3 with Multiple Constellations and Scale Factor for some GLONASS Observations
469         final RinexObservation obs = load("rinex/bbbb0000.00o");
470         Assertions.assertEquals(87, obs.getHeader().getNbSat());
471 
472         List<ObservationDataSet> list = obs.getObservationDataSets();
473         String[] typesobsG2 = {"C1C","L1C","S1C","C1W","S1W","C2W","L2W","S2W","C2L","L2L","S2L","C5Q","L5Q","S5Q"};
474         String[] typesobsR2 = {"C1C","L1C","S1C","C2C","L2C","S2C"};
475         String[] typesobsE2 = {"C1C","L1C","S1C","C6C","L6C","S6C","C5Q","L5Q","S5Q","C7Q","L7Q","S7Q","C8Q","L8Q","S8Q"};
476         String[] typesobsS2 = {"C1C","L1C","S1C","C5I","L5I","S5I"};
477         String[] typesobsC2 = {"C2I","L2I","S2I","C7I","L7I","S7I","C6I","L6I","S6I"};
478         String[] typesobsJ2 = {"C1C","L1C","S1C","C2L","L2L","S2L","C5Q","L5Q","S5Q"};
479         Assertions.assertEquals(36, list.size());
480 
481         checkObservation(list.get(0), false,
482                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
483                          SatelliteSystem.GPS, 30, 0.0,
484                          typesobsG2, PredefinedObservationType.C1C, 20422534.056, 0, 8);
485         checkObservation(list.get(2), false,
486                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
487                          SatelliteSystem.GLONASS, 10, 0.0,
488                          typesobsR2, PredefinedObservationType.S2C, 49.250, 0, 0);
489         checkObservation(list.get(2), false,
490                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
491                          SatelliteSystem.GLONASS, 10, 0.0,
492                          typesobsR2, PredefinedObservationType.C1C, 19186.904493, 0, 9);
493         checkObservation(list.get(7), false,
494                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
495                          SatelliteSystem.GALILEO, 5, 0.0,
496                          typesobsE2, PredefinedObservationType.L8Q, 103747111.324, 0, 8);
497         checkObservation(list.get(13), false,
498                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
499                          SatelliteSystem.BEIDOU, 4, 0.0,
500                          typesobsC2, PredefinedObservationType.C7I, 41010665.465, 0, 5);
501         checkObservation(list.get(13), false,
502                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
503                          SatelliteSystem.BEIDOU, 4, 0.0,
504                          typesobsC2, PredefinedObservationType.L2I, Double.NaN, 0, 0);
505         checkObservation(list.get(12), false,
506                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
507                          SatelliteSystem.SBAS, 138, 0.0,
508                          typesobsS2, PredefinedObservationType.C1C, 40430827.124, 0, 6);
509         checkObservation(list.get(12), false,
510                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
511                          SatelliteSystem.SBAS, 138, 0.0,
512                          typesobsS2, PredefinedObservationType.S5I, 39.750, 0, 0);
513         checkObservation(list.get(34), false,
514                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
515                          SatelliteSystem.QZSS, 193, 0.0,
516                          typesobsJ2, PredefinedObservationType.L2L, 168639076.823, 0, 6);
517         checkObservation(list.get(32), false,
518                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
519                          SatelliteSystem.GLONASS, 2, 0.0,
520                          typesobsR2, PredefinedObservationType.S1C, 0.0445, 0, 0);
521 
522     }
523 
524     @Test
525     public void testMultipleConstellationsGalileoScaleFactorFile() {
526         //Tests Rinex 3 with Multiple Constellations and Scale Factor for all GALILEO Observations
527         List<ObservationDataSet> list = load("rinex/bbbb0000.01o").getObservationDataSets();
528         String[] typesobsG4 = {"C1C","L1C","S1C","C1W","S1W","C2W","L2W","S2W","C2L","L2L","S2L","C5Q","L5Q","S5Q"};
529         String[] typesobsR4 = {"C1C","L1C","S1C","C2C","L2C","S2C"};
530         String[] typesobsE4 = {"C1C","L1C","S1C","C6C","L6C","S6C","C5Q","L5Q","S5Q","C7Q","L7Q","S7Q","C8Q","L8Q","S8Q"};
531         Assertions.assertEquals(36, list.size());
532 
533         checkObservation(list.get(0), false,
534                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
535                          SatelliteSystem.GPS, 30, 0.0,
536                          typesobsG4, PredefinedObservationType.C1C, 20422534.056, 0, 8);
537         checkObservation(list.get(2), false,
538                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
539                          SatelliteSystem.GLONASS, 10, 0.0,
540                          typesobsR4, PredefinedObservationType.S2C, 49.250, 0, 0);
541         checkObservation(list.get(2), false,
542                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
543                          SatelliteSystem.GLONASS, 10, 0.0,
544                          typesobsR4, PredefinedObservationType.C1C, 19186904.493, 0, 9);
545         checkObservation(list.get(7), false,
546                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
547                          SatelliteSystem.GALILEO, 5, 0.0,
548                          typesobsE4, PredefinedObservationType.L8Q, 103747.111324, 0, 8);
549         checkObservation(list.get(26), false,
550                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
551                          SatelliteSystem.GALILEO, 8, 0.0,
552                          typesobsE4, PredefinedObservationType.C1C, 23499.584944, 0, 7);
553         checkObservation(list.get(26), false,
554                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
555                          SatelliteSystem.GALILEO, 8, 0.0,
556                          typesobsE4, PredefinedObservationType.S8Q, 0.051, 0, 0);
557 
558     }
559 
560 
561     @Test
562     public void testContinuationPhaseShift() {
563         List<PhaseShiftCorrection> shifts = load("rinex/continuation-phase-shift.23o").getHeader().getPhaseShiftCorrections();
564         Assertions.assertEquals(4, shifts.size());
565         Assertions.assertEquals(SatelliteSystem.GPS,  shifts.get(0).getSatelliteSystem());
566         Assertions.assertEquals(PredefinedObservationType.L1C,  shifts.get(0).getTypeObs());
567         Assertions.assertEquals(                0.0,  shifts.get(0).getCorrection(), 1.0e-15);
568         Assertions.assertEquals(                 30,  shifts.get(0).getSatsCorrected().size());
569         Assertions.assertEquals(                 19,  shifts.get(0).getSatsCorrected().get( 0).getPRN());
570         Assertions.assertEquals(                 14,  shifts.get(0).getSatsCorrected().get( 9).getPRN());
571         Assertions.assertEquals(                  2,  shifts.get(0).getSatsCorrected().get(10).getPRN());
572         Assertions.assertEquals(                 26,  shifts.get(0).getSatsCorrected().get(19).getPRN());
573         Assertions.assertEquals(                 27,  shifts.get(0).getSatsCorrected().get(20).getPRN());
574         Assertions.assertEquals(                 29,  shifts.get(0).getSatsCorrected().get(29).getPRN());
575         Assertions.assertEquals(SatelliteSystem.GPS,  shifts.get(1).getSatelliteSystem());
576         Assertions.assertEquals(PredefinedObservationType.L2W,  shifts.get(1).getTypeObs());
577         Assertions.assertEquals(                0.0,  shifts.get(1).getCorrection(), 1.0e-15);
578         Assertions.assertEquals(                 30,  shifts.get(1).getSatsCorrected().size());
579         Assertions.assertEquals(                 19,  shifts.get(1).getSatsCorrected().get( 0).getPRN());
580         Assertions.assertEquals(                 12,  shifts.get(1).getSatsCorrected().get( 9).getPRN());
581         Assertions.assertEquals(                 28,  shifts.get(1).getSatsCorrected().get(10).getPRN());
582         Assertions.assertEquals(                 26,  shifts.get(1).getSatsCorrected().get(19).getPRN());
583         Assertions.assertEquals(                  9,  shifts.get(1).getSatsCorrected().get(20).getPRN());
584         Assertions.assertEquals(                 29,  shifts.get(1).getSatsCorrected().get(29).getPRN());
585         Assertions.assertEquals(SatelliteSystem.QZSS, shifts.get(2).getSatelliteSystem());
586         Assertions.assertEquals(PredefinedObservationType.L1C,  shifts.get(2).getTypeObs());
587         Assertions.assertEquals(                0.0,  shifts.get(2).getCorrection(), 1.0e-15);
588         Assertions.assertEquals(                  3,  shifts.get(2).getSatsCorrected().size());
589         Assertions.assertEquals(                  3,  shifts.get(2).getSatsCorrected().get( 0).getTwoDigitsRinexPRN());
590         Assertions.assertEquals(                  2,  shifts.get(2).getSatsCorrected().get( 1).getTwoDigitsRinexPRN());
591         Assertions.assertEquals(                  4,  shifts.get(2).getSatsCorrected().get( 2).getTwoDigitsRinexPRN());
592         Assertions.assertEquals(                195,  shifts.get(2).getSatsCorrected().get( 0).getPRN());
593         Assertions.assertEquals(                194,  shifts.get(2).getSatsCorrected().get( 1).getPRN());
594         Assertions.assertEquals(                196,  shifts.get(2).getSatsCorrected().get( 2).getPRN());
595         Assertions.assertEquals(SatelliteSystem.QZSS, shifts.get(3).getSatelliteSystem());
596         Assertions.assertEquals(PredefinedObservationType.L2S,  shifts.get(3).getTypeObs());
597         Assertions.assertEquals(                0.0,  shifts.get(3).getCorrection(), 1.0e-15);
598         Assertions.assertEquals(                  3,  shifts.get(3).getSatsCorrected().size());
599         Assertions.assertEquals(                  3,  shifts.get(3).getSatsCorrected().get( 0).getTwoDigitsRinexPRN());
600         Assertions.assertEquals(                  2,  shifts.get(3).getSatsCorrected().get( 1).getTwoDigitsRinexPRN());
601         Assertions.assertEquals(                  4,  shifts.get(3).getSatsCorrected().get( 2).getTwoDigitsRinexPRN());
602         Assertions.assertEquals(                195,  shifts.get(3).getSatsCorrected().get( 0).getPRN());
603         Assertions.assertEquals(                194,  shifts.get(3).getSatsCorrected().get( 1).getPRN());
604         Assertions.assertEquals(                196,  shifts.get(3).getSatsCorrected().get( 2).getPRN());
605     }
606 
607     @Test
608     public void testWrongLabel() {
609         try {
610             load("rinex/unknown-label.00o");
611             Assertions.fail("an exception should have been thrown");
612         } catch (OrekitException oe) {
613             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
614             Assertions.assertEquals(22, ((Integer) oe.getParts()[0]).intValue());
615             Assertions.assertEquals("THIS IS NOT A RINEX LABEL", ((String) oe.getParts()[2]).substring(60).trim());
616         }
617     }
618 
619     @Test
620     public void testNumberFormatError() {
621         try {
622             load("rinex/number-format-error.06o");
623             Assertions.fail("an exception should have been thrown");
624         } catch (OrekitException oe) {
625             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
626             Assertions.assertEquals(33, ((Integer) oe.getParts()[0]).intValue());
627             Assertions.assertEquals("-45####.120", ((String) oe.getParts()[2]).substring(21, 33).trim());
628         }
629     }
630 
631     @Test
632     public void testUnsupportedTimeScale() {
633         try {
634             load("rinex/unsupported-time-scale.06o");
635             Assertions.fail("an exception should have been thrown");
636         } catch (OrekitException oe) {
637             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
638             Assertions.assertEquals(18, ((Integer) oe.getParts()[0]).intValue());
639             Assertions.assertEquals("XYZ", ((String) oe.getParts()[2]).substring(48, 51).trim());
640         }
641     }
642 
643     @Test
644     public void testNoTimeScale() {
645         try {
646             load("rinex/no-time-scale.07o");
647             Assertions.fail("an exception should have been thrown");
648         } catch (OrekitException oe) {
649             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
650             Assertions.assertEquals(18, ((Integer) oe.getParts()[0]).intValue());
651             Assertions.assertEquals("", ((String) oe.getParts()[2]).substring(48, 51).trim());
652         }
653     }
654 
655     @Test
656     public void testInconsistentSatelliteSystem() {
657         try {
658             load("rinex/inconsistent-satellite-system.00o");
659             Assertions.fail("an exception should have been thrown");
660         } catch (OrekitException oe) {
661             Assertions.assertEquals(OrekitMessages.INCONSISTENT_SATELLITE_SYSTEM, oe.getSpecifier());
662             Assertions.assertEquals(SatelliteSystem.GPS,     oe.getParts()[3]);
663             Assertions.assertEquals(SatelliteSystem.GALILEO, oe.getParts()[2]);
664         }
665     }
666 
667     @Test
668     public void testInconsistentNumberOfSatellites() {
669         try {
670             load("rinex/inconsistent-number-of-sats.00o");
671             Assertions.fail("an exception should have been thrown");
672         } catch (OrekitException oe) {
673             Assertions.assertEquals(OrekitMessages.INCONSISTENT_NUMBER_OF_SATS, oe.getSpecifier());
674             Assertions.assertEquals(3, ((Integer) oe.getParts()[2]).intValue());
675             Assertions.assertEquals(2, ((Integer) oe.getParts()[3]).intValue());
676         }
677     }
678 
679     @Test
680     public void testMissingHeaderLabel() {
681         try {
682             //Test with RinexV3 Missing Label inside Header
683             load("rinex/missing-label.00o");
684             Assertions.fail("an exception should have been thrown");
685         } catch (OrekitException oe) {
686             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
687         }
688     }
689 
690     @Test
691     public void testRinex3NoMarkerName() {
692         try {
693             //Test with RinexV3 Missing MARKER NAME Label inside Header
694             load("rinex/no-markerNameV3.06o");
695             Assertions.fail("an exception should have been thrown");
696         } catch (OrekitException oe) {
697             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
698         }
699     }
700 
701     @Test
702     public void testRinex2NoMarkerName() {
703         try {
704             //Test with RinexV2 Missing MARKER NAME Label inside Header
705             load("rinex/no-markerNameV2.06o");
706             Assertions.fail("an exception should have been thrown");
707         } catch (OrekitException oe) {
708             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
709         }
710     }
711 
712     @Test
713     public void testRinex2NoObserverAgency() {
714         try {
715             //Test with RinexV2 Missing OBSERVER / AGENCY Label inside Header
716             load("rinex/no-observer-agencyV2.16o");
717             Assertions.fail("an exception should have been thrown");
718         } catch (OrekitException oe) {
719             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
720         }
721     }
722 
723     @Test
724     public void testRinex3NoRecType() {
725         try {
726             //Test with Rinex3 Missing REC # / TYPE / VERS Label inside Header
727             load("rinex/no-rec-typeV3.06o");
728             Assertions.fail("an exception should have been thrown");
729         } catch (OrekitException oe) {
730             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
731         }
732     }
733 
734     @Test
735     public void testRinex2NoRecType() {
736         try {
737             //Test with Rinex2 Missing REC # / TYPE / VERS Label inside Header
738             load("rinex/no-rec-typeV2.16o");
739             Assertions.fail("an exception should have been thrown");
740         } catch (OrekitException oe) {
741             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
742         }
743     }
744 
745     @Test
746     public void testRinex3NoAntType() {
747         try {
748             //Test with Rinex3 Missing ANT # / TYPE Label inside Header
749             load("rinex/no-ant-typeV3.06o");
750             Assertions.fail("an exception should have been thrown");
751         } catch (OrekitException oe) {
752             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
753         }
754     }
755 
756     @Test
757     public void testRinex2NoAntType() {
758         try {
759             //Test with Rinex2 Missing ANT # / TYPE Label inside Header
760             load("rinex/no-ant-typeV2.16o");
761             Assertions.fail("an exception should have been thrown");
762         } catch (OrekitException oe) {
763             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
764         }
765     }
766 
767     @Test
768     public void testRinex3ObserverAgency() {
769         try {
770             //Test with Rinex3 Missing OBSERVER / AGENCY Label inside Header
771             load("rinex/no-rec-typeV3.06o");
772             Assertions.fail("an exception should have been thrown");
773         } catch (OrekitException oe) {
774             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
775         }
776     }
777 
778     @Test
779     public void testRinex2NoApproxPosition() {
780         try {
781             //Test with Rinex2 Missing APPROX POSITION XYZ Label inside Header
782             load("rinex/no-approx-positionV2.16o");
783             Assertions.fail("an exception should have been thrown");
784         } catch (OrekitException oe) {
785             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
786         }
787     }
788 
789     @Test
790     public void testRinex2NoAntennaDelta() {
791         try {
792             //Test with Rinex2 Missing ANTENNA: DELTA H/E/N Label inside Header
793             load("rinex/no-antenna-deltaV2.16o");
794             Assertions.fail("an exception should have been thrown");
795         } catch (OrekitException oe) {
796             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
797         }
798     }
799 
800     @Test
801     public void testRinex3NoAntennaDelta() {
802         try {
803             //Test with Rinex3 Missing ANTENNA: DELTA H/E/N Label inside Header
804             load("rinex/no-antenna-deltaV3.06o");
805             Assertions.fail("an exception should have been thrown");
806         } catch (OrekitException oe) {
807             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
808         }
809     }
810 
811     @Test
812     public void testRinex2NoTimeFirstObs() {
813         try {
814             //Test with Rinex2 Missing TIME OF FIRST OBS Label inside Header
815             load("rinex/no-first-obsV2.16o");
816             Assertions.fail("an exception should have been thrown");
817         } catch (OrekitException oe) {
818             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
819         }
820     }
821 
822     @Test
823     public void testRinex3NoTimeFirstObs() {
824         try {
825             //Test with Rinex3 Missing TIME OF FIRST OBS Label inside Header
826             load("rinex/no-first-obsV3.06o");
827             Assertions.fail("an exception should have been thrown");
828         } catch (OrekitException oe) {
829             Assertions.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
830         }
831     }
832 
833     @Test
834     public void testUnknownSatelliteSystemHeader() {
835         //Test with RinexV3 Unknown Satellite System inside Header
836         final RinexObservation robs = load("rinex/unknown-satsystem.00o");
837         Assertions.assertEquals(9, robs.getHeader().getTypeObs().get(SatelliteSystem.USER_DEFINED_Z).size());
838     }
839 
840     @Test
841     public void testInconsistentNumSatellites() {
842         try {
843             //Test with RinexV3 inconsistent number of sats in an observation w/r to max sats in header
844             load("rinex/inconsistent-satsnum.00o");
845             Assertions.fail("an exception should have been thrown");
846         } catch (OrekitException oe) {
847             Assertions.assertEquals(OrekitMessages.INCONSISTENT_NUMBER_OF_SATS, oe.getSpecifier());
848             Assertions.assertEquals(25, oe.getParts()[3]); //N. max sats
849             Assertions.assertEquals(26, oe.getParts()[2]); //N. sats observation incoherent
850         }
851     }
852 
853     @Test
854     public void testInconsistentSatSystem() {
855         try {
856             //Test with RinexV3 inconsistent satellite system in an observation w/r to file sat system
857             load("rinex/inconsistent-satsystem.00o");
858             Assertions.fail("an exception should have been thrown");
859         } catch (OrekitException oe) {
860             Assertions.assertEquals(OrekitMessages.INCONSISTENT_SATELLITE_SYSTEM, oe.getSpecifier());
861             Assertions.assertEquals(SatelliteSystem.GPS, oe.getParts()[2]); //Rinex Satellite System (GPS)
862             Assertions.assertEquals(SatelliteSystem.GLONASS, oe.getParts()[3]); //First observation of a sat that is not GPS (GLONASS)
863         }
864     }
865 
866     @Test
867     public void testUnknownEventFlag3() {
868         try {
869             load("rinex/unknown-event-flag-3.00o");
870             Assertions.fail("an exception should have been thrown");
871         } catch (OrekitException oe) {
872             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
873             Assertions.assertEquals(61, ((Integer) oe.getParts()[0]).intValue());
874         }
875     }
876 
877     @Test
878     public void testUnknownEventFlag4() {
879         try {
880             load("rinex/unknown-event-flag-4.00o");
881             Assertions.fail("an exception should have been thrown");
882         } catch (OrekitException oe) {
883             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
884             Assertions.assertEquals(53, ((Integer) oe.getParts()[0]).intValue());
885         }
886     }
887 
888     @Test
889     public void testUnknownFrequency() {
890         try {
891             load("rinex/unknown-rinex-frequency.00o");
892             Assertions.fail("an exception should have been thrown");
893         } catch (OrekitException oe) {
894             Assertions.assertEquals(OrekitMessages.UNKNOWN_RINEX_FREQUENCY, oe.getSpecifier());
895             Assertions.assertEquals("AAA", oe.getParts()[0]);
896             Assertions.assertEquals(14, ((Integer) oe.getParts()[2]).intValue());
897         }
898     }
899 
900     @Test
901     public void testDCBSApplied() {
902         RinexObservation l = load("rinex/dcbs.00o");
903         Assertions.assertEquals(51, l.getObservationDataSets().size());
904         RinexObservationHeader header = l.getHeader();
905         List<AppliedDCBS> list = header.getListAppliedDCBS();
906         Assertions.assertEquals(2, list.size());
907         Assertions.assertEquals(SatelliteSystem.GPS, list.get(0).getSatelliteSystem());
908         Assertions.assertEquals("dcbs-program-name", list.get(0).getProgDCBS());
909         Assertions.assertEquals("http://example.com/GPS", list.get(0).getSourceDCBS());
910         Assertions.assertEquals(SatelliteSystem.GLONASS, list.get(1).getSatelliteSystem());
911         Assertions.assertEquals("dcbs-program-name", list.get(1).getProgDCBS());
912         Assertions.assertEquals("http://example.com/GLONASS", list.get(1).getSourceDCBS());
913         Assertions.assertEquals( 4, header.getTypeObs().size());
914         Assertions.assertEquals(12, header.getTypeObs().get(SatelliteSystem.GPS).size());
915         Assertions.assertEquals(12, header.getTypeObs().get(SatelliteSystem.GLONASS).size());
916         Assertions.assertEquals(12, header.getTypeObs().get(SatelliteSystem.GALILEO).size());
917         Assertions.assertEquals( 9, header.getTypeObs().get(SatelliteSystem.BEIDOU).size());
918         Assertions.assertEquals(PredefinedObservationType.C1I, header.getTypeObs().get(SatelliteSystem.BEIDOU).get(0));
919         Assertions.assertEquals(PredefinedObservationType.L1I, header.getTypeObs().get(SatelliteSystem.BEIDOU).get(1));
920         Assertions.assertEquals(PredefinedObservationType.S1I, header.getTypeObs().get(SatelliteSystem.BEIDOU).get(2));
921         Assertions.assertEquals(PredefinedObservationType.C7I, header.getTypeObs().get(SatelliteSystem.BEIDOU).get(3));
922         Assertions.assertEquals(PredefinedObservationType.L7I, header.getTypeObs().get(SatelliteSystem.BEIDOU).get(4));
923         Assertions.assertEquals(PredefinedObservationType.S7I, header.getTypeObs().get(SatelliteSystem.BEIDOU).get(5));
924         Assertions.assertEquals(PredefinedObservationType.C6I, header.getTypeObs().get(SatelliteSystem.BEIDOU).get(6));
925         Assertions.assertEquals(PredefinedObservationType.L6I, header.getTypeObs().get(SatelliteSystem.BEIDOU).get(7));
926         Assertions.assertEquals(PredefinedObservationType.S6I, header.getTypeObs().get(SatelliteSystem.BEIDOU).get(8));
927     }
928 
929     @Test
930     public void testPCVSApplied() {
931         RinexObservation l = load("rinex/pcvs.00o");
932         Assertions.assertEquals(51, l.getObservationDataSets().size());
933         RinexObservationHeader header = l.getHeader();
934         List<AppliedPCVS> list = header.getListAppliedPCVS();
935         Assertions.assertEquals(2, list.size());
936         Assertions.assertEquals(SatelliteSystem.GPS, list.get(0).getSatelliteSystem());
937         Assertions.assertEquals("pcvs-program-name", list.get(0).getProgPCVS());
938         Assertions.assertEquals("http://example.com/GPS", list.get(0).getSourcePCVS());
939         Assertions.assertEquals(SatelliteSystem.GLONASS, list.get(1).getSatelliteSystem());
940         Assertions.assertEquals("pcvs-program-name", list.get(1).getProgPCVS());
941         Assertions.assertEquals("http://example.com/GLONASS", list.get(1).getSourcePCVS());
942     }
943 
944     @Test
945     public void testCycleSlip() {
946         RinexObservation l = load("rinex/cycle-slip.00o");
947         Assertions.assertEquals(51, l.getObservationDataSets().size());
948         RinexObservationHeader header = l.getHeader();
949         List<AppliedPCVS> list = header.getListAppliedPCVS();
950         Assertions.assertEquals(2, list.size());
951         Assertions.assertEquals(SatelliteSystem.GPS, list.get(0).getSatelliteSystem());
952         Assertions.assertEquals("pcvs-program-name", list.get(0).getProgPCVS());
953         Assertions.assertEquals("http://example.com/GPS", list.get(0).getSourcePCVS());
954         Assertions.assertEquals(SatelliteSystem.GLONASS, list.get(1).getSatelliteSystem());
955         Assertions.assertEquals("pcvs-program-name", list.get(1).getProgPCVS());
956         Assertions.assertEquals("http://example.com/GLONASS", list.get(1).getSourcePCVS());
957     }
958 
959     @Test
960     public void testRinex220Spaceborne() {
961         RinexObservation l = load("rinex/ice12720.07o");
962         Assertions.assertEquals("SPACEBORNE", l.getHeader().getMarkerType());
963         Assertions.assertEquals(SatelliteSystem.GPS, l.getHeader().getSatelliteSystem());
964         Assertions.assertEquals(4 * 7, l.getObservationDataSets().size());
965         for (int i = 0; i < l.getObservationDataSets().size(); ++i) {
966             ObservationDataSet dataSet = l.getObservationDataSets().get(i);
967             switch (i % 7) {
968                 case 0 :
969                     Assertions.assertEquals( 1, dataSet.getSatellite().getPRN());
970                     break;
971                 case 1 :
972                     Assertions.assertEquals( 5, dataSet.getSatellite().getPRN());
973                     break;
974                 case 2 :
975                     Assertions.assertEquals( 9, dataSet.getSatellite().getPRN());
976                     break;
977                 case 3 :
978                     Assertions.assertEquals(12, dataSet.getSatellite().getPRN());
979                     break;
980                 case 4 :
981                     Assertions.assertEquals(14, dataSet.getSatellite().getPRN());
982                     break;
983                 case 5 :
984                     Assertions.assertEquals(22, dataSet.getSatellite().getPRN());
985                     break;
986                 case 6 :
987                     Assertions.assertEquals(30, dataSet.getSatellite().getPRN());
988                     break;
989             }
990             List<ObservationData> list = dataSet.getObservationData();
991             Assertions.assertEquals(9, list.size());
992             Assertions.assertEquals(PredefinedObservationType.L1, list.get(0).getObservationType());
993             Assertions.assertEquals(PredefinedObservationType.L2, list.get(1).getObservationType());
994             Assertions.assertEquals(PredefinedObservationType.P1, list.get(2).getObservationType());
995             Assertions.assertEquals(PredefinedObservationType.P2, list.get(3).getObservationType());
996             Assertions.assertEquals(PredefinedObservationType.C1, list.get(4).getObservationType());
997             Assertions.assertEquals(PredefinedObservationType.LA, list.get(5).getObservationType());
998             Assertions.assertEquals(PredefinedObservationType.S1, list.get(6).getObservationType());
999             Assertions.assertEquals(PredefinedObservationType.S2, list.get(7).getObservationType());
1000             Assertions.assertEquals(PredefinedObservationType.SA, list.get(8).getObservationType());
1001         }
1002     }
1003 
1004     @Test
1005     public void testRinex220SpaceborneScaled() {
1006         RinexObservation raw   = load("rinex/ice12720.07o");
1007         RinexObservation scaled = load("rinex/ice12720-scaled.07o");
1008         Assertions.assertEquals(4 * 7, raw.getObservationDataSets().size());
1009         Assertions.assertEquals(4 * 7, scaled.getObservationDataSets().size());
1010         for (int i = 0; i < raw.getObservationDataSets().size(); ++i) {
1011 
1012             ObservationDataSet rawDataSet    = raw.getObservationDataSets().get(i);
1013             Assertions.assertEquals("SPACEBORNE", raw.getHeader().getMarkerType());
1014             Assertions.assertEquals(SatelliteSystem.GPS, raw.getHeader().getSatelliteSystem());
1015 
1016             ObservationDataSet scaledDataSet = scaled.getObservationDataSets().get(i);
1017             Assertions.assertEquals("SPACEBORNE", scaled.getHeader().getMarkerType());
1018             Assertions.assertEquals(SatelliteSystem.GPS, scaled.getHeader().getSatelliteSystem());
1019 
1020             List<ObservationData> rawList    = rawDataSet.getObservationData();
1021             List<ObservationData> scaledList = scaledDataSet.getObservationData();
1022             Assertions.assertEquals(9, rawList.size());
1023             Assertions.assertEquals(9, scaledList.size());
1024             for (int j = 0; j < rawList.size(); ++j) {
1025                 final ObservationData rawData    = rawList.get(j);
1026                 final ObservationData scaledData = scaledList.get(j);
1027                 Assertions.assertEquals(rawData.getObservationType(), scaledData.getObservationType());
1028                 Assertions.assertEquals(rawData.getValue(), scaledData.getValue(), FastMath.ulp(rawData.getValue()));
1029             }
1030         }
1031     }
1032 
1033     @Test
1034     public void testIssue608() {
1035         //Tests Rinex 3.04 with GPS, GLONASS, Galileo and SBAS Constellations
1036         RinexObservation ods = load("rinex/brca083.06o");
1037         AbsoluteDate t0 = new AbsoluteDate(2016, 3, 24, 13, 10, 36.0, TimeScalesFactory.getGPS());
1038         Assertions.assertEquals(5, ods.getObservationDataSets().size());
1039 
1040         Assertions.assertEquals("A 9080",                     ods.getHeader().getMarkerName());
1041 
1042         // Test GPS
1043         Assertions.assertEquals(SatelliteSystem.GPS,    ods.getObservationDataSets().get(1).getSatellite().getSystem());
1044         Assertions.assertEquals(9,                      ods.getObservationDataSets().get(1).getSatellite().getPRN());
1045         Assertions.assertEquals(0.0,                    ods.getObservationDataSets().get(1).getDate().durationFrom(t0), 1.0e-15);
1046         Assertions.assertEquals(PredefinedObservationType.C1C,    ods.getObservationDataSets().get(1).getObservationData().get(0).getObservationType());
1047         Assertions.assertEquals(20891534.648,           ods.getObservationDataSets().get(1).getObservationData().get(0).getValue(), 1.0e-15);
1048 
1049         // Test SBAS
1050         Assertions.assertEquals(SatelliteSystem.SBAS,   ods.getObservationDataSets().get(4).getSatellite().getSystem());
1051         Assertions.assertEquals(120,                    ods.getObservationDataSets().get(4).getSatellite().getPRN());
1052         Assertions.assertEquals(0.0,                    ods.getObservationDataSets().get(4).getDate().durationFrom(t0), 1.0e-15);
1053         Assertions.assertEquals(PredefinedObservationType.L1C,    ods.getObservationDataSets().get(4).getObservationData().get(1).getObservationType());
1054         Assertions.assertEquals(335849.135,             ods.getObservationDataSets().get(4).getObservationData().get(1).getValue(), 1.0e-15);
1055     }
1056 
1057     @Test
1058     public void testIssue605() {
1059         // Test observation type C0, L0, S0 and D0
1060         RinexObservation ods = load("rinex/embe083.06o");
1061         AbsoluteDate t0 = new AbsoluteDate(2016, 3, 24, 13, 10, 36.0, TimeScalesFactory.getGPS());
1062         Assertions.assertEquals(5, ods.getObservationDataSets().size());
1063 
1064         // Test Glonass
1065         Assertions.assertEquals(SatelliteSystem.GLONASS, ods.getObservationDataSets().get(3).getSatellite().getSystem());
1066         Assertions.assertEquals(12,                      ods.getObservationDataSets().get(3).getSatellite().getPRN());
1067         Assertions.assertEquals(0.0,                     ods.getObservationDataSets().get(3).getDate().durationFrom(t0), 1.0e-15);
1068         Assertions.assertEquals(20427680.259,            ods.getObservationDataSets().get(3).getObservationData().get(0).getValue(), 1.0e-15);
1069         Assertions.assertEquals(-885349.430,             ods.getObservationDataSets().get(3).getObservationData().get(1).getValue(), 1.0e-15);
1070         Assertions.assertEquals(22397545.647,            ods.getObservationDataSets().get(3).getObservationData().get(3).getValue(), 1.0e-15);
1071         Assertions.assertEquals(37.594,                  ods.getObservationDataSets().get(3).getObservationData().get(4).getValue(), 1.0e-15);
1072     }
1073 
1074     @Test
1075     public void testIssue698() {
1076         // Test missing Beidou observation type for Rinex 3.04
1077         RinexObservation ods = load("rinex/abcd083.06o");
1078         AbsoluteDate t0 = new AbsoluteDate(2016, 3, 24, 13, 10, 36.0, TimeScalesFactory.getGPS());
1079         Assertions.assertEquals(2, ods.getObservationDataSets().size());
1080 
1081         // Test Beidou
1082         Assertions.assertEquals(SatelliteSystem.BEIDOU, ods.getObservationDataSets().get(1).getSatellite().getSystem());
1083         Assertions.assertEquals(6,                      ods.getObservationDataSets().get(1).getSatellite().getPRN());
1084         Assertions.assertEquals(0.0,                    ods.getObservationDataSets().get(1).getDate().durationFrom(t0), 1.0e-15);
1085         Assertions.assertEquals(41,                     ods.getObservationDataSets().get(1).getObservationData().size());
1086 
1087     }
1088 
1089     @Test
1090     public void testGlonass() {
1091         RinexObservationHeader header = load("rinex/abcd083.06o").getHeader();
1092         List<GlonassSatelliteChannel> channels = header.getGlonassChannels();
1093         Assertions.assertEquals(18, channels.size());
1094         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 0).getSatellite().getSystem());
1095         Assertions.assertEquals( 1,                      channels.get( 0).getSatellite().getPRN());
1096         Assertions.assertEquals( 1,                      channels.get( 0).getK());
1097         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 1).getSatellite().getSystem());
1098         Assertions.assertEquals( 2,                      channels.get( 1).getSatellite().getPRN());
1099         Assertions.assertEquals( 2,                      channels.get( 1).getK());
1100         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 2).getSatellite().getSystem());
1101         Assertions.assertEquals( 3,                      channels.get( 2).getSatellite().getPRN());
1102         Assertions.assertEquals( 3,                      channels.get( 2).getK());
1103         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 3).getSatellite().getSystem());
1104         Assertions.assertEquals( 4,                      channels.get( 3).getSatellite().getPRN());
1105         Assertions.assertEquals( 4,                      channels.get( 3).getK());
1106         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 4).getSatellite().getSystem());
1107         Assertions.assertEquals( 5,                      channels.get( 4).getSatellite().getPRN());
1108         Assertions.assertEquals( 5,                      channels.get( 4).getK());
1109         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 5).getSatellite().getSystem());
1110         Assertions.assertEquals( 6,                      channels.get( 5).getSatellite().getPRN());
1111         Assertions.assertEquals(-6,                      channels.get( 5).getK());
1112         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 6).getSatellite().getSystem());
1113         Assertions.assertEquals( 7,                      channels.get( 6).getSatellite().getPRN());
1114         Assertions.assertEquals(-5,                      channels.get( 6).getK());
1115         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 7).getSatellite().getSystem());
1116         Assertions.assertEquals( 8,                      channels.get( 7).getSatellite().getPRN());
1117         Assertions.assertEquals(-4,                      channels.get( 7).getK());
1118         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 8).getSatellite().getSystem());
1119         Assertions.assertEquals( 9,                      channels.get( 8).getSatellite().getPRN());
1120         Assertions.assertEquals(-3,                      channels.get( 8).getK());
1121         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get( 9).getSatellite().getSystem());
1122         Assertions.assertEquals(10,                      channels.get( 9).getSatellite().getPRN());
1123         Assertions.assertEquals(-2,                      channels.get( 9).getK());
1124         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get(10).getSatellite().getSystem());
1125         Assertions.assertEquals(11,                      channels.get(10).getSatellite().getPRN());
1126         Assertions.assertEquals(-1,                      channels.get(10).getK());
1127         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get(11).getSatellite().getSystem());
1128         Assertions.assertEquals(12,                      channels.get(11).getSatellite().getPRN());
1129         Assertions.assertEquals( 0,                      channels.get(11).getK());
1130         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get(12).getSatellite().getSystem());
1131         Assertions.assertEquals(13,                      channels.get(12).getSatellite().getPRN());
1132         Assertions.assertEquals( 1,                      channels.get(12).getK());
1133         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get(13).getSatellite().getSystem());
1134         Assertions.assertEquals(14,                      channels.get(13).getSatellite().getPRN());
1135         Assertions.assertEquals( 2,                      channels.get(13).getK());
1136         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get(14).getSatellite().getSystem());
1137         Assertions.assertEquals(15,                      channels.get(14).getSatellite().getPRN());
1138         Assertions.assertEquals( 0,                      channels.get(14).getK());
1139         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get(15).getSatellite().getSystem());
1140         Assertions.assertEquals(16,                      channels.get(15).getSatellite().getPRN());
1141         Assertions.assertEquals( 4,                      channels.get(15).getK());
1142         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get(16).getSatellite().getSystem());
1143         Assertions.assertEquals(17,                      channels.get(16).getSatellite().getPRN());
1144         Assertions.assertEquals( 5,                      channels.get(16).getK());
1145         Assertions.assertEquals(SatelliteSystem.GLONASS, channels.get(17).getSatellite().getSystem());
1146         Assertions.assertEquals(18,                      channels.get(17).getSatellite().getPRN());
1147         Assertions.assertEquals(-5,                      channels.get(17).getK());
1148     }
1149 
1150     private void checkObservation(final ObservationDataSet obser,
1151                                   final boolean clockOffsetApplied,
1152                                   final int year, final int month, final int day,
1153                                   final int hour, final int minute, final double second,
1154                                   final TimeScale timescale,
1155                                   final SatelliteSystem system, final int prnNumber,
1156                                   final double rcvrClkOffset, final String[] typesObs,
1157                                   final ObservationType rf, final double obsValue,
1158                                   final int lliValue, final int sigstrength) {
1159 
1160         final AbsoluteDate date = new AbsoluteDate(year, month, day, hour, minute, second,
1161                                                    timescale);
1162 
1163         Assertions.assertEquals(system,         obser.getSatellite().getSystem());
1164         Assertions.assertEquals(prnNumber,      obser.getSatellite().getPRN());
1165         Assertions.assertEquals(clockOffsetApplied ? 0.0 : rcvrClkOffset,
1166                                 date.durationFrom(obser.getDate()),
1167                                 1.0e-15);
1168         Assertions.assertEquals(rcvrClkOffset,  obser.getRcvrClkOffset(), 1.E-17);
1169         for (int i = 0; i < typesObs.length; i++) {
1170             final ObservationData od = obser.getObservationData().get(i);
1171             Assertions.assertEquals(PredefinedObservationType.valueOf(typesObs[i]), od.getObservationType());
1172             if (od.getObservationType() == rf) {
1173                 if (Double.isNaN(obsValue)) {
1174                     Assertions.assertTrue(Double.isNaN(od.getValue()));
1175                 } else {
1176                     Assertions.assertEquals(obsValue, od.getValue(), 1.E-3);
1177                 }
1178                 Assertions.assertEquals(lliValue,    od.getLossOfLockIndicator());
1179                 Assertions.assertEquals(sigstrength, od.getSignalStrength());
1180             }
1181         }
1182 
1183     }
1184 
1185     private RinexObservation load(final String name) {
1186         final DataSource dataSource = new DataSource(name, () -> Utils.class.getClassLoader().getResourceAsStream(name));
1187         return new RinexObservationParser().parse(dataSource);
1188      }
1189 
1190     private RinexObservation loadCompressed(final String name) {
1191         final DataSource raw = new DataSource(name.substring(name.indexOf('/') + 1),
1192                                               () -> Utils.class.getClassLoader().getResourceAsStream(name));
1193         DataSource filtered = new HatanakaCompressFilter().filter(new UnixCompressFilter().filter(raw));
1194         return new RinexObservationParser().parse(filtered);
1195      }
1196 
1197 }