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.frames;
18  
19  import org.hipparchus.util.FastMath;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.Test;
22  import org.orekit.data.AbstractFilesLoaderTest;
23  import org.orekit.errors.OrekitException;
24  import org.orekit.errors.OrekitMessages;
25  import org.orekit.time.AbsoluteDate;
26  import org.orekit.time.ChronologicalComparator;
27  import org.orekit.time.TimeScalesFactory;
28  import org.orekit.utils.Constants;
29  import org.orekit.utils.IERSConventions;
30  
31  import java.util.SortedSet;
32  import java.util.TreeSet;
33  
34  
35  public class RapidDataAndPredictionColumnsLoaderTest extends AbstractFilesLoaderTest {
36  
37      @Test
38      public void testStartDateDaily1980() {
39          setRoot("rapid-data-columns");
40          IERSConventions.NutationCorrectionConverter converter =
41                  IERSConventions.IERS_1996.getNutationCorrectionConverter();
42          SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
43          new RapidDataAndPredictionColumnsLoader(false, "^finals\\.daily$", manager, () -> utc).fillHistory(converter, history);
44          Assertions.assertEquals(new AbsoluteDate(2011, 4, 9, TimeScalesFactory.getUTC()),
45                              new EOPHistory(IERSConventions.IERS_1996, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
46                                             history, true).getStartDate());
47      }
48  
49      @Test
50      public void testEndDateDaily1980() {
51          setRoot("rapid-data-columns");
52          IERSConventions.NutationCorrectionConverter converter =
53                  IERSConventions.IERS_1996.getNutationCorrectionConverter();
54          SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
55          new RapidDataAndPredictionColumnsLoader(false, "^finals\\.daily$", manager, () -> utc).fillHistory(converter, history);
56          Assertions.assertEquals(new AbsoluteDate(2011, 10, 6, TimeScalesFactory.getUTC()),
57                              new EOPHistory(IERSConventions.IERS_1996, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
58                                             history, true).getEndDate());
59      }
60  
61      @Test
62      public void testStartDateDaily2000() {
63          setRoot("rapid-data-columns");
64          IERSConventions.NutationCorrectionConverter converter =
65                  IERSConventions.IERS_2003.getNutationCorrectionConverter();
66          SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
67          new RapidDataAndPredictionColumnsLoader(true, "^finals\\.daily$", manager, () -> utc).fillHistory(converter, history);
68          Assertions.assertEquals(new AbsoluteDate(2011, 4, 9, TimeScalesFactory.getUTC()),
69                              new EOPHistory(IERSConventions.IERS_2003, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
70                                             history, true).getStartDate());
71      }
72  
73      @Test
74      public void testMissingColumnsPadding1980() {
75          setRoot("rapid-data-columns");
76          IERSConventions.NutationCorrectionConverter converter =
77                  IERSConventions.IERS_1996.getNutationCorrectionConverter();
78          SortedSet<EOPEntry> data = new TreeSet<EOPEntry>(new ChronologicalComparator());
79          new RapidDataAndPredictionColumnsLoader(false, "^finals\\.daily$", manager, () -> utc).fillHistory(converter, data);
80          EOPHistory history = new EOPHistory(IERSConventions.IERS_1996, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
81                                              data, true);
82  
83          // after 2011-05-31, the example daily file has no columns for Bulletin B data
84          // we don't see anything since we fall back to bulletin A
85          AbsoluteDate t1Inf = new AbsoluteDate(2011, 6, 1, TimeScalesFactory.getUTC());
86          Assertions.assertEquals(-67.724,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t1Inf)[0]), 1.0e-10);
87          Assertions.assertEquals(-11.807,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t1Inf)[1]), 1.0e-10);
88          Assertions.assertEquals(-0.2778790, history.getUT1MinusUTC(t1Inf),                                                1.0e-10);
89          Assertions.assertEquals( 0.5773,    1000 * history.getLOD(t1Inf),                                                 1.0e-10);
90          AbsoluteDate t1Sup = t1Inf.shiftedBy(Constants.JULIAN_DAY);
91          Assertions.assertEquals(-67.800,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t1Sup)[0]), 1.0e-10);
92          Assertions.assertEquals(-11.810,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t1Sup)[1]), 1.0e-10);
93          Assertions.assertEquals(-0.2784173, history.getUT1MinusUTC(t1Sup),                                                1.0e-10);
94          Assertions.assertEquals( 0.5055,    1000 * history.getLOD(t1Sup),                                                 1.0e-10);
95  
96          // after 2011-07-06, the example daily file has no columns for LOD, but it is interpolated
97          AbsoluteDate t2Inf = new AbsoluteDate(2011, 7, 6, TimeScalesFactory.getUTC());
98          Assertions.assertEquals(-72.717,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t2Inf)[0]), 1.0e-10);
99          Assertions.assertEquals(-10.620,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t2Inf)[1]), 1.0e-10);
100         Assertions.assertEquals(-0.2915826, history.getUT1MinusUTC(t2Inf),                                                1.0e-10);
101         Assertions.assertEquals( 0.5020,    1000 * history.getLOD(t2Inf),                                                 1.0e-10);
102         AbsoluteDate t2Sup = t2Inf.shiftedBy(Constants.JULIAN_DAY);
103         Assertions.assertEquals(-73.194,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t2Sup)[0]), 1.0e-10);
104         Assertions.assertEquals(-10.535,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t2Sup)[1]), 1.0e-10);
105         Assertions.assertEquals(-0.2920866, history.getUT1MinusUTC(t2Sup),                                                1.0e-10);
106         Assertions.assertEquals( 5.3509e-6, 1000 * history.getLOD(t2Sup),                                                 1.0e-10);
107 
108         // after 2011-09-19, the example daily file has no columns for nutation
109         AbsoluteDate t3Inf = new AbsoluteDate(2011, 9, 19, TimeScalesFactory.getUTC());
110         Assertions.assertEquals(-79.889,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t3Inf)[0]), 1.0e-10);
111         Assertions.assertEquals(-11.125,    3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t3Inf)[1]), 1.0e-10);
112         Assertions.assertEquals(-0.3112849, history.getUT1MinusUTC(t3Inf),                                                1.0e-10);
113         Assertions.assertEquals( 3.2137e-6, 1000 * history.getLOD(t3Inf),                                                 1.0e-10);
114         AbsoluteDate t3Sup = t3Inf.shiftedBy(Constants.JULIAN_DAY);
115         Assertions.assertEquals( 0.0,       3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t3Sup)[0]), 1.0e-10);
116         Assertions.assertEquals( 0.0,       3600000 * FastMath.toDegrees(history.getEquinoxNutationCorrection(t3Sup)[1]), 1.0e-10);
117         Assertions.assertEquals(-0.3115675, history.getUT1MinusUTC(t3Sup),                                                1.0e-10);
118         Assertions.assertEquals( 3.4186e-6, 1000 * history.getLOD(t3Sup),                                                 1.0e-10);
119 
120     }
121 
122     @Test
123     public void testMissingColumnsPadding2000() {
124         setRoot("rapid-data-columns");
125         IERSConventions.NutationCorrectionConverter converter =
126                 IERSConventions.IERS_2003.getNutationCorrectionConverter();
127         SortedSet<EOPEntry> data = new TreeSet<EOPEntry>(new ChronologicalComparator());
128         new RapidDataAndPredictionColumnsLoader(true, "^finals2000A\\.daily$", manager, () -> utc).fillHistory(converter, data);
129         EOPHistory history = new EOPHistory(IERSConventions.IERS_2003, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
130                                             data, true);
131 
132         // after 2011-05-31, the example daily file has no columns for Bulletin B data
133         // we don't see anything since we fall back to bulletin A
134         AbsoluteDate t1Inf = new AbsoluteDate(2011, 6, 1, TimeScalesFactory.getUTC());
135         Assertions.assertEquals(-0.015313,  3600 * FastMath.toDegrees(history.getPoleCorrection(t1Inf).getXp()), 1.0e-10);
136         Assertions.assertEquals( 0.403214,  3600 * FastMath.toDegrees(history.getPoleCorrection(t1Inf).getYp()), 1.0e-10);
137         Assertions.assertEquals(-0.2778790, history.getUT1MinusUTC(t1Inf),                                       1.0e-10);
138         Assertions.assertEquals( 0.5773,    1000 * history.getLOD(t1Inf),                                        1.0e-10);
139         AbsoluteDate t1Sup = t1Inf.shiftedBy(Constants.JULIAN_DAY);
140         Assertions.assertEquals(-0.014222,  3600 * FastMath.toDegrees(history.getPoleCorrection(t1Sup).getXp()), 1.0e-10);
141         Assertions.assertEquals( 0.404430,  3600 * FastMath.toDegrees(history.getPoleCorrection(t1Sup).getYp()), 1.0e-10);
142         Assertions.assertEquals(-0.2784173, history.getUT1MinusUTC(t1Sup),                                       1.0e-10);
143         Assertions.assertEquals( 0.5055,    1000 * history.getLOD(t1Sup),                                        1.0e-10);
144 
145         // after 2011-07-06, the example daily file has no columns for LOD, but it is interpolated
146         AbsoluteDate t2Inf = new AbsoluteDate(2011, 7, 6, TimeScalesFactory.getUTC());
147         Assertions.assertEquals( 0.052605,  3600 * FastMath.toDegrees(history.getPoleCorrection(t2Inf).getXp()), 1.0e-10);
148         Assertions.assertEquals( 0.440076,  3600 * FastMath.toDegrees(history.getPoleCorrection(t2Inf).getYp()), 1.0e-10);
149         Assertions.assertEquals(-0.2915826, history.getUT1MinusUTC(t2Inf),                                       1.0e-10);
150         Assertions.assertEquals( 0.5020,    1000 * history.getLOD(t2Inf),                                        1.0e-10);
151         AbsoluteDate t2Sup = t2Inf.shiftedBy(Constants.JULIAN_DAY);
152         Assertions.assertEquals( 0.055115,  3600 * FastMath.toDegrees(history.getPoleCorrection(t2Sup).getXp()), 1.0e-10);
153         Assertions.assertEquals( 0.440848,  3600 * FastMath.toDegrees(history.getPoleCorrection(t2Sup).getYp()), 1.0e-10);
154         Assertions.assertEquals(-0.2920866, history.getUT1MinusUTC(t2Sup),                                       1.0e-10);
155         Assertions.assertEquals( 5.3509e-6, 1000 * history.getLOD(t2Sup),                                        1.0e-10);
156 
157     }
158 
159     @Test
160     public void testEndDateDaily2000() {
161         setRoot("rapid-data-columns");
162         IERSConventions.NutationCorrectionConverter converter =
163                 IERSConventions.IERS_2003.getNutationCorrectionConverter();
164         SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
165         new RapidDataAndPredictionColumnsLoader(true, "^finals2000A\\.daily$", manager, () -> utc).fillHistory(converter, history);
166         Assertions.assertEquals(new AbsoluteDate(2011, 10, 6, TimeScalesFactory.getUTC()),
167                             new EOPHistory(IERSConventions.IERS_2003, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
168                                            history, true).getEndDate());
169     }
170 
171     @Test
172     public void testNoColumns() {
173         setRoot("rapid-data-columns");
174         IERSConventions.NutationCorrectionConverter converter =
175                         IERSConventions.IERS_2010.getNutationCorrectionConverter();
176         SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
177         new RapidDataAndPredictionColumnsLoader(true, "^finals2000A-no-columns\\.daily$", manager, () -> utc).fillHistory(converter, history);
178         EOPHistory eopH = new EOPHistory(IERSConventions.IERS_2010, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
179                                          history, true);
180         Assertions.assertEquals(new AbsoluteDate(2011, 4, 16, TimeScalesFactory.getUTC()), eopH.getEndDate());
181         AbsoluteDate testDate = eopH.getEndDate().shiftedBy(-2 * Constants.JULIAN_DAY);
182         Assertions.assertEquals(0.0, eopH.getPoleCorrection(testDate).getXp(),                1.0e-15);
183         Assertions.assertEquals(0.0, eopH.getPoleCorrection(testDate).getYp(),                1.0e-15);
184         Assertions.assertEquals(0.0, eopH.getUT1MinusUTC(testDate),                           1.0e-15);
185         Assertions.assertEquals(0.0, eopH.getLOD(testDate),                                   1.0e-15);
186         Assertions.assertEquals(0.0, eopH.getNonRotatinOriginNutationCorrection(testDate)[0], 1.0e-15);
187         Assertions.assertEquals(0.0, eopH.getNonRotatinOriginNutationCorrection(testDate)[1], 1.0e-15);
188     }
189 
190     @Test
191     public void testPost2070() {
192         setRoot("rapid-data-columns");
193         IERSConventions.NutationCorrectionConverter converter =
194                         IERSConventions.IERS_2010.getNutationCorrectionConverter();
195         SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
196         new RapidDataAndPredictionColumnsLoader(true, "^finals2000A-post-2070\\.daily$", manager, () -> utc).fillHistory(converter, history);
197         Assertions.assertEquals(new AbsoluteDate(2075, 4, 16, TimeScalesFactory.getUTC()),
198                             new EOPHistory(IERSConventions.IERS_2010, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
199                                            history, true).getEndDate());
200 
201     }
202 
203     @Test
204     public void testTruncatedLine() {
205         doTestWrongFile("^finals2000A-truncated-line\\.daily$", 3);
206     }
207 
208     @Test
209     public void testWrongDateFormat() {
210         doTestWrongFile("^finals2000A-wrong-date-format\\.daily$", 3);
211     }
212 
213     @Test
214     public void testWrongYear() {
215         doTestWrongFile("^finals2000A-wrong-year\\.daily$", 6);
216     }
217 
218     @Test
219     public void testWrongMonth() {
220         doTestWrongFile("^finals2000A-wrong-month\\.daily$", 5);
221     }
222 
223     @Test
224     public void testWrongDay() {
225         doTestWrongFile("^finals2000A-wrong-day\\.daily$", 4);
226     }
227 
228     @Test
229     public void testWrongPoleAFormat() {
230         doTestWrongFile("^finals2000A-wrong-pole-A-format\\.daily$", 7);
231     }
232 
233     @Test
234     public void testWrongPoleBFormat() {
235         doTestWrongFile("^finals2000A-wrong-pole-B-format\\.daily$", 7);
236     }
237 
238     @Test
239     public void testWrongUT1UTCAFormat() {
240         doTestWrongFile("^finals2000A-wrong-ut1-utc-A-format\\.daily$", 7);
241     }
242 
243     @Test
244     public void testWrongUT1UTCBFormat() {
245         doTestWrongFile("^finals2000A-wrong-ut1-utc-B-format\\.daily$", 7);
246     }
247 
248     @Test
249     public void testWrongLODAFormat() {
250         doTestWrongFile("^finals2000A-wrong-lod-A-format\\.daily$", 7);
251     }
252 
253     @Test
254     public void testWrongNutationAFormat() {
255         doTestWrongFile("^finals2000A-wrong-nutation-A-format\\.daily$", 7);
256     }
257 
258     @Test
259     public void testWrongNutationBFormat() {
260         doTestWrongFile("^finals2000A-wrong-nutation-B-format\\.daily$", 7);
261     }
262 
263     private void doTestWrongFile(String fileName, int lineNumber) {
264         setRoot("rapid-data-columns");
265         IERSConventions.NutationCorrectionConverter converter =
266                         IERSConventions.IERS_2010.getNutationCorrectionConverter();
267         SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
268         try {
269             new RapidDataAndPredictionColumnsLoader(true, fileName, manager, () -> utc).fillHistory(converter, history);
270             Assertions.fail("an exception should have been thrown");
271         } catch (OrekitException oe) {
272             Assertions.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
273             Assertions.assertEquals(lineNumber, ((Integer) oe.getParts()[0]).intValue());
274         }
275     }
276 
277 }