1   /* Copyright 2002-2022 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.gnss;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.util.List;
22  
23  import org.hipparchus.geometry.euclidean.threed.Vector3D;
24  import org.hipparchus.util.FastMath;
25  import org.junit.Assert;
26  import org.junit.Before;
27  import org.junit.Test;
28  import org.orekit.Utils;
29  import org.orekit.data.DataSource;
30  import org.orekit.data.UnixCompressFilter;
31  import org.orekit.errors.OrekitException;
32  import org.orekit.errors.OrekitIllegalArgumentException;
33  import org.orekit.errors.OrekitMessages;
34  import org.orekit.time.AbsoluteDate;
35  import org.orekit.time.TimeScale;
36  import org.orekit.time.TimeScalesFactory;
37  
38  public class RinexLoaderTest {
39  
40      @Before
41      public void setUp() {
42          // Sets the root of data to read
43          Utils.setDataRoot("gnss");
44      }
45  
46      @Test
47      public void testDefaultLoadRinex2() {
48          Utils.setDataRoot("rinex");
49          Assert.assertEquals(51, new RinexObservationLoader("^aaaa0000\\.00o$").getObservationDataSets().size());
50      }
51  
52      @Test
53      public void testDefaultLoadRinex3() {
54          Utils.setDataRoot("rinex");
55          Assert.assertEquals(5, new RinexObservationLoader("^brca083\\.06o$").getObservationDataSets().size());
56      }
57  
58      @Test
59      public void testReadError() {
60          try {
61              new RinexObservationLoader(new DataSource("read-error", () -> new InputStream() {
62                  public int read() throws IOException {
63                      throw new IOException("boo!");
64                  }
65              }));
66              Assert.fail("an exception should have been thrown");
67          } catch (OrekitException oe) {
68              Assert.assertEquals("boo!", oe.getSpecifier().getSourceString());
69          }
70      }
71  
72      @Test
73      public void testWrongVersion() {
74          try {
75              load("rinex/unknown-version.06o");
76              Assert.fail("an exception should have been thrown");
77          } catch (OrekitException oe) {
78              Assert.assertEquals(OrekitMessages.UNSUPPORTED_FILE_FORMAT, oe.getSpecifier());
79          }
80      }
81  
82      @Test
83      public void testWrongFileType() {
84          try {
85              load("rinex/unknown-type.06o");
86              Assert.fail("an exception should have been thrown");
87          } catch (OrekitException oe) {
88              Assert.assertEquals(OrekitMessages.UNSUPPORTED_FILE_FORMAT, oe.getSpecifier());
89          }
90      }
91  
92      @Test
93      public void testShortFirstLine() {
94          try {
95              load("rinex/short-first-line.06o");
96              Assert.fail("an exception should have been thrown");
97          } catch (OrekitException oe) {
98              Assert.assertEquals(OrekitMessages.UNSUPPORTED_FILE_FORMAT, oe.getSpecifier());
99          }
100     }
101 
102     @Test
103     public void testWrongFirstLabel() {
104         try {
105             load("rinex/unknown-first-label.06o");
106             Assert.fail("an exception should have been thrown");
107         } catch (OrekitException oe) {
108             Assert.assertEquals(OrekitMessages.UNSUPPORTED_FILE_FORMAT, oe.getSpecifier());
109         }
110     }
111 
112     @Test
113     public void testRinex2OptionalRecords() {
114         final RinexObservationLoader  loader = load("rinex/cccc0000.07o");
115         final RinexObservationHeader  header = loader.getObservationDataSets().get(0).getHeader();
116         Assert.assertEquals(0.0,
117                             Vector3D.distance(new Vector3D(1.1111, 2.2222,  3.3333),
118                                               header.getAntennaReferencePoint()),
119                             1.0e-15);
120         Assert.assertEquals(0.0,
121                             Vector3D.distance(new Vector3D(9.9999, 8.8888, 7.7777),
122                                               header.getAntennaBSight()),
123                             1.0e-15);
124         Assert.assertEquals(0.0,
125                             Vector3D.distance(new Vector3D(0.1455, -0.3421, 0.0024),
126                                               header.getCenterMass()),
127                             1.0e-15);
128         Assert.assertEquals(0.0,
129                             new AbsoluteDate(2007, 9, 29, 0, 0,  0.0, TimeScalesFactory.getGPS()).
130                             durationFrom(header.getTFirstObs()),
131                             1.0e-15);
132         Assert.assertEquals(0.0,
133                             new AbsoluteDate(2007, 9, 29, 0, 0, 30.0, TimeScalesFactory.getGPS()).
134                             durationFrom(header.getTLastObs()),
135                             1.0e-15);
136     }
137 
138     @Test
139     public void testRinex3OptionalRecords() {
140         final RinexObservationLoader  loader = load("rinex/dddd0000.01o");
141         final RinexObservationHeader  header = loader.getObservationDataSets().get(0).getHeader();
142         Assert.assertEquals(0.0,
143                             Vector3D.distance(new Vector3D(1.1111, 2.2222,  3.3333),
144                                               header.getAntennaReferencePoint()),
145                             1.0e-15);
146         Assert.assertEquals(0.0,
147                             Vector3D.distance(new Vector3D(0.1111, 0.2222, 0.3333),
148                                               header.getAntennaPhaseCenter()),
149                             1.0e-15);
150         Assert.assertEquals(0.0,
151                             Vector3D.distance(new Vector3D(9.9999, 8.8888, 7.7777),
152                                               header.getAntennaBSight()),
153                             1.0e-15);
154         Assert.assertEquals(0.0,
155                             Vector3D.distance(new Vector3D(6.6666, 5.5555, 4.4444),
156                                               header.getAntennaZeroDirection()),
157                             1.0e-15);
158         Assert.assertEquals(0.1010,
159                             header.getAntennaAzimuth(),
160                             1.0e-15);
161         Assert.assertEquals(0.0,
162                             Vector3D.distance(new Vector3D(0.1455, -0.3421, 0.0024),
163                                               header.getCenterMass()),
164                             1.0e-15);
165         Assert.assertEquals(0.0,
166                             new AbsoluteDate(2018, 1, 29,  0,  0,  0.0, TimeScalesFactory.getGPS()).
167                             durationFrom(header.getTFirstObs()),
168                             1.0e-15);
169         Assert.assertEquals(0.0,
170                             new AbsoluteDate(2018, 1, 29, 23, 59, 45.0, TimeScalesFactory.getGPS()).
171                             durationFrom(header.getTLastObs()),
172                             1.0e-15);
173     }
174 
175     @Test
176     public void testRinex2Header() {
177 
178         //Tests Rinex 2 with only GPS Constellation
179         RinexObservationLoader  loader = load("rinex/jnu10110.17o");
180         Assert.assertEquals(44, loader.getObservationDataSets().size());
181         for (ObservationDataSet dataSet : loader.getObservationDataSets()) {
182             RinexObservationHeader header = dataSet.getHeader();
183 
184             Assert.assertEquals(2.11, header.getRinexVersion(), 1.0e-15);
185             Assert.assertEquals(SatelliteSystem.GPS,    header.getSatelliteSystem());
186             Assert.assertEquals("JNU1",                 header.getMarkerName());
187             Assert.assertNull(header.getMarkerNumber());
188             Assert.assertEquals("Nathan Vary",          header.getObserverName());
189             Assert.assertEquals("FAA",                  header.getAgencyName());
190             Assert.assertEquals("82C1",                 header.getReceiverNumber());
191             Assert.assertEquals("NOV WAASGII",          header.getReceiverType());
192             Assert.assertEquals("",                     header.getReceiverVersion());
193             Assert.assertEquals("",                     header.getAntennaNumber());
194             Assert.assertEquals("MPL_WAAS_2225NW NONE", header.getAntennaType());
195             Assert.assertEquals(-2354253.7610,          header.getApproxPos().getX(),      1.0e-4);
196             Assert.assertEquals(-2388550.5590,          header.getApproxPos().getY(),      1.0e-4);
197             Assert.assertEquals(5407042.5010,           header.getApproxPos().getZ(),      1.0e-4);
198             Assert.assertEquals(0.0,                    header.getAntennaHeight(),         1.0e-4);
199             Assert.assertEquals(0.0,                    header.getEccentricities().getX(), 1.0e-4);
200             Assert.assertEquals(0.0,                    header.getEccentricities().getY(), 1.0e-4);
201             Assert.assertEquals(30.0,                   header.getInterval(), 1.0e-15);
202             Assert.assertEquals(-1,                     header.getClkOffset());
203             Assert.assertEquals(18,                     header.getLeapSeconds());
204             Assert.assertEquals(0.0, new AbsoluteDate(2017, 1, 11, TimeScalesFactory.getGPS()).durationFrom(header.getTFirstObs()), 1.0e-15);
205             Assert.assertTrue(Double.isInfinite(header.getTLastObs().durationFrom(header.getTFirstObs())));
206 
207         }
208     }
209 
210     @Test
211     public void testRinex3Header() {
212 
213         //Tests Rinex 3 with Multiple Constellations
214         RinexObservationLoader  loader = load("rinex/aaaa0000.00o");
215         for (ObservationDataSet dataSet : loader.getObservationDataSets()) {
216             RinexObservationHeader header = dataSet.getHeader();
217 
218             Assert.assertEquals(3.02, header.getRinexVersion(), 1.0e-15);
219             Assert.assertEquals(SatelliteSystem.MIXED,  header.getSatelliteSystem());
220             Assert.assertEquals("RDLT",                 header.getMarkerName());
221             Assert.assertEquals("RDLT",                 header.getMarkerNumber());
222             Assert.assertEquals("OBS",                  header.getObserverName());
223             Assert.assertEquals("AGENCY",               header.getAgencyName());
224             Assert.assertEquals("5035K69749",           header.getReceiverNumber());
225             Assert.assertEquals("Trimble NetR9",        header.getReceiverType());
226             Assert.assertEquals("5.03",                 header.getReceiverVersion());
227             Assert.assertEquals("1912118081",           header.getAntennaNumber());
228             Assert.assertEquals("TRM57971.00     NONE", header.getAntennaType());
229             Assert.assertEquals(2104228.6921,           header.getApproxPos().getX(),      1.0e-4);
230             Assert.assertEquals(-5642017.3992,          header.getApproxPos().getY(),      1.0e-4);
231             Assert.assertEquals(2095406.0835,           header.getApproxPos().getZ(),      1.0e-4);
232             Assert.assertEquals(0.0,                    header.getAntennaHeight(),         1.0e-4);
233             Assert.assertEquals(0.0,                    header.getEccentricities().getX(), 1.0e-4);
234             Assert.assertEquals(0.0,                    header.getEccentricities().getY(), 1.0e-4);
235             Assert.assertNull(header.getAntennaReferencePoint());
236             Assert.assertNull(header.getObservationCode());
237             Assert.assertNull(header.getAntennaPhaseCenter());
238             Assert.assertNull(header.getAntennaBSight());
239             Assert.assertTrue(Double.isNaN(header.getAntennaAzimuth()));
240             Assert.assertNull(header.getAntennaZeroDirection());
241             Assert.assertNull(header.getCenterMass());
242             Assert.assertEquals("DBHZ",                  header.getSignalStrengthUnit());
243             Assert.assertEquals(15.0,                    header.getInterval(), 1.0e-15);
244             Assert.assertEquals(-1,                      header.getClkOffset());
245             Assert.assertEquals(0,                       header.getListAppliedDCBS().size());
246             Assert.assertEquals(0,                       header.getListAppliedPCVS().size());
247             Assert.assertEquals(3,                       header.getPhaseShiftCorrections().size());
248             Assert.assertEquals(SatelliteSystem.GPS,     header.getPhaseShiftCorrections().get(0).getSatelliteSystem());
249             Assert.assertEquals(ObservationType.L2X,      header.getPhaseShiftCorrections().get(0).getTypeObs());
250             Assert.assertNull(header.getPhaseShiftCorrections().get(0).getSatsCorrected());
251             Assert.assertEquals(-0.25000,                header.getPhaseShiftCorrections().get(0).getCorrection(), 1.0e-5);
252             Assert.assertEquals(SatelliteSystem.GLONASS, header.getPhaseShiftCorrections().get(1).getSatelliteSystem());
253             Assert.assertEquals(ObservationType.L1P,      header.getPhaseShiftCorrections().get(1).getTypeObs());
254             Assert.assertEquals(+0.25000,                header.getPhaseShiftCorrections().get(1).getCorrection(), 1.0e-5);
255             Assert.assertEquals(SatelliteSystem.GLONASS, header.getPhaseShiftCorrections().get(2).getSatelliteSystem());
256             Assert.assertEquals(ObservationType.L2C,      header.getPhaseShiftCorrections().get(2).getTypeObs());
257             Assert.assertEquals(-0.25000,                header.getPhaseShiftCorrections().get(2).getCorrection(), 1.0e-5);
258             Assert.assertEquals( 0,                      header.getLeapSeconds());
259             Assert.assertEquals( 0,                      header.getLeapSecondsFuture());
260             Assert.assertEquals( 0,                      header.getLeapSecondsWeekNum());
261             Assert.assertEquals( 0,                      header.getLeapSecondsDayNum());
262             Assert.assertEquals(0.0, new AbsoluteDate(2016, 1, 11, TimeScalesFactory.getGPS()).durationFrom(header.getTFirstObs()), 1.0e-15);
263             Assert.assertTrue(Double.isInfinite(header.getTLastObs().durationFrom(header.getTFirstObs())));
264         }
265     }
266 
267     @Test
268     public void testGPSFile() {
269 
270         //Tests Rinex 2 with only GPS Constellation
271         RinexObservationLoader  loader = load("rinex/jnu10110.17o");
272         String[] typesobs = {"L1","L2","P1","P2","C1","S1","S2"};
273 
274         List<ObservationDataSet> list = loader.getObservationDataSets();
275         Assert.assertEquals(44, list.size());
276 
277         checkObservation(list.get(0),
278                          2017, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
279                          SatelliteSystem.GPS, 2, -0.03,
280                          typesobs, ObservationType.L1, 124458652.886, 4, 0);
281         checkObservation(list.get(0),
282                          2017, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
283                          SatelliteSystem.GPS, 2, -0.03,
284                          typesobs, ObservationType.P1, Double.NaN, 0, 0);
285         checkObservation(list.get(3),
286                          2017, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
287                          SatelliteSystem.GPS, 6, -0.03,
288                          typesobs, ObservationType.S2, 42.300, 4, 0);
289         checkObservation(list.get(11),
290                          2017, 1, 11, 0, 0, 30, TimeScalesFactory.getGPS(),
291                          SatelliteSystem.GPS, 2, -0.08,
292                          typesobs, ObservationType.C1, 23688342.361, 4, 0);
293         checkObservation(list.get(23),
294                          2017, 1, 11, 0, 1, 0, TimeScalesFactory.getGPS(),
295                          SatelliteSystem.GPS, 3, 0,
296                          typesobs, ObservationType.P2, 25160656.959, 4, 0);
297         checkObservation(list.get(23),
298                          2017, 1, 11, 0, 1, 0, TimeScalesFactory.getGPS(),
299                          SatelliteSystem.GPS, 3, 0,
300                          typesobs, ObservationType.P1, Double.NaN, 0, 0);
301         checkObservation(list.get(43),
302                          2017, 1, 11, 0, 1, 30, TimeScalesFactory.getGPS(),
303                          SatelliteSystem.GPS, 30, 0,
304                          typesobs, ObservationType.S1, 41.6, 4, 0);
305 
306     }
307 
308     @Test
309     public void testMoreThan12Sats() {
310         RinexObservationLoader  loader = loadCompressed("rinex/bogi1210.09d.Z");
311         List<ObservationDataSet> ods = loader.getObservationDataSets();
312         Assert.assertEquals(135, ods.size());
313         AbsoluteDate lastEpoch = null;
314         int[] satsPerEpoch = { 16, 15, 15, 15, 15, 15, 15, 14, 15 };
315         int epochCount = 0;
316         int n = 0;
317         for (final ObservationDataSet ds : ods) {
318             if (lastEpoch != null && ds.getDate().durationFrom(lastEpoch) > 1.0e-3) {
319                 Assert.assertEquals(satsPerEpoch[epochCount], n);
320                 ++epochCount;
321                 n = 0;
322             }
323             ++n;
324             lastEpoch = ds.getDate();
325         }
326         Assert.assertEquals(satsPerEpoch[epochCount], n);
327         Assert.assertEquals(satsPerEpoch.length, epochCount + 1);
328     }
329 
330     @Test
331     public void testGPSGlonassFile() {
332         //Tests Rinex 2 with GPS and GLONASS Constellations
333         RinexObservationLoader  loader = load("rinex/aiub0000.00o");
334         String[] typesobs2 = {"P1","L1","L2","P2"};
335 
336         List<ObservationDataSet> list = loader.getObservationDataSets();
337         Assert.assertEquals(24, list.size());
338 
339         checkObservation(list.get(0),
340                          2001, 3, 24, 13, 10, 36, TimeScalesFactory.getGPS(),
341                          SatelliteSystem.GPS, 12, -.123456789,
342                          typesobs2, ObservationType.P1, 23629347.915, 0, 0);
343         checkObservation(list.get(1),
344                          2001, 3, 24, 13, 10, 36, TimeScalesFactory.getGPS(),
345                          SatelliteSystem.GPS, 9, -.123456789,
346                          typesobs2, ObservationType.L1, -0.12, 0, 9);
347         checkObservation(list.get(2),
348                          2001, 3, 24, 13, 10, 36, TimeScalesFactory.getGPS(),
349                          SatelliteSystem.GPS, 6, -.123456789,
350                          typesobs2, ObservationType.P2, 20607605.848, 4, 4);
351         checkObservation(list.get(3),
352                          2001, 3, 24, 13, 10, 54, TimeScalesFactory.getGPS(),
353                          SatelliteSystem.GPS, 12, -.123456789,
354                          typesobs2, ObservationType.L2, -41981.375, 0, 0);
355         checkObservation(list.get(6),
356                          2001, 3, 24, 13, 10, 54, TimeScalesFactory.getGPS(),
357                          SatelliteSystem.GLONASS, 21, -.123456789,
358                          typesobs2, ObservationType.P1, 21345678.576, 0, 0);
359         checkObservation(list.get(7),
360                          2001, 3, 24, 13, 10, 54, TimeScalesFactory.getGPS(),
361                          SatelliteSystem.GLONASS, 22, -.123456789,
362                          typesobs2, ObservationType.P2, Double.NaN, 0, 0);
363         checkObservation(list.get(23),
364                          2001, 3, 24, 13, 14, 48, TimeScalesFactory.getGPS(),
365                          SatelliteSystem.GPS, 6, -.123456234,
366                          typesobs2, ObservationType.L1, 267583.678, 1, 7);
367         
368     }
369 
370     @Test
371     public void testMultipleConstellationsFile() {
372         //Tests Rinex 3 with Multiple Constellations
373         RinexObservationLoader  loader = load("rinex/aaaa0000.00o");
374 
375         String[] typesobsG = {"C1C","L1C","S1C","C2W","L2W","S2W","C2X","L2X","S2X","C5X","L5X","S5X"};
376         String[] typesobsR = {"C1C","L1C","S1C","C1P","L1P","S1P","C2C","L2C","S2C","C2P","L2P","S2P"};
377         String[] typesobsE = {"C1X","L1X","S1X","C5X","L5X","S5X","C7X","L7X","S7X","C8X","L8X","S8X"};
378         String[] typesobsC = {"C1I","L1I","S1I","C7I","L7I","S7I","C6I","L6I","S6I"};
379         List<ObservationDataSet> list = loader.getObservationDataSets();
380         Assert.assertEquals(51, list.size());
381         checkObservation(list.get(0),
382                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
383                          SatelliteSystem.GLONASS, 10, 0.0,
384                          typesobsR, ObservationType.C1C, 23544632.969, 0, 6);
385         checkObservation(list.get(1),
386                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
387                          SatelliteSystem.GPS, 27, 0.0,
388                          typesobsG, ObservationType.C1C, 22399181.883, 0, 7);
389         checkObservation(list.get(9),
390                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
391                          SatelliteSystem.GPS, 3, 0.0,
392                          typesobsG, ObservationType.S5X,         47.600, 0, 0);
393         checkObservation(list.get(10),
394                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
395                          SatelliteSystem.GALILEO, 14, 0.0,
396                          typesobsE, ObservationType.L8X, 76221970.869, 0, 8);
397         checkObservation(list.get(25),
398                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
399                          SatelliteSystem.BEIDOU, 12, 0.0,
400                          typesobsC, ObservationType.S7I, 31.100, 0, 0);
401         checkObservation(list.get(25),
402                          2016, 1, 11, 0, 0, 0, TimeScalesFactory.getGPS(),
403                          SatelliteSystem.BEIDOU, 12, 0.0,
404                          typesobsC, ObservationType.S7I, 31.100, 0, 0);
405         checkObservation(list.get(50),
406                          2016, 1, 11, 0, 0, 15, TimeScalesFactory.getGPS(),
407                          SatelliteSystem.BEIDOU, 11, 0.0,
408                          typesobsC, ObservationType.C7I, 23697971.738, 0, 7);
409     }
410 
411     @Test
412     public void testMultipleConstellationsGlonassScaleFactorFile() {
413         //Tests Rinex 3 with Multiple Constellations and Scale Factor for some GLONASS Observations
414         RinexObservationLoader  loader = load("rinex/bbbb0000.00o");
415         String[] typesobsG2 = {"C1C","L1C","S1C","C1W","S1W","C2W","L2W","S2W","C2L","L2L","S2L","C5Q","L5Q","S5Q"};
416         String[] typesobsR2 = {"C1C","L1C","S1C","C2C","L2C","S2C"};
417         String[] typesobsE2 = {"C1C","L1C","S1C","C6C","L6C","S6C","C5Q","L5Q","S5Q","C7Q","L7Q","S7Q","C8Q","L8Q","S8Q"};
418         String[] typesobsS2 = {"C1C","L1C","S1C","C5I","L5I","S5I"};
419         String[] typesobsC2 = {"C2I","L2I","S2I","C7I","L7I","S7I","C6I","L6I","S6I"};
420         String[] typesobsJ2 = {"C1C","L1C","S1C","C2L","L2L","S2L","C5Q","L5Q","S5Q"};
421         List<ObservationDataSet> list = loader.getObservationDataSets();
422         Assert.assertEquals(36, list.size());
423 
424         checkObservation(list.get(0),
425                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
426                          SatelliteSystem.GPS, 30, 0.0,
427                          typesobsG2, ObservationType.C1C, 20422534.056, 0, 8);
428         checkObservation(list.get(2),
429                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
430                          SatelliteSystem.GLONASS, 10, 0.0,
431                          typesobsR2, ObservationType.S2C, 49.250, 0, 0);
432         checkObservation(list.get(2),
433                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
434                          SatelliteSystem.GLONASS, 10, 0.0,
435                          typesobsR2, ObservationType.C1C, 19186.904493, 0, 9);
436         checkObservation(list.get(7),
437                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
438                          SatelliteSystem.GALILEO, 5, 0.0,
439                          typesobsE2, ObservationType.L8Q, 103747111.324, 0, 8);
440         checkObservation(list.get(13),
441                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
442                          SatelliteSystem.BEIDOU, 4, 0.0,
443                          typesobsC2, ObservationType.C7I, 41010665.465, 0, 5);
444         checkObservation(list.get(13),
445                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
446                          SatelliteSystem.BEIDOU, 4, 0.0,
447                          typesobsC2, ObservationType.L2I, Double.NaN, 0, 0);
448         checkObservation(list.get(12),
449                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
450                          SatelliteSystem.SBAS, 138, 0.0,
451                          typesobsS2, ObservationType.C1C, 40430827.124, 0, 6);
452         checkObservation(list.get(12),
453                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
454                          SatelliteSystem.SBAS, 138, 0.0,
455                          typesobsS2, ObservationType.S5I, 39.750, 0, 0);
456         checkObservation(list.get(34),
457                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
458                          SatelliteSystem.QZSS, 193, 0.0,
459                          typesobsJ2, ObservationType.L2L, 168639076.823, 0, 6);
460         checkObservation(list.get(32),
461                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
462                          SatelliteSystem.GLONASS, 2, 0.0,
463                          typesobsR2, ObservationType.S1C, 0.0445, 0, 0);
464     }
465 
466     @Test
467     public void testMultipleConstellationsGalileoScaleFactorFile() {
468         //Tests Rinex 3 with Multiple Constellations and Scale Factor for all GALILEO Observations
469         RinexObservationLoader  loader = load("rinex/bbbb0000.01o");
470         String[] typesobsG4 = {"C1C","L1C","S1C","C1W","S1W","C2W","L2W","S2W","C2L","L2L","S2L","C5Q","L5Q","S5Q"};
471         String[] typesobsR4 = {"C1C","L1C","S1C","C2C","L2C","S2C"};
472         String[] typesobsE4 = {"C1C","L1C","S1C","C6C","L6C","S6C","C5Q","L5Q","S5Q","C7Q","L7Q","S7Q","C8Q","L8Q","S8Q"};
473         List<ObservationDataSet> list = loader.getObservationDataSets();
474         Assert.assertEquals(36, list.size());
475 
476         checkObservation(list.get(0),
477                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
478                          SatelliteSystem.GPS, 30, 0.0,
479                          typesobsG4, ObservationType.C1C, 20422534.056, 0, 8);
480         checkObservation(list.get(2),
481                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
482                          SatelliteSystem.GLONASS, 10, 0.0,
483                          typesobsR4, ObservationType.S2C, 49.250, 0, 0);
484         checkObservation(list.get(2),
485                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
486                          SatelliteSystem.GLONASS, 10, 0.0,
487                          typesobsR4, ObservationType.C1C, 19186904.493, 0, 9);
488         checkObservation(list.get(7),
489                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
490                          SatelliteSystem.GALILEO, 5, 0.0,
491                          typesobsE4, ObservationType.L8Q, 103747.111324, 0, 8);
492         checkObservation(list.get(26),
493                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
494                          SatelliteSystem.GALILEO, 8, 0.0,
495                          typesobsE4, ObservationType.C1C, 23499.584944, 0, 7);
496         checkObservation(list.get(26),
497                          2018, 1, 29, 0, 0, 0, TimeScalesFactory.getGPS(),
498                          SatelliteSystem.GALILEO, 8, 0.0,
499                          typesobsE4, ObservationType.S8Q, 0.051, 0, 0);
500 
501     }
502     
503     
504     @Test
505     public void testWrongLabel() {
506         try {
507             load("rinex/unknown-label.00o");
508             Assert.fail("an exception should have been thrown");
509         } catch (OrekitException oe) {
510             Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
511             Assert.assertEquals(22, ((Integer) oe.getParts()[0]).intValue());
512             Assert.assertEquals("THIS IS NOT A RINEX LABEL", ((String) oe.getParts()[2]).substring(60).trim());
513         }
514     }
515     
516     @Test
517     public void testMissingHeaderLabel() {
518         try {
519             //Test with RinexV3 Missing Label inside Header
520             load("rinex/missing-label.00o");
521             Assert.fail("an exception should have been thrown");
522         } catch (OrekitException oe) {
523             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
524         }
525     }
526 
527     @Test
528     public void testRinex3NoMarkerName() {
529         try {
530             //Test with RinexV3 Missing MARKER NAME Label inside Header
531             load("rinex/no-markerNameV3.06o");
532             Assert.fail("an exception should have been thrown");
533         } catch (OrekitException oe) {
534             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
535         }
536     }
537 
538     @Test
539     public void testRinex2NoMarkerName() {
540         try {
541             //Test with RinexV2 Missing MARKER NAME Label inside Header
542             load("rinex/no-markerNameV2.06o");
543             Assert.fail("an exception should have been thrown");
544         } catch (OrekitException oe) {
545             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
546         }
547     }
548 
549     @Test
550     public void testRinex2NoObserverAgency() {
551         try {
552             //Test with RinexV2 Missing OBSERVER / AGENCY Label inside Header
553             load("rinex/no-observer-agencyV2.16o");
554             Assert.fail("an exception should have been thrown");
555         } catch (OrekitException oe) {
556             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
557         }
558     }
559 
560     @Test
561     public void testRinex3NoRecType() {
562         try {
563             //Test with Rinex3 Missing REC # / TYPE / VERS Label inside Header
564             load("rinex/no-rec-typeV3.06o");
565             Assert.fail("an exception should have been thrown");
566         } catch (OrekitException oe) {
567             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
568         }
569     }
570 
571     @Test
572     public void testRinex2NoRecType() {
573         try {
574             //Test with Rinex2 Missing REC # / TYPE / VERS Label inside Header
575             load("rinex/no-rec-typeV2.16o");
576             Assert.fail("an exception should have been thrown");
577         } catch (OrekitException oe) {
578             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
579         }
580     }
581 
582     @Test
583     public void testRinex3NoAntType() {
584         try {
585             //Test with Rinex3 Missing ANT # / TYPE Label inside Header
586             load("rinex/no-ant-typeV3.06o");
587             Assert.fail("an exception should have been thrown");
588         } catch (OrekitException oe) {
589             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
590         }
591     }
592 
593     @Test
594     public void testRinex2NoAntType() {
595         try {
596             //Test with Rinex2 Missing ANT # / TYPE Label inside Header
597             load("rinex/no-ant-typeV2.16o");
598             Assert.fail("an exception should have been thrown");
599         } catch (OrekitException oe) {
600             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
601         }
602     }
603 
604     @Test
605     public void testRinex3ObserverAgency() {
606         try {
607             //Test with Rinex3 Missing OBSERVER / AGENCY Label inside Header
608             load("rinex/no-rec-typeV3.06o");
609             Assert.fail("an exception should have been thrown");
610         } catch (OrekitException oe) {
611             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
612         }
613     }
614 
615     @Test
616     public void testRinex2NoApproxPosition() {
617         try {
618             //Test with Rinex2 Missing APPROX POSITION XYZ Label inside Header
619             load("rinex/no-approx-positionV2.16o");
620             Assert.fail("an exception should have been thrown");
621         } catch (OrekitException oe) {
622             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
623         }
624     }
625 
626     @Test
627     public void testRinex2NoAntennaDelta() {
628         try {
629             //Test with Rinex2 Missing ANTENNA: DELTA H/E/N Label inside Header
630             load("rinex/no-antenna-deltaV2.16o");
631             Assert.fail("an exception should have been thrown");
632         } catch (OrekitException oe) {
633             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
634         }
635     }
636 
637     @Test
638     public void testRinex3NoAntennaDelta() {
639         try {
640             //Test with Rinex3 Missing ANTENNA: DELTA H/E/N Label inside Header
641             load("rinex/no-antenna-deltaV3.06o");
642             Assert.fail("an exception should have been thrown");
643         } catch (OrekitException oe) {
644             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
645         }
646     }
647 
648     @Test
649     public void testRinex2NoTimeFirstObs() {
650         try {
651             //Test with Rinex2 Missing TIME OF FIRST OBS Label inside Header
652             load("rinex/no-first-obsV2.16o");
653             Assert.fail("an exception should have been thrown");
654         } catch (OrekitException oe) {
655             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
656         }
657     }
658 
659     @Test
660     public void testRinex3NoTimeFirstObs() {
661         try {
662             //Test with Rinex3 Missing TIME OF FIRST OBS Label inside Header
663             load("rinex/no-first-obsV3.06o");
664             Assert.fail("an exception should have been thrown");
665         } catch (OrekitException oe) {
666             Assert.assertEquals(OrekitMessages.INCOMPLETE_HEADER, oe.getSpecifier());
667         }
668     }
669 
670     @Test
671     public void testUnknownSatelliteSystemHeader() {
672         try {
673             //Test with RinexV3 Unknown Satellite System inside Header
674             load("rinex/unknown-satsystem.00o");
675             Assert.fail("an exception should have been thrown");
676         } catch (OrekitIllegalArgumentException oe) {
677             Assert.assertEquals(OrekitMessages.UNKNOWN_SATELLITE_SYSTEM, oe.getSpecifier());
678             Assert.assertEquals('Z', oe.getParts()[0]);
679         }
680     }
681     
682     @Test
683     public void testInconsistentNumSatellites() {
684         try {
685             //Test with RinexV3 inconsistent number of sats in an observation w/r to max sats in header
686             load("rinex/inconsistent-satsnum.00o");
687             Assert.fail("an exception should have been thrown");
688         } catch (OrekitException oe) {
689             Assert.assertEquals(OrekitMessages.INCONSISTENT_NUMBER_OF_SATS, oe.getSpecifier());
690             Assert.assertEquals(25, oe.getParts()[3]); //N. max sats
691             Assert.assertEquals(26, oe.getParts()[2]); //N. sats observation incoherent
692         }
693     }
694     
695     @Test
696     public void testInconsistentSatSystem() {
697         try {
698             //Test with RinexV3 inconsistent satellite system in an observation w/r to file sat system
699             load("rinex/inconsistent-satsystem.00o");
700             Assert.fail("an exception should have been thrown");
701         } catch (OrekitException oe) {
702             Assert.assertEquals(OrekitMessages.INCONSISTENT_SATELLITE_SYSTEM, oe.getSpecifier());
703             Assert.assertEquals(SatelliteSystem.GPS, oe.getParts()[2]); //Rinex Satellite System (GPS)
704             Assert.assertEquals(SatelliteSystem.GLONASS, oe.getParts()[3]); //First observation of a sat that is not GPS (GLONASS)
705         }
706     }
707     
708     @Test
709     public void testUnknownFrequency() {
710         try {
711             load("rinex/unknown-rinex-frequency.00o");
712             Assert.fail("an exception should have been thrown");
713         } catch (OrekitException oe) {
714             Assert.assertEquals(OrekitMessages.UNKNOWN_RINEX_FREQUENCY, oe.getSpecifier());
715             Assert.assertEquals("AAA", (String) oe.getParts()[0]);
716             Assert.assertEquals(14, ((Integer) oe.getParts()[2]).intValue());
717         }
718     }
719 
720     @Test
721     public void testDCBSApplied() {
722         RinexObservationLoader  loader = load("rinex/dcbs.00o");
723         List<ObservationDataSet> l = loader.getObservationDataSets();
724         Assert.assertEquals(51, l.size());
725         for (ObservationDataSet dataSet : l) {
726             RinexObservationHeader header = dataSet.getHeader();
727             List<AppliedDCBS> list = header.getListAppliedDCBS();
728             Assert.assertEquals(2, list.size());
729             Assert.assertEquals(SatelliteSystem.GPS, list.get(0).getSatelliteSystem());
730             Assert.assertEquals("dcbs-program-name", list.get(0).getProgDCBS());
731             Assert.assertEquals("http://example.com/GPS", list.get(0).getSourceDCBS());
732             Assert.assertEquals(SatelliteSystem.GLONASS, list.get(1).getSatelliteSystem());
733             Assert.assertEquals("dcbs-program-name", list.get(1).getProgDCBS());
734             Assert.assertEquals("http://example.com/GLONASS", list.get(1).getSourceDCBS());
735         }
736     }
737 
738     @Test
739     public void testPCVSApplied() {
740         RinexObservationLoader loader = load("rinex/pcvs.00o");
741         List<ObservationDataSet> l = loader.getObservationDataSets();
742         Assert.assertEquals(51, l.size());
743         for (ObservationDataSet dataSet : l) {
744             RinexObservationHeader header = dataSet.getHeader();
745             List<AppliedPCVS> list = header.getListAppliedPCVS();
746             Assert.assertEquals(2, list.size());
747             Assert.assertEquals(SatelliteSystem.GPS, list.get(0).getSatelliteSystem());
748             Assert.assertEquals("pcvs-program-name", list.get(0).getProgPCVS());
749             Assert.assertEquals("http://example.com/GPS", list.get(0).getSourcePCVS());
750             Assert.assertEquals(SatelliteSystem.GLONASS, list.get(1).getSatelliteSystem());
751             Assert.assertEquals("pcvs-program-name", list.get(1).getProgPCVS());
752             Assert.assertEquals("http://example.com/GLONASS", list.get(1).getSourcePCVS());
753         }
754     }
755 
756     @Test
757     public void testRinex220Spaceborne() {
758         RinexObservationLoader loader = load("rinex/ice12720.07o");
759         List<ObservationDataSet> l = loader.getObservationDataSets();
760         Assert.assertEquals(4 * 7, l.size());
761         for (int i = 0; i < l.size(); ++i) {
762             ObservationDataSet dataSet = l.get(i);
763             Assert.assertEquals("SPACEBORNE", dataSet.getHeader().getMarkerType());
764             Assert.assertEquals(SatelliteSystem.GPS, dataSet.getHeader().getSatelliteSystem());
765             switch (i % 7) {
766                 case 0 :
767                     Assert.assertEquals( 1, dataSet.getPrnNumber());
768                     break;
769                 case 1 :
770                     Assert.assertEquals( 5, dataSet.getPrnNumber());
771                     break;
772                 case 2 :
773                     Assert.assertEquals( 9, dataSet.getPrnNumber());
774                     break;
775                 case 3 :
776                     Assert.assertEquals(12, dataSet.getPrnNumber());
777                     break;
778                 case 4 :
779                     Assert.assertEquals(14, dataSet.getPrnNumber());
780                     break;
781                 case 5 :
782                     Assert.assertEquals(22, dataSet.getPrnNumber());
783                     break;
784                 case 6 :
785                     Assert.assertEquals(30, dataSet.getPrnNumber());
786                     break;
787             }
788             List<ObservationData> list = dataSet.getObservationData();
789             Assert.assertEquals(9, list.size());
790             Assert.assertEquals(ObservationType.L1, list.get(0).getObservationType());
791             Assert.assertEquals(ObservationType.L2, list.get(1).getObservationType());
792             Assert.assertEquals(ObservationType.P1, list.get(2).getObservationType());
793             Assert.assertEquals(ObservationType.P2, list.get(3).getObservationType());
794             Assert.assertEquals(ObservationType.C1, list.get(4).getObservationType());
795             Assert.assertEquals(ObservationType.LA, list.get(5).getObservationType());
796             Assert.assertEquals(ObservationType.S1, list.get(6).getObservationType());
797             Assert.assertEquals(ObservationType.S2, list.get(7).getObservationType());
798             Assert.assertEquals(ObservationType.SA, list.get(8).getObservationType());
799         }
800     }
801 
802     @Test
803     public void testRinex220SpaceborneScaled() {
804         List<ObservationDataSet> raw    = load("rinex/ice12720.07o").getObservationDataSets();
805         List<ObservationDataSet> scaled = load("rinex/ice12720-scaled.07o").getObservationDataSets();
806         Assert.assertEquals(4 * 7, raw.size());
807         Assert.assertEquals(4 * 7, scaled.size());
808         for (int i = 0; i < raw.size(); ++i) {
809 
810             ObservationDataSet rawDataSet    = raw.get(i);
811             Assert.assertEquals("SPACEBORNE", rawDataSet.getHeader().getMarkerType());
812             Assert.assertEquals(SatelliteSystem.GPS, rawDataSet.getHeader().getSatelliteSystem());
813 
814             ObservationDataSet scaledDataSet = scaled.get(i);
815             Assert.assertEquals("SPACEBORNE", scaledDataSet.getHeader().getMarkerType());
816             Assert.assertEquals(SatelliteSystem.GPS, scaledDataSet.getHeader().getSatelliteSystem());
817 
818             List<ObservationData> rawList    = rawDataSet.getObservationData();
819             List<ObservationData> scaledList = scaledDataSet.getObservationData();
820             Assert.assertEquals(9, rawList.size());
821             Assert.assertEquals(9, scaledList.size());
822             for (int j = 0; j < rawList.size(); ++j) {
823                 final ObservationData rawData    = rawList.get(j);
824                 final ObservationData scaledData = scaledList.get(j);
825                 Assert.assertEquals(rawData.getObservationType(), scaledData.getObservationType());
826                 Assert.assertEquals(rawData.getValue(), scaledData.getValue(), FastMath.ulp(rawData.getValue()));
827             }
828         }
829     }
830 
831     @Test
832     public void testIssue608() {
833         //Tests Rinex 3.04 with GPS, GLONASS, Galileo and SBAS Constellations
834         RinexObservationLoader  loader = load("rinex/brca083.06o");
835         AbsoluteDate t0 = new AbsoluteDate(2016, 3, 24, 13, 10, 36.0, TimeScalesFactory.getGPS());
836         List<ObservationDataSet> ods = loader.getObservationDataSets();
837         Assert.assertEquals(5, ods.size());
838 
839         Assert.assertEquals("A 9080",                     ods.get(2).getHeader().getMarkerName());
840 
841         // Test GPS
842         Assert.assertEquals(SatelliteSystem.GPS,    ods.get(1).getSatelliteSystem());
843         Assert.assertEquals(9,                      ods.get(1).getPrnNumber());
844         Assert.assertEquals(0.0,                    ods.get(1).getDate().durationFrom(t0), 1.0e-15);
845         Assert.assertEquals(ObservationType.C1C,    ods.get(1).getObservationData().get(0).getObservationType());
846         Assert.assertEquals(20891534.648,           ods.get(1).getObservationData().get(0).getValue(), 1.0e-15);
847 
848         // Test SBAS
849         Assert.assertEquals(SatelliteSystem.SBAS,   ods.get(4).getSatelliteSystem());
850         Assert.assertEquals(120,                    ods.get(4).getPrnNumber());
851         Assert.assertEquals(0.0,                    ods.get(4).getDate().durationFrom(t0), 1.0e-15);
852         Assert.assertEquals(ObservationType.L1C,    ods.get(4).getObservationData().get(1).getObservationType());
853         Assert.assertEquals(335849.135,           ods.get(4).getObservationData().get(1).getValue(), 1.0e-15);
854     }
855 
856     @Test
857     public void testIssue605() {
858         // Test observation type C0, L0, S0 and D0
859         RinexObservationLoader  loader = load("rinex/embe083.06o");
860         AbsoluteDate t0 = new AbsoluteDate(2016, 3, 24, 13, 10, 36.0, TimeScalesFactory.getGPS());
861         List<ObservationDataSet> ods = loader.getObservationDataSets();
862         Assert.assertEquals(5, ods.size());
863 
864         // Test Glonass
865         Assert.assertEquals(SatelliteSystem.GLONASS, ods.get(3).getSatelliteSystem());
866         Assert.assertEquals(12,                      ods.get(3).getPrnNumber());
867         Assert.assertEquals(0.0,                     ods.get(3).getDate().durationFrom(t0), 1.0e-15);
868         Assert.assertEquals(20427680.259,            ods.get(3).getObservationData().get(0).getValue(), 1.0e-15);
869         Assert.assertEquals(-885349.430,             ods.get(3).getObservationData().get(1).getValue(), 1.0e-15);
870         Assert.assertEquals(22397545.647,            ods.get(3).getObservationData().get(3).getValue(), 1.0e-15);
871         Assert.assertEquals(37.594,                  ods.get(3).getObservationData().get(4).getValue(), 1.0e-15);
872     }
873 
874     @Test
875     public void testIssue698() {
876         // Test missing Beidou observation type for Rinex 3.04
877         RinexObservationLoader  loader = load("rinex/abcd083.06o");
878         AbsoluteDate t0 = new AbsoluteDate(2016, 3, 24, 13, 10, 36.0, TimeScalesFactory.getGPS());
879         List<ObservationDataSet> ods = loader.getObservationDataSets();
880         Assert.assertEquals(2, ods.size());
881 
882         // Test Beidou
883         Assert.assertEquals(SatelliteSystem.BEIDOU, ods.get(1).getSatelliteSystem());
884         Assert.assertEquals(6,                      ods.get(1).getPrnNumber());
885         Assert.assertEquals(0.0,                    ods.get(1).getDate().durationFrom(t0), 1.0e-15);
886         Assert.assertEquals(41,                     ods.get(1).getObservationData().size());
887 
888     }
889 
890     private void checkObservation(final ObservationDataSet obser,
891                                   final int year, final int month, final int day,
892                                   final int hour, final int minute, final double second,
893                                   final TimeScale timescale,
894                                   final SatelliteSystem system, final int prnNumber,
895                                   final double rcvrClkOffset, final String[] typesObs,
896                                   final ObservationType rf, final double obsValue,
897                                   final int lliValue, final int sigstrength) {
898 
899         final AbsoluteDate date = new AbsoluteDate(year, month, day, hour, minute, second,
900                                                    timescale);
901 
902         Assert.assertEquals(system,         obser.getSatelliteSystem());
903         Assert.assertEquals(prnNumber,      obser.getPrnNumber());
904         Assert.assertEquals(date,           obser.getDate());
905         Assert.assertEquals(rcvrClkOffset,  obser.getRcvrClkOffset(), 1.E-17);
906         for (int i = 0; i < typesObs.length; i++) {
907             final ObservationData od = obser.getObservationData().get(i);
908             Assert.assertEquals(ObservationType.valueOf(typesObs[i]), od.getObservationType());
909             if (od.getObservationType() == rf) {
910                 if (Double.isNaN(obsValue)) {
911                     Assert.assertTrue(Double.isNaN(od.getValue()));
912                 } else {
913                     Assert.assertEquals(obsValue, od.getValue(), 1.E-3);
914                 }
915                 Assert.assertEquals(lliValue,    od.getLossOfLockIndicator());
916                 Assert.assertEquals(sigstrength, od.getSignalStrength());
917             }
918         }
919 
920     }
921 
922     private RinexObservationLoader load(final String name) {
923         return new RinexObservationLoader(new DataSource(name,
924                                               () -> Utils.class.getClassLoader().getResourceAsStream(name)));
925      }
926 
927     private RinexObservationLoader loadCompressed(final String name) {
928         final DataSource raw = new DataSource(name.substring(name.indexOf('/') + 1),
929                                               () -> Utils.class.getClassLoader().getResourceAsStream(name));
930         DataSource filtered = new HatanakaCompressFilter().filter(new UnixCompressFilter().filter(raw));
931         return new RinexObservationLoader(filtered);
932      }
933 
934 }