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
57 /**
58 * Create a new instance for loading EOP data from multiple {@link
59 * EOPHistoryLoader}s.
60 *
61 * @param dataProvidersManager provides access to the needed EOP data files.
62 */
63 public LazyLoadedEop(final DataProvidersManager dataProvidersManager) {
64 this.dataProvidersManager = dataProvidersManager;
65 this.eopHistoryLoaders = new HashMap<>();
66 this.eopContinuityThreshold = 5 * Constants.JULIAN_DAY;
67 }
68
69 /**
70 * Get the data providers manager for this instance.
71 *
72 * @return the provider of EOP data files.
73 */
74 public DataProvidersManager getDataProvidersManager() {
75 return dataProvidersManager;
76 }
77
78 /**
79 * Add the default loaders EOP history (IAU 1980 precession/nutation).
80 * <p>
81 * The default loaders look for IERS EOP C04 and bulletins B files. They correspond to
82 * {@link IERSConventions#IERS_1996 IERS 1996} conventions.
83 * </p>
84 *
85 * @param rapidDataColumnsSupportedNames regular expression for supported rapid data
86 * columns EOP files names (may be null if the
87 * default IERS file names are used)
88 * @param rapidDataXMLSupportedNames regular expression for supported rapid data
89 * XML EOP files names (may be null if the
90 * default IERS file names are used)
91 * @param eopC04SupportedNames regular expression for supported EOP C04
92 * files names (may be null if the default IERS
93 * file names are used)
94 * @param bulletinBSupportedNames regular expression for supported bulletin B
95 * files names (may be null if the default IERS
96 * file names are used)
97 * @param bulletinASupportedNames regular expression for supported bulletin A
98 * files names (may be null if the default IERS
99 * file names are used)
100 * @param utcSupplier UTC time scale supplier. Value is not
101 * accessed until attempting to load EOP.
102 * @see <a href="http://hpiers.obspm.fr/eoppc/eop/eopc04/">IERS EOP C04 files</a>
103 * @see #addEOPHistoryLoader(IERSConventions, EOPHistoryLoader)
104 * @see #clearEOPHistoryLoaders()
105 * @see #addDefaultEOP2000HistoryLoaders(String, String, String, String, String, Supplier)
106 */
107 public void addDefaultEOP1980HistoryLoaders(final String rapidDataColumnsSupportedNames,
108 final String rapidDataXMLSupportedNames,
109 final String eopC04SupportedNames,
110 final String bulletinBSupportedNames,
111 final String bulletinASupportedNames,
112 final Supplier<TimeScale> utcSupplier) {
113 final String rapidColNames =
114 (rapidDataColumnsSupportedNames == null) ?
115 FramesFactory.RAPID_DATA_PREDICTION_COLUMNS_1980_FILENAME :
116 rapidDataColumnsSupportedNames;
117 addEOPHistoryLoader(IERSConventions.IERS_1996,
118 new RapidDataAndPredictionColumnsLoader(false, rapidColNames,
119 dataProvidersManager, utcSupplier));
120 final String rapidXmlNames =
121 (rapidDataXMLSupportedNames == null) ?
122 FramesFactory.RAPID_DATA_PREDICTION_XML_1980_FILENAME :
123 rapidDataXMLSupportedNames;
124 addEOPHistoryLoader(IERSConventions.IERS_1996,
125 new RapidDataAndPredictionXMLLoader(rapidXmlNames, dataProvidersManager,
126 utcSupplier));
127 final String eopcNames =
128 (eopC04SupportedNames == null) ?
129 FramesFactory.EOPC04_1980_FILENAME : eopC04SupportedNames;
130 addEOPHistoryLoader(IERSConventions.IERS_1996,
131 new EOPC04FilesLoader(eopcNames, dataProvidersManager, utcSupplier));
132 final String bulBNames =
133 (bulletinBSupportedNames == null) ?
134 FramesFactory.BULLETINB_1980_FILENAME : bulletinBSupportedNames;
135 addEOPHistoryLoader(IERSConventions.IERS_1996,
136 new BulletinBFilesLoader(bulBNames, dataProvidersManager, utcSupplier));
137 final String bulANames =
138 (bulletinASupportedNames == null) ?
139 FramesFactory.BULLETINA_FILENAME : bulletinASupportedNames;
140 addEOPHistoryLoader(IERSConventions.IERS_1996,
141 new BulletinAFilesLoader(bulANames, dataProvidersManager, utcSupplier));
142 }
143
144 /**
145 * Add the default loaders for EOP history (IAU 2000/2006 precession/nutation).
146 * <p>
147 * The default loaders look for IERS EOP C04 and bulletins B files. They correspond to
148 * both {@link IERSConventions#IERS_2003 IERS 2003} and {@link
149 * IERSConventions#IERS_2010 IERS 2010} conventions.
150 * </p>
151 *
152 * @param rapidDataColumnsSupportedNames regular expression for supported rapid data
153 * columns EOP files names (may be null if the
154 * default IERS file names are used)
155 * @param rapidDataXMLSupportedNames regular expression for supported rapid data
156 * XML EOP files names (may be null if the
157 * default IERS file names are used)
158 * @param eopC04SupportedNames regular expression for supported EOP C04
159 * files names (may be null if the default IERS
160 * file names are used)
161 * @param bulletinBSupportedNames regular expression for supported bulletin B
162 * files names (may be null if the default IERS
163 * file names are used)
164 * @param bulletinASupportedNames regular expression for supported bulletin A
165 * files names (may be null if the default IERS
166 * file names are used)
167 * @param utcSupplier UTC time scale supplier. Value is not
168 * accessed until attempting to load EOP.
169 * @see <a href="http://hpiers.obspm.fr/eoppc/eop/eopc04/">IERS EOP C04 files</a>
170 * @see #addEOPHistoryLoader(IERSConventions, EOPHistoryLoader)
171 * @see #clearEOPHistoryLoaders()
172 * @see #addDefaultEOP1980HistoryLoaders(String, String, String, String, String, Supplier)
173 */
174 public void addDefaultEOP2000HistoryLoaders(final String rapidDataColumnsSupportedNames,
175 final String rapidDataXMLSupportedNames,
176 final String eopC04SupportedNames,
177 final String bulletinBSupportedNames,
178 final String bulletinASupportedNames,
179 final Supplier<TimeScale> utcSupplier) {
180 final String rapidColNames =
181 (rapidDataColumnsSupportedNames == null) ?
182 FramesFactory.RAPID_DATA_PREDICITON_COLUMNS_2000_FILENAME :
183 rapidDataColumnsSupportedNames;
184 addEOPHistoryLoader(IERSConventions.IERS_2003,
185 new RapidDataAndPredictionColumnsLoader(
186 true, rapidColNames, dataProvidersManager, utcSupplier));
187 addEOPHistoryLoader(IERSConventions.IERS_2010,
188 new RapidDataAndPredictionColumnsLoader(
189 true, rapidColNames, dataProvidersManager, utcSupplier));
190 final String rapidXmlNames =
191 (rapidDataXMLSupportedNames == null) ?
192 FramesFactory.RAPID_DATA_PREDICITON_XML_2000_FILENAME :
193 rapidDataXMLSupportedNames;
194 addEOPHistoryLoader(IERSConventions.IERS_2003,
195 new RapidDataAndPredictionXMLLoader(
196 rapidXmlNames, dataProvidersManager, utcSupplier));
197 addEOPHistoryLoader(IERSConventions.IERS_2010,
198 new RapidDataAndPredictionXMLLoader(
199 rapidXmlNames, dataProvidersManager, utcSupplier));
200 final String eopcNames =
201 (eopC04SupportedNames == null) ?
202 FramesFactory.EOPC04_2000_FILENAME : eopC04SupportedNames;
203 addEOPHistoryLoader(IERSConventions.IERS_2003,
204 new EOPC04FilesLoader(eopcNames, dataProvidersManager, utcSupplier));
205 addEOPHistoryLoader(IERSConventions.IERS_2010,
206 new EOPC04FilesLoader(eopcNames, dataProvidersManager, utcSupplier));
207 final String bulBNames =
208 (bulletinBSupportedNames == null) ?
209 FramesFactory.BULLETINB_2000_FILENAME : bulletinBSupportedNames;
210 addEOPHistoryLoader(IERSConventions.IERS_2003,
211 new BulletinBFilesLoader(bulBNames, dataProvidersManager, utcSupplier));
212 addEOPHistoryLoader(IERSConventions.IERS_2010,
213 new BulletinBFilesLoader(bulBNames, dataProvidersManager, utcSupplier));
214 final String bulANames =
215 (bulletinASupportedNames == null) ?
216 FramesFactory.BULLETINA_FILENAME : bulletinASupportedNames;
217 addEOPHistoryLoader(IERSConventions.IERS_2003,
218 new BulletinAFilesLoader(bulANames, dataProvidersManager, utcSupplier));
219 addEOPHistoryLoader(IERSConventions.IERS_2010,
220 new BulletinAFilesLoader(bulANames, dataProvidersManager, utcSupplier));
221 }
222
223 /**
224 * Add a loader for Earth Orientation Parameters history.
225 *
226 * @param conventions IERS conventions to which EOP history applies
227 * @param loader custom loader to add for the EOP history
228 * @see #addDefaultEOP1980HistoryLoaders(String, String, String, String, String, Supplier)
229 * @see #clearEOPHistoryLoaders()
230 */
231 public void addEOPHistoryLoader(final IERSConventions conventions, final EOPHistoryLoader loader) {
232 synchronized (eopHistoryLoaders) {
233 if (!eopHistoryLoaders.containsKey(conventions)) {
234 eopHistoryLoaders.put(conventions, new ArrayList<>());
235 }
236 eopHistoryLoaders.get(conventions).add(loader);
237 }
238 }
239
240 /**
241 * Clear loaders for Earth Orientation Parameters history.
242 *
243 * @see #addEOPHistoryLoader(IERSConventions, EOPHistoryLoader)
244 * @see #addDefaultEOP1980HistoryLoaders(String, String, String, String, String, Supplier)
245 */
246 public void clearEOPHistoryLoaders() {
247 synchronized (eopHistoryLoaders) {
248 eopHistoryLoaders.clear();
249 }
250 }
251
252 /**
253 * Set the threshold to check EOP continuity.
254 * <p>
255 * The default threshold (used if this method is never called) is 5 Julian days. If
256 * after loading EOP entries some holes between entries exceed this threshold, an
257 * exception will be triggered.
258 * </p>
259 * <p>
260 * One case when calling this method is really useful is for applications that use a
261 * single Bulletin A, as these bulletins have a roughly one month wide hole for the
262 * first bulletin of each month, which contains older final data in addition to the
263 * rapid data and the predicted data.
264 * </p>
265 *
266 * @param threshold threshold to use for checking EOP continuity (in seconds)
267 */
268 public void setEOPContinuityThreshold(final double threshold) {
269 eopContinuityThreshold = threshold;
270 }
271
272 /**
273 * Get Earth Orientation Parameters history.
274 * <p>
275 * If no {@link EOPHistoryLoader} has been added by calling {@link
276 * #addEOPHistoryLoader(IERSConventions, EOPHistoryLoader) addEOPHistoryLoader} or if
277 * {@link #clearEOPHistoryLoaders() clearEOPHistoryLoaders} has been called
278 * afterwards, the {@link #addDefaultEOP1980HistoryLoaders(String, String, String,
279 * String, String, Supplier)} and {@link #addDefaultEOP2000HistoryLoaders(String,
280 * String, String, String, String, Supplier)} methods will be called automatically
281 * with supported file names parameters all set to null, in order to get the default
282 * loaders configuration.
283 * </p>
284 *
285 * @param conventions conventions for which EOP history is requested
286 * @param simpleEOP if true, tidal effects are ignored when interpolating EOP
287 * @param timeScales to use when loading EOP and computing corrections.
288 * @return Earth Orientation Parameters history
289 */
290 public EOPHistory getEOPHistory(final IERSConventions conventions,
291 final boolean simpleEOP,
292 final TimeScales timeScales) {
293
294 synchronized (eopHistoryLoaders) {
295
296 if (eopHistoryLoaders.isEmpty()) {
297 // set up using default loaders
298 final Supplier<TimeScale> utcSupplier = timeScales::getUTC;
299 addDefaultEOP2000HistoryLoaders(null, null, null, null, null, utcSupplier);
300 addDefaultEOP1980HistoryLoaders(null, null, null, null, null, utcSupplier);
301 }
302
303 // TimeStamped based set needed to remove duplicates
304 OrekitException pendingException = null;
305 final SortedSet<EOPEntry> data = new TreeSet<>(new ChronologicalComparator());
306
307 // try to load canonical data if available
308 if (eopHistoryLoaders.containsKey(conventions)) {
309 for (final EOPHistoryLoader loader : eopHistoryLoaders.get(conventions)) {
310 try {
311 loader.fillHistory(
312 conventions.getNutationCorrectionConverter(timeScales),
313 data);
314 } catch (OrekitException oe) {
315 pendingException = oe;
316 }
317 }
318 }
319
320 if (data.isEmpty() && pendingException != null) {
321 throw pendingException;
322 }
323
324 final EOPHistory history =
325 new EOPHistory(conventions, data, simpleEOP, timeScales);
326 history.checkEOPContinuity(eopContinuityThreshold);
327 return history;
328
329 }
330
331 }
332
333 }