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.junit.jupiter.api.Assertions;
20  import org.junit.jupiter.api.Test;
21  import org.orekit.data.AbstractFilesLoaderTest;
22  import org.orekit.errors.OrekitException;
23  import org.orekit.errors.OrekitMessages;
24  import org.orekit.time.AbsoluteDate;
25  import org.orekit.time.ChronologicalComparator;
26  import org.orekit.time.DateComponents;
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 BulletinAFilesLoaderTest extends AbstractFilesLoaderTest {
36  
37      @Test
38      public void testStartDate() {
39          setRoot("bulletinA");
40          SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
41          new BulletinAFilesLoader("bulletina-xxvi-\\d\\d\\d\\.txt", manager, () -> utc).fillHistory(null, history);
42          Assertions.assertEquals(new AbsoluteDate(new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, 56475),
43                                               TimeScalesFactory.getUTC()),
44                              new EOPHistory(IERSConventions.IERS_2010, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
45                                             history, true).getStartDate());
46      }
47  
48      @Test
49      public void testEndDate() {
50          setRoot("bulletinA");
51          SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
52          new BulletinAFilesLoader("bulletina-xxvi-\\d\\d\\d\\.txt", manager, () -> utc).fillHistory(null, history);
53          Assertions.assertTrue(getMaxGap(history) < 2);
54          Assertions.assertEquals(new AbsoluteDate(new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, 56968),
55                                               TimeScalesFactory.getUTC()),
56                              new EOPHistory(IERSConventions.IERS_2010, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
57                                             history, false).getEndDate());
58      }
59  
60      @Test
61      public void testSingleFile() {
62          setRoot("bulletinA");
63          SortedSet<EOPEntry> data = new TreeSet<EOPEntry>(new ChronologicalComparator());
64          new BulletinAFilesLoader("bulletina-xxvi-039.txt", manager, () -> utc).fillHistory(null, data);
65          EOPHistory history = new EOPHistory(IERSConventions.IERS_2010, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
66                                              data, true);
67  
68          // earliest date is for pole position, provided days 56546, 56547, 56548
69          Assertions.assertEquals(new AbsoluteDate(new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, 56546),
70                                               TimeScalesFactory.getUTC()),
71                              history.getStartDate());
72  
73          // with this single file, there is a hole between last pole (56548) and first rapid data (56555)
74          Assertions.assertEquals(56555 - 56548, getMaxGap(data));
75  
76          // latest date is for EOP prediction, corresponding to 56926
77          Assertions.assertEquals(new AbsoluteDate(new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, 56926),
78                                               TimeScalesFactory.getUTC()),
79                              history.getEndDate());
80      }
81  
82      @Test
83      public void testPredictedValuesContent() {
84          setRoot("bulletinA");
85          SortedSet<EOPEntry> data = new TreeSet<>(new ChronologicalComparator());
86          new BulletinAFilesLoader(FramesFactory.BULLETINA_FILENAME, manager, () -> utc).fillHistory(null, data);
87          EOPHistory history = new EOPHistory(IERSConventions.IERS_2010, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
88                                              data, true);
89          AbsoluteDate date = new AbsoluteDate(2013, 12, 1, 12, 0, 0, TimeScalesFactory.getUTC());
90          // the following values are from bulletina-xxvi-045.txt, predicted values section, lines 108-472
91          Assertions.assertEquals(EopDataType.PREDICTED, history.getEopDataType(date));
92      }
93  
94      @Test
95      public void testRapidDataContent() {
96          setRoot("bulletinA");
97          SortedSet<EOPEntry> data = new TreeSet<EOPEntry>(new ChronologicalComparator());
98          new BulletinAFilesLoader(FramesFactory.BULLETINA_FILENAME, manager, () -> utc).fillHistory(null, data);
99          EOPHistory history = new EOPHistory(IERSConventions.IERS_2010, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
100                                             data, true);
101         AbsoluteDate date = new AbsoluteDate(2013, 10, 14, 12, 0, 0, TimeScalesFactory.getUTC());
102         // the following values are from bulletina-xxvi-042.txt, rapid service section, lines 53-56
103         Assertions.assertEquals(        (-3 * -0.001957 + 27 * -0.003274 + 27 * -0.004706 - 3 * -0.006211) / 48,  history.getUT1MinusUTC(date), 1.0e-10);
104         Assertions.assertEquals(asToRad((-3 *  0.11518  + 27 *  0.11389  + 27 *  0.11285  - 3 *  0.11171)  / 48), history.getPoleCorrection(date).getXp(), 1.0e-10);
105         Assertions.assertEquals(asToRad((-3 *  0.28484  + 27 *  0.28449  + 27 *  0.28408  - 3 *  0.28379)  / 48), history.getPoleCorrection(date).getYp(), 1.0e-10);
106         Assertions.assertEquals(EopDataType.RAPID, history.getEopDataType(date));
107     }
108 
109     @Test
110     public void testFinalValuesContent() {
111         setRoot("bulletinA");
112         SortedSet<EOPEntry> data = new TreeSet<EOPEntry>(new ChronologicalComparator());
113         new BulletinAFilesLoader(FramesFactory.BULLETINA_FILENAME, manager, () -> utc).fillHistory(null, data);
114         EOPHistory history = new EOPHistory(IERSConventions.IERS_2010, EOPHistory.DEFAULT_INTERPOLATION_DEGREE,
115                 data, true);
116         AbsoluteDate date = new AbsoluteDate(2013, 8, 26, 12, 0, 0, TimeScalesFactory.getUTC());
117         // the following values are from bulletina-xxvi-040.txt, final values section, lines 79-82
118         Assertions.assertEquals(        (-3 * 0.04058 + 27 * 0.04000 + 27 * 0.03953 - 3 * 0.03917) / 48,  history.getUT1MinusUTC(date), 1.0e-10);
119         Assertions.assertEquals(asToRad((-3 * 0.1692  + 27 * 0.1689  + 27 * 0.1685  - 3 * 0.1684)  / 48), history.getPoleCorrection(date).getXp(), 1.0e-10);
120         Assertions.assertEquals(asToRad((-3 * 0.3336  + 27 * 0.3322  + 27 * 0.3307  - 3 * 0.3294)  / 48), history.getPoleCorrection(date).getYp(), 1.0e-10);
121         double[] nroNutationCorrection = history.getNonRotatinOriginNutationCorrection(date);
122         double[] equinoxNutationCorrection = history.getEquinoxNutationCorrection(date);
123         Assertions.assertEquals(asToRad((-3 * -0.24  + 27 * -0.20  + 27 * -0.24  - 3 * -0.21) / 1000 / 48), nroNutationCorrection[0], 1.0e-10);
124         Assertions.assertEquals(asToRad((-3 * -0.13  + 27 * -0.09  + 27 * -0.12  - 3 * -0.18) / 1000 / 48), nroNutationCorrection[1], 1.0e-10);
125         Assertions.assertEquals(asToRad((-3 * -88.7  + 27 * -88.9  + 27 * -89.0  - 3 * -88.8) / 1000 / 48), equinoxNutationCorrection[0], 1.0e-10);
126         Assertions.assertEquals(asToRad((-3 * -13.1  + 27 * -13.0  + 27 * -13.0  - 3 * -13.1) / 1000 / 48), equinoxNutationCorrection[1], 1.0e-10);
127         Assertions.assertEquals(EopDataType.FINAL, history.getEopDataType(date));
128     }
129 
130     private double asToRad(double mas) {
131         return mas * Constants.ARC_SECONDS_TO_RADIANS;
132     }
133 
134     @Test
135     public void testMissingSections() {
136         setRoot("bulletinA");
137         checkTruncated("bulletina-missing-eop-rapid-service.txt",    OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE);
138         checkTruncated("bulletina-missing-eop-prediction.txt",       OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE);
139         checkTruncated("bulletina-with-1980-without-2000-rapid.txt", OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE);
140         checkTruncated("bulletina-without-1980-with-2000-rapid.txt", OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE);
141         checkTruncated("bulletina-with-1980-without-2000-final.txt", OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE);
142         checkTruncated("bulletina-without-1980-with-2000-final.txt", OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE);
143     }
144 
145     @Test
146     public void testMissingData() {
147         setRoot("bulletinA");
148         checkTruncated("bulletina-truncated-in-eop-data.txt",  OrekitMessages.UNEXPECTED_END_OF_FILE_AFTER_LINE);
149         checkTruncated("bulletina-truncated-in-pole-data.txt", OrekitMessages.UNEXPECTED_END_OF_FILE_AFTER_LINE);
150     }
151 
152     private void checkTruncated(String name, OrekitMessages expected) {
153         SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
154         try {
155             new BulletinAFilesLoader(name, manager, () -> utc).fillHistory(null, history);
156             Assertions.fail("an exception should have been thrown");
157         } catch (OrekitException oe) {
158             Assertions.assertEquals(expected, oe.getSpecifier());
159             Assertions.assertTrue(((String) oe.getParts()[0]).endsWith(name));
160         }
161     }
162 
163     @Test
164     public void testInconsistentDate() {
165         setRoot("bulletinA");
166         checkInconsistent("bulletina-inconsistent-year.txt");
167         checkInconsistent("bulletina-inconsistent-month.txt");
168         checkInconsistent("bulletina-inconsistent-day.txt");
169     }
170 
171     private void checkInconsistent(String name) {
172         SortedSet<EOPEntry> history = new TreeSet<EOPEntry>(new ChronologicalComparator());
173         try {
174             new BulletinAFilesLoader(name, manager, () -> utc).fillHistory(null, history);
175             Assertions.fail("an exception should have been thrown");
176         } catch (OrekitException oe) {
177             Assertions.assertEquals(OrekitMessages.INCONSISTENT_DATES_IN_IERS_FILE, oe.getSpecifier());
178             Assertions.assertTrue(((String) oe.getParts()[0]).endsWith(name));
179         }
180     }
181 
182 }