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.sinex;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.BeforeEach;
22  import org.junit.jupiter.api.Test;
23  import org.orekit.Utils;
24  import org.orekit.data.DataSource;
25  import org.orekit.errors.OrekitException;
26  import org.orekit.errors.OrekitMessages;
27  import org.orekit.files.sinex.Station.ReferenceSystem;
28  import org.orekit.gnss.GnssSignal;
29  import org.orekit.gnss.PredefinedGnssSignal;
30  import org.orekit.gnss.SatInSystem;
31  import org.orekit.gnss.SatelliteSystem;
32  import org.orekit.models.earth.displacement.PsdCorrection;
33  import org.orekit.time.AbsoluteDate;
34  import org.orekit.time.DateComponents;
35  import org.orekit.time.TimeComponents;
36  import org.orekit.time.TimeScalesFactory;
37  import org.orekit.utils.Constants;
38  import org.orekit.utils.TimeSpanMap;
39  
40  import java.util.List;
41  import java.util.Map;
42  
43  import static org.junit.jupiter.api.Assertions.assertEquals;
44  import static org.junit.jupiter.api.Assertions.assertTrue;
45  
46  public class SinexParserTest {
47  
48      @BeforeEach
49      public void setUp() {
50          // Sets the root of data to read
51          Utils.setDataRoot("gnss");
52      }
53  
54      @Test
55      public void testSmallIGSSinexFile() {
56  
57          final Sinex sinex = load("/sinex/cod20842-small.snx");
58  
59          assertEquals(2, sinex.getStations().size());
60  
61          checkStation(sinex.getStations().get("ABMF"), 2019, 350, 0.0, 2019, 352, 86370, 2019, 351, 43185,
62                       "ABMF", "97103M001", Vector3D.ZERO,
63                       new Vector3D(0.291978579235962e07, -0.538374495897593e07, 0.177460486102077e07),
64                       Vector3D.ZERO, "TRM57971.00", AntennaKey.OTHER_RADOME_CODE, AntennaKey.ANY_SERIAL_NUMBER);
65  
66          checkStation(sinex.getStations().get("ABPO"), 2019, 350, 0.0, 2019, 352, 86370, 2019, 351, 43185,
67                       "ABPO", "33302M001", new Vector3D(0.0083, 0., 0.),
68                       new Vector3D(0.409721654480569e07, 0.442911920899428e07, -.206577118054971e07),
69                       Vector3D.ZERO, "ASH701945G_M", "SCIT", AntennaKey.ANY_SERIAL_NUMBER);
70  
71      }
72  
73      @Test
74      public void testSLRSinexFile() {
75  
76          final Sinex sinex = load("/sinex/SLRF2008_150928_2015.09.28.snx");
77  
78          // Test date computation using format description
79          ParseInfo<AbstractSinex> parseInfo = new ParseInfo<AbstractSinex>(TimeScalesFactory.getTimeScales()) {
80              /** {@inheritDoc} */
81              @Override
82              protected AbstractSinex build() {
83                  return null;
84              }
85          };
86          parseInfo.setTimeScale(TimeScalesFactory.getUTC());
87          final AbsoluteDate date    = parseInfo.stringEpochToAbsoluteDate("95:120:86399", false);
88          final AbsoluteDate refDate = new AbsoluteDate("1995-04-30T23:59:59.000", TimeScalesFactory.getUTC());
89          assertEquals(0., refDate.durationFrom(date), 0.);
90  
91          // Test some values
92          checkStation(sinex.getStations().get("1885"), 1996, 310, 71317, 1996, 320, 73221, 2005, 1, 0.,
93                       "1885", "12302S006", null,
94                       new Vector3D(0.318389220590831e07, 0.142146588920043e07, 0.532281398355808e07),
95                       new Vector3D(-.239370506815545e-01 / Constants.JULIAN_YEAR,
96                                    0.114173567092327e-01 / Constants.JULIAN_YEAR,
97                                    -.145139658580209e-02 / Constants.JULIAN_YEAR),
98                       null, null, null);
99  
100         checkStation(sinex.getStations().get("7082"), 1983, 313, 13398, 1984, 4, 83080, 2005, 1, 0.,
101                      "7082", "40438M001", null,
102                      new Vector3D(-.173599736285899e07, -.442504854754010e07, 0.424143058893134e07),
103                      new Vector3D(-.142509359401051e-01 / Constants.JULIAN_YEAR,
104                                   -.975043019205914e-02 / Constants.JULIAN_YEAR,
105                                   -.506419781207987e-03 / Constants.JULIAN_YEAR),
106                      null, null, null);
107     }
108 
109     @Test
110     public void testStationEccentricityXYZFile() {
111 
112         // Load file (it corresponds to a small version of the real complete file)
113         final Sinex sinex = load("/sinex/ecc_xyz-small.snx");
114         assertEquals(3, sinex.getStations().size());
115 
116         // Reference values
117         final Vector3D ecc1148 = Vector3D.ZERO;
118         final Vector3D ecc7035 = new Vector3D(-0.9670, -1.9490, 1.3990);
119         final Vector3D ecc7120 = new Vector3D(-3.0850, -1.3670, 1.2620);
120 
121         final AbsoluteDate interm1148 = new AbsoluteDate(1990, 2, 14, TimeScalesFactory.getGPS());
122         final AbsoluteDate interm7035 = new AbsoluteDate(1988, 7,  8, TimeScalesFactory.getGPS());
123         final AbsoluteDate interm7120 = new AbsoluteDate(1981, 9, 26, TimeScalesFactory.getGPS());
124 
125         // Verify
126         assertEquals(ReferenceSystem.XYZ, sinex.getStations().get("1148").getEccRefSystem());
127         assertEquals(0., ecc1148.distance(sinex.getStations().get("1148").getEccentricities(interm1148)), 1.0e-15);
128         assertEquals(ReferenceSystem.XYZ, sinex.getStations().get("7035").getEccRefSystem());
129         assertEquals(0., ecc7035.distance(sinex.getStations().get("7035").getEccentricities(interm7035)), 1.0e-15);
130         assertEquals(ReferenceSystem.XYZ, sinex.getStations().get("7120").getEccRefSystem());
131         assertEquals(0., ecc7120.distance(sinex.getStations().get("7120").getEccentricities(interm7120)), 1.0e-15);
132 
133     }
134 
135     @Test
136     public void testStationEccentricityUNEFile() {
137 
138         // Load file (it corresponds to a small version of the real complete file)
139         final Sinex sinex = load("/sinex/ecc_une-small.snx");
140         assertEquals(3, sinex.getStations().size());
141 
142         // Reference values
143         final Vector3D ecc1148 = Vector3D.ZERO;
144         final Vector3D ecc7035 = new Vector3D(2.5870, 0.0060, 0.0170);
145         final Vector3D ecc7120 = new Vector3D(3.6020, -0.0130, 0.0090);
146 
147         final AbsoluteDate interm1148 = new AbsoluteDate(1990, 2, 14, TimeScalesFactory.getGPS());
148         final AbsoluteDate interm7035 = new AbsoluteDate(1988, 7,  8, TimeScalesFactory.getGPS());
149         final AbsoluteDate interm7120 = new AbsoluteDate(1981, 9, 26, TimeScalesFactory.getGPS());
150 
151         // Verify
152         assertEquals(ReferenceSystem.UNE, sinex.getStations().get("1148").getEccRefSystem());
153         assertEquals(0., ecc1148.distance(sinex.getStations().get("1148").getEccentricities(interm1148)), 1.0e-15);
154         assertEquals(ReferenceSystem.UNE, sinex.getStations().get("7035").getEccRefSystem());
155         assertEquals(0., ecc7035.distance(sinex.getStations().get("7035").getEccentricities(interm7035)), 1.0e-15);
156         assertEquals(ReferenceSystem.UNE, sinex.getStations().get("7120").getEccRefSystem());
157         assertEquals(0., ecc7120.distance(sinex.getStations().get("7120").getEccentricities(interm7120)), 1.0e-15);
158 
159     }
160 
161     @Test
162     public void testIssue867() {
163 
164         // Load file (it corresponds to a small version of the real complete file)
165         final Sinex sinex = load("/sinex/ecc_xyz-small-multiple-ecc.snx");
166         assertEquals(4, sinex.getStations().size());
167 
168         // Verify station 7236
169         final Station  station7236    = sinex.getStations().get("7236");
170         final Vector3D refStation7236 = Vector3D.ZERO;
171         assertEquals(0.0, refStation7236.distance(station7236.getEccentricities(new AbsoluteDate("1995-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
172         assertEquals(0.0, station7236.getEccentricitiesTimeSpanMap().getFirstTransition().getDate().durationFrom(new AbsoluteDate("1988-01-01T00:00:00.000", TimeScalesFactory.getUTC())), 1.0e-15);
173         assertEquals(0.0, station7236.getEccentricitiesTimeSpanMap().getLastTransition().getDate().durationFrom(new AbsoluteDate("1999-09-30T23:59:59.000", TimeScalesFactory.getUTC())), 1.0e-15);
174 
175         // Verify station 7237
176         final Station station7237 = sinex.getStations().get("7237");
177         final Vector3D refStation7237 = Vector3D.ZERO;
178         assertEquals(0.0, refStation7237.distance(station7237.getEccentricities(new AbsoluteDate("1995-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
179         assertEquals(0.0, refStation7237.distance(station7237.getEccentricities(new AbsoluteDate("2021-12-06T17:30:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
180         assertEquals(0.0, refStation7237.distance(station7237.getEccentricities(new AbsoluteDate("2999-12-06T17:30:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
181         assertEquals(0.0, station7237.getEccentricitiesTimeSpanMap().getFirstTransition().getDate().durationFrom(new AbsoluteDate("1988-01-01T00:00:00.000", TimeScalesFactory.getUTC())), 1.0e-15);
182         Assertions.assertSame(station7237.getEccentricitiesTimeSpanMap().getLastTransition().getDate(), AbsoluteDate.FUTURE_INFINITY);
183 
184         // Verify station 7090
185         final Station station7090 = sinex.getStations().get("7090");
186         Vector3D refStation7090 = new Vector3D(-1.2030, 2.5130, -1.5440);
187         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1982-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
188         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1984-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
189         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1985-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
190         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1986-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
191         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1987-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
192         refStation7090 = new Vector3D(-1.1990, 2.5070, -1.5400);
193         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1988-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
194         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1990-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
195         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1991-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
196         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1992-01-01T12:00:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
197         refStation7090 = new Vector3D(-1.2060, 2.5010, -1.5530);
198         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1992-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
199         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1995-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
200         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("1998-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
201         refStation7090 = new Vector3D(-1.2048, 2.5019, -1.5516);
202         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("2002-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
203         refStation7090 = new Vector3D(-1.2058, 2.5026, -1.5522);
204         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("2005-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
205         refStation7090 = new Vector3D(-1.2069, 2.5034, -1.5505);
206         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("2008-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
207         refStation7090 = new Vector3D(-1.2043, 2.5040, -1.5509);
208         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("2012-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
209         refStation7090 = new Vector3D(-1.2073, 2.5034, -1.5509);
210         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("2015-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
211 
212         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("2021-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
213         assertEquals(0.0, refStation7090.distance(station7090.getEccentricities(new AbsoluteDate("2999-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
214         assertEquals(0.0, station7090.getEccentricitiesTimeSpanMap().getFirstTransition().getDate().durationFrom(new AbsoluteDate("1979-07-01T00:00:00.000", TimeScalesFactory.getUTC())), 1.0e-15);
215 
216         Assertions.assertSame(station7090.getEccentricitiesTimeSpanMap().getLastTransition().getDate(), AbsoluteDate.FUTURE_INFINITY);
217 
218         // Verify station 7092
219         final Station station7092 = sinex.getStations().get("7092");
220         Vector3D refStation7092 = new Vector3D(-3.0380, 0.6290, 0.4980);
221         assertEquals(0.0, refStation7092.distance(station7092.getEccentricities(new AbsoluteDate("1980-07-05T07:50:00.000", TimeScalesFactory.getUTC()))), 1.0e-15);
222         assertEquals(0.0, station7092.getEccentricitiesTimeSpanMap().getFirstTransition().getDate().durationFrom(new AbsoluteDate("1979-08-15T00:00:00.000", TimeScalesFactory.getUTC())), 1.0e-15);
223         assertEquals(0.0, station7092.getEccentricitiesTimeSpanMap().getLastTransition().getDate().durationFrom(new AbsoluteDate("1980-10-31T23:59:59.000", TimeScalesFactory.getUTC())), 1.0e-15);
224 
225     }
226 
227     @Test
228     public void testIssue1149() {
229         final Sinex sinex = load("/sinex/JAX0MGXFIN_20202440000_01D_000_SOL.SNX");
230         assertEquals(133, sinex.getStations().size());
231     }
232 
233     @Test
234     public void testIssue1649A() {
235         final Sinex sinex = load("/sinex/JAX0MGXFIN_20202440000_01D_000_SOL.SNX");
236         assertEquals(133, sinex.getStations().size());
237 
238         // phase centers correspond to antenna ASH700936D_M    SNOW CR143
239         // which is replaced by antenna ASH700936D_M    SNOW -----
240         final Map<GnssSignal, Vector3D> phaseCenters =
241             sinex.getStations().get("DRAG").getPhaseCenters(sinex.getFileEpochStartTime());
242         assertEquals(2, phaseCenters.size());
243 
244         // check GPS phase centers
245         Vector3D pc01 = phaseCenters.get(PredefinedGnssSignal.G01);
246         assertEquals( 0.0909, pc01.getX(), 1.0e-15);
247         assertEquals( 0.0003, pc01.getY(), 1.0e-15);
248         assertEquals(-0.0002, pc01.getZ(), 1.0e-15);
249         Vector3D pc02 = phaseCenters.get(PredefinedGnssSignal.G02);
250         assertEquals( 0.1192, pc02.getX(), 1.0e-15);
251         assertEquals( 0.0001, pc02.getY(), 1.0e-15);
252         assertEquals( 0.0001, pc02.getZ(), 1.0e-15);
253 
254     }
255 
256     @Test
257     public void testIssue1649B() {
258         final Sinex sinex = load("/sinex/ESA0OPSFIN_20241850000_01D_01D_SOL.SNX");
259         assertEquals(150, sinex.getStations().size());
260 
261         // phase centers correspond to antenna JAVRINGANT_DM   SCIS 00842
262         // which is present in the file with exact matching
263         final Map<GnssSignal, Vector3D> stationsPhaseCenters =
264             sinex.getStations().get("GUAM").getPhaseCenters(sinex.getFileEpochStartTime());
265         assertEquals(7, stationsPhaseCenters.size());
266 
267         // check GPS phase centers
268         Vector3D pc01 = stationsPhaseCenters.get(PredefinedGnssSignal.G01);
269         assertEquals( 0.0859, pc01.getX(), 1.0e-15);
270         assertEquals( 0.0003, pc01.getY(), 1.0e-15);
271         assertEquals( 0.0015, pc01.getZ(), 1.0e-15);
272         Vector3D pc02 = stationsPhaseCenters.get(PredefinedGnssSignal.G02);
273         assertEquals( 0.1166, pc02.getX(), 1.0e-15);
274         assertEquals( 0.0002, pc02.getY(), 1.0e-15);
275         assertEquals( 0.0001, pc02.getZ(), 1.0e-15);
276 
277         // check GALILEO phase centers
278         Vector3D pcE01 = stationsPhaseCenters.get(PredefinedGnssSignal.E01);
279         assertEquals( 0.0859, pcE01.getX(), 1.0e-15);
280         assertEquals( 0.0003, pcE01.getY(), 1.0e-15);
281         assertEquals( 0.0015, pcE01.getZ(), 1.0e-15);
282         Vector3D pcE05 = stationsPhaseCenters.get(PredefinedGnssSignal.E05);
283         assertEquals( 0.1247, pcE05.getX(), 1.0e-15);
284         assertEquals( 0.0003, pcE05.getY(), 1.0e-15);
285         assertEquals( 0.0000, pcE05.getZ(), 1.0e-15);
286         Vector3D pcE06 = stationsPhaseCenters.get(PredefinedGnssSignal.E06);
287         assertEquals( 0.1112, pcE06.getX(), 1.0e-15);
288         assertEquals( 0.0001, pcE06.getY(), 1.0e-15);
289         assertEquals( 0.0003, pcE06.getZ(), 1.0e-15);
290         Vector3D pcE07 = stationsPhaseCenters.get(PredefinedGnssSignal.E07);
291         assertEquals( 0.1189, pcE07.getX(), 1.0e-15);
292         assertEquals( 0.0003, pcE07.getY(), 1.0e-15);
293         assertEquals( 0.0001, pcE07.getZ(), 1.0e-15);
294         Vector3D pcE08 = stationsPhaseCenters.get(PredefinedGnssSignal.E08);
295         assertEquals( 0.1247, pcE08.getX(), 1.0e-15);
296         assertEquals( 0.0003, pcE08.getY(), 1.0e-15);
297         assertEquals( 0.0000, pcE08.getZ(), 1.0e-15);
298 
299         // check satellite phase centers
300         final Map<SatInSystem, Map<GnssSignal, Vector3D>> satellitesPhaseCenters =
301             sinex.getSatellitesPhaseCenters();
302         assertEquals(78, satellitesPhaseCenters.size());
303         final Map<GnssSignal, Vector3D> phaseCentersE223 =
304             satellitesPhaseCenters.get(new SatInSystem(SatelliteSystem.GALILEO, 223));
305         assertEquals(2, phaseCentersE223.size());
306         final Vector3D pc022301 = phaseCentersE223.get(PredefinedGnssSignal.E01);
307         assertEquals( 0.1222, pc022301.getX(), 1.0e-15);
308         assertEquals(-0.0109, pc022301.getY(), 1.0e-15);
309         assertEquals( 0.7296, pc022301.getZ(), 1.0e-15);
310         final Vector3D pc022305 = phaseCentersE223.get(PredefinedGnssSignal.E05);
311         assertEquals( 0.1240, pc022305.getX(), 1.0e-15);
312         assertEquals(-0.0109, pc022305.getY(), 1.0e-15);
313         assertEquals( 0.6065, pc022305.getZ(), 1.0e-15);
314 
315     }
316 
317     @Test
318     public void testUnknownGnssAntenna() {
319         try {
320             load("/sinex/cod-unknown-GNSS-antenna.snx");
321             Assertions.fail("an exception should have been thrown");
322         } catch (OrekitException oe) {
323             assertEquals(OrekitMessages.UNKNOWN_GNSS_ANTENNA, oe.getSpecifier());
324             assertEquals("ASH701945G_M", oe.getParts()[0]);
325             assertEquals("SCIT",         oe.getParts()[1]);
326             assertEquals("12345",        oe.getParts()[2]);
327         }
328     }
329 
330     @Test
331     public void testCorruptedHeader() {
332         try {
333             load("/sinex/corrupted-header.snx");
334             Assertions.fail("an exception should have been thrown");
335         } catch (OrekitException oe) {
336             assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
337             assertEquals(1, ((Integer) oe.getParts()[0]).intValue());
338         }
339     }
340 
341     @Test
342     public void testNoDataForEpoch() {
343 
344         // Load file (it corresponds to a small version of the real complete file)
345         final Sinex sinex = load("/sinex/ecc_xyz-small-multiple-ecc.snx");
346 
347         // Station 7236
348         final Station station7236 = sinex.getStations().get("7236");
349 
350         // Epoch of exception
351         final AbsoluteDate exceptionEpoch = new AbsoluteDate("1987-01-11T00:00:00.000", TimeScalesFactory.getUTC());
352 
353         // Test the exception
354         try {
355             station7236.getEccentricities(exceptionEpoch);
356             Assertions.fail("an exception should have been thrown");
357         } catch (OrekitException oe) {
358             assertEquals(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, oe.getSpecifier());
359         }
360 
361         // Test the exception
362         try {
363             station7236.getAntennaKey(exceptionEpoch);
364             Assertions.fail("an exception should have been thrown");
365         } catch (OrekitException oe) {
366             assertEquals(OrekitMessages.MISSING_STATION_DATA_FOR_EPOCH, oe.getSpecifier());
367         }
368 
369     }
370 
371     @Test
372     public void testIssue1150A() {
373         final Sinex sinex = load("/sinex/JAX0MGXFIN_20202440000_01D_000_SOL.SNX");
374         final AbsoluteDate date   = new AbsoluteDate(2020, 8, 31, 12, 0, 0.0, TimeScalesFactory.getGPS());
375         final Vector3D     ecc    = sinex.getStations().get("ABPO").getEccentricities(date);
376         assertEquals(0.0083, ecc.getX(), 1.0e-10);
377         assertEquals(0.0000, ecc.getY(), 1.0e-10);
378         assertEquals(0.0000, ecc.getZ(), 1.0e-10);
379     }
380 
381     @Test
382     public void testIssue1150B() {
383 
384         // Load file
385         final Sinex sinex = load("/sinex/issue1150.snx");
386 
387         // Verify start epoch for station "1148" is equal to the file start epoch
388         final Station station1148 = sinex.getStations().get("1148");
389         assertEquals(0.0, sinex.getFileEpochStartTime().durationFrom(station1148.getEccentricitiesTimeSpanMap().getFirstTransition().getDate()));
390 
391         // Verify end epoch for station "7035" is equal future infinity
392         final Station station7035 = sinex.getStations().get("7035");
393         Assertions.assertSame(station7035.getEccentricitiesTimeSpanMap().getLastTransition().getDate(), AbsoluteDate.FUTURE_INFINITY);
394 
395         // Verify start epoch for station "7120" is equal to the file start epoch
396         final Station station7120 = sinex.getStations().get("7120");
397         assertEquals(0.0, sinex.getFileEpochStartTime().durationFrom(station7120.getEccentricitiesTimeSpanMap().getFirstTransition().getDate()));
398         Assertions.assertSame(station7120.getEccentricitiesTimeSpanMap().getLastTransition().getDate(), AbsoluteDate.FUTURE_INFINITY);
399 
400     }
401 
402     @Test
403     public void testCorruptedFile() {
404         try {
405             load("/sinex/cod20842-corrupted.snx");
406             Assertions.fail("an exception should have been thrown");
407         } catch (OrekitException oe) {
408             assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
409             assertEquals(52, ((Integer) oe.getParts()[0]).intValue());
410         }
411     }
412 
413     @Test
414     public void testUnknownFrequencyCode() {
415         try {
416             load("/sinex/unknown-frequency-code.snx");
417             Assertions.fail("an exception should have been thrown");
418         } catch (OrekitException oe) {
419             assertEquals(OrekitMessages.UNKNOWN_GNSS_FREQUENCY, oe.getSpecifier());
420             assertEquals(SatelliteSystem.GLONASS, oe.getParts()[0]);
421             assertEquals(7, oe.getParts()[1]);
422             assertEquals(90, (Integer) oe.getParts()[2]);
423             assertTrue(((String) oe.getParts()[3]).endsWith("unknown-frequency-code.snx"));
424         }
425     }
426 
427     @Test
428     public void testPostSeismicDeformation() {
429         final Sinex sinex = load("/sinex/ITRF2020-psd-gnss.snx");
430 
431         // 2010-02-27 06:34:16 https://earthquake.usgs.gov/earthquakes/eventpage/official20100227063411530_30/executive
432         final AbsoluteDate date2010 = new AbsoluteDate(2010, 2, 27, 6, 34, 16.0, TimeScalesFactory.getUTC());
433         final TimeSpanMap<List<PsdCorrection>> psdAntuco = sinex.getStations().get("ANTC").getPsdTimeSpanMap();
434         assertEquals(2, psdAntuco.getSpansNumber());
435         final List<PsdCorrection> corr2010 = psdAntuco.getFirstNonNullSpan().getData();
436         assertEquals(5, corr2010.size());
437         assertEquals(0, corr2010.get(0).getEarthquakeDate().durationFrom(date2010));
438         assertEquals(PsdCorrection.TimeEvolution.LOG, corr2010.get(0).getEvolution());
439         assertEquals(PsdCorrection.Axis.EAST, corr2010.get(0).getAxis());
440         assertEquals(-1.28699198121674e-01, corr2010.get(0).getAmplitude(), 1.0e-14);
441         assertEquals(8.08455225832410e-01, corr2010.get(0).getRelaxationTime() / Constants.JULIAN_YEAR, 1.0e-14);
442         assertEquals(0, corr2010.get(1).getEarthquakeDate().durationFrom(date2010));
443         assertEquals(PsdCorrection.TimeEvolution.LOG, corr2010.get(1).getEvolution());
444         assertEquals(PsdCorrection.Axis.EAST, corr2010.get(1).getAxis());
445         assertEquals(-3.56937459818481e-02, corr2010.get(1).getAmplitude(), 1.0e-14);
446         assertEquals(3.53677247694474e-03, corr2010.get(1).getRelaxationTime() / Constants.JULIAN_YEAR, 1.0e-14);
447         assertEquals(0, corr2010.get(2).getEarthquakeDate().durationFrom(date2010));
448         assertEquals(PsdCorrection.TimeEvolution.LOG, corr2010.get(2).getEvolution());
449         assertEquals(PsdCorrection.Axis.NORTH, corr2010.get(2).getAxis());
450         assertEquals(8.76938710916818e-02, corr2010.get(2).getAmplitude(), 1.0e-14);
451         assertEquals(6.74719810025941e+00, corr2010.get(2).getRelaxationTime() / Constants.JULIAN_YEAR, 1.0e-14);
452         assertEquals(0, corr2010.get(3).getEarthquakeDate().durationFrom(date2010));
453         assertEquals(PsdCorrection.TimeEvolution.LOG, corr2010.get(3).getEvolution());
454         assertEquals(PsdCorrection.Axis.NORTH, corr2010.get(3).getAxis());
455         assertEquals(1.23511869822841e-02, corr2010.get(3).getAmplitude(), 1.0e-14);
456         assertEquals(1.72868196121241e-02, corr2010.get(3).getRelaxationTime() / Constants.JULIAN_YEAR, 1.0e-14);
457         assertEquals(0, corr2010.get(4).getEarthquakeDate().durationFrom(date2010));
458         assertEquals(PsdCorrection.TimeEvolution.LOG, corr2010.get(4).getEvolution());
459         assertEquals(PsdCorrection.Axis.UP, corr2010.get(4).getAxis());
460         assertEquals(5.50435552310340e-02, corr2010.get(4).getAmplitude(), 1.0e-14);
461         assertEquals(4.70992312239571e-01, corr2010.get(4).getRelaxationTime() / Constants.JULIAN_YEAR, 1.0e-14);
462 
463         // 2013-08-30T16:25:03 https://earthquake.usgs.gov/earthquakes/eventpage/usb000jdt7/executive
464         // 2016-03-12T18:06:44 https://earthquake.usgs.gov/earthquakes/eventpage/at00o3xubc/executive
465         final AbsoluteDate date2013 = new AbsoluteDate(2013, 8, 30, 16, 25,  3.0, TimeScalesFactory.getUTC());
466         final AbsoluteDate date2016 = new AbsoluteDate(2016, 3, 12, 18,  6, 44.0, TimeScalesFactory.getUTC());
467         final TimeSpanMap<List<PsdCorrection>> psdAtkaIsland = sinex.getStations().get("AB01").getPsdTimeSpanMap();
468         assertEquals(3, psdAtkaIsland.getSpansNumber());
469         final List<PsdCorrection> corr2013 = psdAtkaIsland.getFirstNonNullSpan().getData();
470         assertEquals(1, corr2013.size());
471         assertEquals(0, corr2013.get(0).getEarthquakeDate().durationFrom(date2013));
472         assertEquals(PsdCorrection.TimeEvolution.EXP, corr2013.get(0).getEvolution());
473         assertEquals(PsdCorrection.Axis.NORTH, corr2013.get(0).getAxis());
474         assertEquals(-1.16779196624443e-02, corr2013.get(0).getAmplitude(), 1.0e-14);
475         assertEquals(5.02510982822891e-01, corr2013.get(0).getRelaxationTime() / Constants.JULIAN_YEAR, 1.0e-14);
476         final List<PsdCorrection> corr2016 = psdAtkaIsland.getFirstNonNullSpan().next().getData();
477         assertEquals(1, corr2016.size());
478         assertEquals(0, corr2016.get(0).getEarthquakeDate().durationFrom(date2016));
479         assertEquals(PsdCorrection.TimeEvolution.EXP, corr2016.get(0).getEvolution());
480         assertEquals(PsdCorrection.Axis.NORTH, corr2016.get(0).getAxis());
481         assertEquals(-1.31981162574364e-02, corr2016.get(0).getAmplitude(), 1.0e-14);
482         assertEquals(1.02131561331021e+00, corr2016.get(0).getRelaxationTime() / Constants.JULIAN_YEAR, 1.0e-14);
483 
484     }
485 
486     private void checkStation(final Station station, final int startYear, final int startDay, final double secInStartDay,
487                               final int endYear, final int endDay, final double secInEndDay,
488                               final int epochYear, final int epochDay, final double secInEpoch,
489                               final String siteCode, final String refDomes, final Vector3D refEcc,
490                               final Vector3D refPos, final Vector3D refVel,
491                               final String antennaName, final String radomeCode, final String serialNumber) {
492 
493         final AbsoluteDate start = new AbsoluteDate(new DateComponents(startYear, startDay),
494                                                     new TimeComponents(secInStartDay),
495                                                     TimeScalesFactory.getUTC());
496         final AbsoluteDate end = new AbsoluteDate(new DateComponents(endYear, endDay),
497                                                   new TimeComponents(secInEndDay),
498                                                   TimeScalesFactory.getUTC());
499         final AbsoluteDate epoch = new AbsoluteDate(new DateComponents(epochYear, epochDay),
500                                                     new TimeComponents(secInEpoch),
501                                                     TimeScalesFactory.getUTC());
502 
503         final AbsoluteDate midDate = start.shiftedBy(0.5 * end.durationFrom(start));
504 
505         assertEquals(0., start.durationFrom(station.getValidFrom()), 1.0e-10);
506         assertEquals(0., end.durationFrom(station.getValidUntil()),  1.0e-10);
507         assertEquals(0., epoch.durationFrom(station.getEpoch()),     1.0e-10);
508         assertEquals(siteCode, station.getSiteCode());
509         assertEquals(refDomes, station.getDomes());
510         if (refEcc != null) {
511             assertEquals(0., refEcc.distance(station.getEccentricities(midDate)), 1.0e-10);
512         }
513         assertEquals(0., refPos.distance(station.getPosition()), 1.0e-10);
514         assertEquals(0., refVel.distance(station.getVelocity()), 1.0e-10);
515         if (antennaName != null) {
516             assertEquals(new AntennaKey(antennaName, radomeCode, serialNumber),
517                                     station.getAntennaKey(midDate));
518         }
519 
520     }
521 
522     private Sinex load(final String name) {
523         return new SinexParser(TimeScalesFactory.getTimeScales()).
524                parse(new DataSource(name, () -> SinexParserTest.class.getResourceAsStream(name)));
525     }
526 
527 }