1 /* Contributed in the public domain.
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 java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.SortedSet;
24 import java.util.TreeSet;
25 import java.util.function.Supplier;
26
27 import org.orekit.data.DataProvidersManager;
28 import org.orekit.errors.OrekitException;
29 import org.orekit.time.ChronologicalComparator;
30 import org.orekit.time.TimeScale;
31 import org.orekit.time.TimeScales;
32 import org.orekit.utils.Constants;
33 import org.orekit.utils.IERSConventions;
34
35 /**
36 * Loads Earth Orientation Parameters (EOP) from a configured set of {@link
37 * EopHistoryLoader}s on demand. Methods are synchronized so it is safe for access from
38 * multiple threads.
39 *
40 * @author Guylaine Prat
41 * @author Luc Maisonobe
42 * @author Pascal Parraud
43 * @author Evan Ward
44 * @see LazyLoadedFrames
45 * @see FramesFactory
46 * @since 10.1
47 */
48 public class LazyLoadedEop {
49
50 /** Provides access to the EOP data files. */
51 private final DataProvidersManager dataProvidersManager;
52 /** Loaders for Earth Orientation parameters. */
53 private final Map<IERSConventions, List<EopHistoryLoader>> eopHistoryLoaders;
54 /** Threshold for EOP continuity. */
55 private double eopContinuityThreshold;
56 /** Degree for EOP interpolation.
57 * @since 12.0
58 */
59 private int interpolationDegree;
60
61 /**
62 * Create a new instance for loading EOP data from multiple {@link
63 * EopHistoryLoader}s.
64 *
65 * @param dataProvidersManager provides access to the needed EOP data files.
66 */
67 public LazyLoadedEop(final DataProvidersManager dataProvidersManager) {
68 this.dataProvidersManager = dataProvidersManager;
69 this.eopHistoryLoaders = new HashMap<>();
70 this.eopContinuityThreshold = 5 * Constants.JULIAN_DAY;
71 this.interpolationDegree = EOPHistory.DEFAULT_INTERPOLATION_DEGREE;
72 }
73
74 /**
75 * Get the data providers manager for this instance.
76 *
77 * @return the provider of EOP data files.
78 */
79 public DataProvidersManager getDataProvidersManager() {
80 return dataProvidersManager;
81 }
82
83 /**
84 * Add the default loaders EOP history (IAU 1980 precession/nutation).
85 * <p>
86 * The default loaders look for IERS EOP C04 and bulletins B files. They correspond to
87 * {@link IERSConventions#IERS_1996 IERS 1996} conventions.
88 * </p>
89 *
90 * @param rapidDataColumnsSupportedNames regular expression for supported rapid data
91 * columns EOP files names (may be null if the
92 * default IERS file names are used)
93 * @param xmlSupportedNames regular expression for supported XML EOP
94 * files names (may be null if the
95 * default IERS file names are used)
96 * @param eopC04SupportedNames regular expression for supported EOP C04
97 * files names (may be null if the default IERS
98 * file names are used)
99 * @param bulletinBSupportedNames regular expression for supported bulletin B
100 * files names (may be null if the default IERS
101 * file names are used)
102 * @param bulletinASupportedNames regular expression for supported bulletin A
103 * files names (may be null if the default IERS
104 * file names are used)
105 * @param csvSupportedNames regular expression for supported csv files names
106 * (may be null if the default IERS file names are used)
107 * @param utcSupplier UTC time scale supplier. Value is not
108 * accessed until attempting to load EOP.
109 * @see <a href="https://datacenter.iers.org/products/eop/">IERS https data download</a>
110 * @see #addEOPHistoryLoader(IERSConventions, EopHistoryLoader)
111 * @see #clearEOPHistoryLoaders()
112 * @see #addDefaultEOP2000HistoryLoaders(String, String, String, String, String, String, Supplier)
113 * @since 12.0
114 */
115 public void addDefaultEOP1980HistoryLoaders(final String rapidDataColumnsSupportedNames,
116 final String xmlSupportedNames,
117 final String eopC04SupportedNames,
118 final String bulletinBSupportedNames,
119 final String bulletinASupportedNames,
120 final String csvSupportedNames,
121 final Supplier<TimeScale> utcSupplier) {
122 final String rapidColNames =
123 (rapidDataColumnsSupportedNames == null) ?
124 FramesFactory.RAPID_DATA_PREDICTION_COLUMNS_1980_FILENAME :
125 rapidDataColumnsSupportedNames;
126 addEOPHistoryLoader(IERSConventions.IERS_1996,
127 new RapidDataAndPredictionColumnsLoader(false, rapidColNames,
128 dataProvidersManager, utcSupplier));
129 final String xmlNames = (xmlSupportedNames == null) ?
130 FramesFactory.XML_1980_FILENAME :
131 xmlSupportedNames;
132 addEOPHistoryLoader(IERSConventions.IERS_1996,
133 new EopXmlLoader(xmlNames, dataProvidersManager, utcSupplier));
134 final String eopcNames =
135 (eopC04SupportedNames == null) ?
136 FramesFactory.EOPC04_1980_FILENAME : eopC04SupportedNames;
137 addEOPHistoryLoader(IERSConventions.IERS_1996,
138 new EopC04FilesLoader(eopcNames, dataProvidersManager, utcSupplier));
139 final String bulBNames =
140 (bulletinBSupportedNames == null) ?
141 FramesFactory.BULLETINB_1980_FILENAME : bulletinBSupportedNames;
142 addEOPHistoryLoader(IERSConventions.IERS_1996,
143 new BulletinBFilesLoader(bulBNames, dataProvidersManager, utcSupplier));
144 final String bulANames =
145 (bulletinASupportedNames == null) ?
146 FramesFactory.BULLETINA_FILENAME : bulletinASupportedNames;
147 addEOPHistoryLoader(IERSConventions.IERS_1996,
148 new BulletinAFilesLoader(bulANames, dataProvidersManager, utcSupplier));
149 final String csvNames = (csvSupportedNames == null) ?
150 FramesFactory.CSV_FILENAME : csvSupportedNames;
151 addEOPHistoryLoader(IERSConventions.IERS_1996,
152 new EopCsvFilesLoader(csvNames, dataProvidersManager, utcSupplier));
153 }
154
155 /**
156 * Add the default loaders for EOP history (IAU 2000/2006 precession/nutation).
157 * <p>
158 * The default loaders look for IERS EOP C04 and bulletins B files. They correspond to
159 * both {@link IERSConventions#IERS_2003 IERS 2003} and {@link
160 * IERSConventions#IERS_2010 IERS 2010} conventions.
161 * </p>
162 *
163 * @param rapidDataColumnsSupportedNames regular expression for supported rapid data
164 * columns EOP files names (may be null if the
165 * default IERS file names are used)
166 * @param xmlSupportedNames regular expression for supported XML EOP
167 * files names (may be null if the
168 * default IERS file names are used)
169 * @param eopC04SupportedNames regular expression for supported EOP C04
170 * files names (may be null if the default IERS
171 * file names are used)
172 * @param bulletinBSupportedNames regular expression for supported bulletin B
173 * files names (may be null if the default IERS
174 * file names are used)
175 * @param bulletinASupportedNames regular expression for supported bulletin A
176 * files names (may be null if the default IERS
177 * file names are used)
178 * @param csvSupportedNames regular expression for supported csv files names
179 * (may be null if the default IERS file names are used)
180 * @param utcSupplier UTC time scale supplier. Value is not
181 * accessed until attempting to load EOP.
182 * @see <a href="https://datacenter.iers.org/products/eop/">IERS https data download</a>
183 * @see #addEOPHistoryLoader(IERSConventions, EopHistoryLoader)
184 * @see #clearEOPHistoryLoaders()
185 * @see #addDefaultEOP1980HistoryLoaders(String, String, String, String, String, String, Supplier)
186 * @since 12.0
187 */
188 public void addDefaultEOP2000HistoryLoaders(final String rapidDataColumnsSupportedNames,
189 final String xmlSupportedNames,
190 final String eopC04SupportedNames,
191 final String bulletinBSupportedNames,
192 final String bulletinASupportedNames,
193 final String csvSupportedNames,
194 final Supplier<TimeScale> utcSupplier) {
195 final String rapidColNames =
196 (rapidDataColumnsSupportedNames == null) ?
197 FramesFactory.RAPID_DATA_PREDICTION_COLUMNS_2000_FILENAME :
198 rapidDataColumnsSupportedNames;
199 addEOPHistoryLoader(IERSConventions.IERS_2003,
200 new RapidDataAndPredictionColumnsLoader(true, rapidColNames, dataProvidersManager, utcSupplier));
201 addEOPHistoryLoader(IERSConventions.IERS_2010,
202 new RapidDataAndPredictionColumnsLoader(true, rapidColNames, dataProvidersManager, utcSupplier));
203 final String xmlNames = (xmlSupportedNames == null) ?
204 FramesFactory.XML_2000_FILENAME :
205 xmlSupportedNames;
206 addEOPHistoryLoader(IERSConventions.IERS_2003,
207 new EopXmlLoader(xmlNames, dataProvidersManager, utcSupplier));
208 addEOPHistoryLoader(IERSConventions.IERS_2010,
209 new EopXmlLoader(xmlNames, dataProvidersManager, utcSupplier));
210 final String eopcNames = (eopC04SupportedNames == null) ?
211 FramesFactory.EOPC04_2000_FILENAME : eopC04SupportedNames;
212 addEOPHistoryLoader(IERSConventions.IERS_2003,
213 new EopC04FilesLoader(eopcNames, dataProvidersManager, utcSupplier));
214 addEOPHistoryLoader(IERSConventions.IERS_2010,
215 new EopC04FilesLoader(eopcNames, dataProvidersManager, utcSupplier));
216 final String bulBNames = (bulletinBSupportedNames == null) ?
217 FramesFactory.BULLETINB_2000_FILENAME : bulletinBSupportedNames;
218 addEOPHistoryLoader(IERSConventions.IERS_2003,
219 new BulletinBFilesLoader(bulBNames, dataProvidersManager, utcSupplier));
220 addEOPHistoryLoader(IERSConventions.IERS_2010,
221 new BulletinBFilesLoader(bulBNames, dataProvidersManager, utcSupplier));
222 final String bulANames = (bulletinASupportedNames == null) ?
223 FramesFactory.BULLETINA_FILENAME : bulletinASupportedNames;
224 addEOPHistoryLoader(IERSConventions.IERS_2003,
225 new BulletinAFilesLoader(bulANames, dataProvidersManager, utcSupplier));
226 addEOPHistoryLoader(IERSConventions.IERS_2010,
227 new BulletinAFilesLoader(bulANames, dataProvidersManager, utcSupplier));
228 final String csvNames = (csvSupportedNames == null) ?
229 FramesFactory.CSV_FILENAME : csvSupportedNames;
230 addEOPHistoryLoader(IERSConventions.IERS_2003,
231 new EopCsvFilesLoader(csvNames, dataProvidersManager, utcSupplier));
232 addEOPHistoryLoader(IERSConventions.IERS_2010,
233 new EopCsvFilesLoader(csvNames, dataProvidersManager, utcSupplier));
234 }
235
236 /**
237 * Add a loader for Earth Orientation Parameters history.
238 *
239 * @param conventions IERS conventions to which EOP history applies
240 * @param loader custom loader to add for the EOP history
241 * @see #addDefaultEOP1980HistoryLoaders(String, String, String, String, String, String, Supplier)
242 * @see #clearEOPHistoryLoaders()
243 */
244 public void addEOPHistoryLoader(final IERSConventions conventions, final EopHistoryLoader loader) {
245 synchronized (eopHistoryLoaders) {
246 if (!eopHistoryLoaders.containsKey(conventions)) {
247 eopHistoryLoaders.put(conventions, new ArrayList<>());
248 }
249 eopHistoryLoaders.get(conventions).add(loader);
250 }
251 }
252
253 /**
254 * Clear loaders for Earth Orientation Parameters history.
255 *
256 * @see #addEOPHistoryLoader(IERSConventions, EopHistoryLoader)
257 * @see #addDefaultEOP1980HistoryLoaders(String, String, String, String, String, String, Supplier)
258 */
259 public void clearEOPHistoryLoaders() {
260 synchronized (eopHistoryLoaders) {
261 eopHistoryLoaders.clear();
262 }
263 }
264
265 /**
266 * Set the threshold to check EOP continuity.
267 * <p>
268 * The default threshold (used if this method is never called) is 5 Julian days. If
269 * after loading EOP entries some holes between entries exceed this threshold, an
270 * exception will be triggered.
271 * </p>
272 * <p>
273 * One case when calling this method is really useful is for applications that use a
274 * single Bulletin A, as these bulletins have a roughly one month wide hole for the
275 * first bulletin of each month, which contains older final data in addition to the
276 * rapid data and the predicted data.
277 * </p>
278 *
279 * @param threshold threshold to use for checking EOP continuity (in seconds)
280 */
281 public void setEOPContinuityThreshold(final double threshold) {
282 eopContinuityThreshold = threshold;
283 }
284
285 /**
286 * Set the degree for interpolation degree.
287 * <p>
288 * The default threshold (used if this method is never called) is {@link EOPHistory#DEFAULT_INTERPOLATION_DEGREE}.
289 * </p>
290 *
291 * @param interpolationDegree interpolation degree, must be of the form 4k-1
292 * @since 12.0
293 */
294 public void setInterpolationDegree(final int interpolationDegree) {
295 this.interpolationDegree = interpolationDegree;
296 }
297
298 /**
299 * Get Earth Orientation Parameters history.
300 * <p>
301 * If no {@link EopHistoryLoader} has been added by calling {@link
302 * #addEOPHistoryLoader(IERSConventions, EopHistoryLoader) addEOPHistoryLoader} or if
303 * {@link #clearEOPHistoryLoaders() clearEOPHistoryLoaders} has been called
304 * afterwards, the {@link #addDefaultEOP1980HistoryLoaders(String, String, String,
305 * String, String, String, Supplier)} and {@link #addDefaultEOP2000HistoryLoaders(String,
306 * String, String, String, String, String, Supplier)} methods will be called automatically
307 * with supported file names parameters all set to null, in order to get the default
308 * loaders configuration.
309 * </p>
310 *
311 * @param conventions conventions for which EOP history is requested
312 * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
313 * @param timeScales to use when loading EOP and computing corrections.
314 * @return Earth Orientation Parameters history
315 */
316 public EOPHistory getEOPHistory(final IERSConventions conventions,
317 final boolean simpleEOP,
318 final TimeScales timeScales) {
319
320 synchronized (eopHistoryLoaders) {
321
322 if (eopHistoryLoaders.isEmpty()) {
323 // set up using default loaders
324 final Supplier<TimeScale> utcSupplier = timeScales::getUTC;
325 addDefaultEOP2000HistoryLoaders(null, null, null, null, null, null, utcSupplier);
326 addDefaultEOP1980HistoryLoaders(null, null, null, null, null, null, utcSupplier);
327 }
328
329 // TimeStamped based set needed to remove duplicates
330 OrekitException pendingException = null;
331 final SortedSet<EOPEntry> data = new TreeSet<>(new ChronologicalComparator());
332
333 // try to load canonical data if available
334 if (eopHistoryLoaders.containsKey(conventions)) {
335 for (final EopHistoryLoader loader : eopHistoryLoaders.get(conventions)) {
336 try {
337 loader.fillHistory(conventions.getNutationCorrectionConverter(timeScales),
338 data);
339 } catch (OrekitException oe) {
340 pendingException = oe;
341 }
342 }
343 }
344
345 if (data.isEmpty() && pendingException != null) {
346 throw pendingException;
347 }
348
349 final EOPHistory history = new EOPHistory(conventions, interpolationDegree, data, simpleEOP, timeScales);
350 history.checkEOPContinuity(eopContinuityThreshold);
351 return history;
352
353 }
354
355 }
356
357 }