1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.frames;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.List;
24 import java.util.function.Supplier;
25
26 import org.orekit.data.DataProvidersManager;
27 import org.orekit.data.DataSource;
28 import org.orekit.errors.OrekitException;
29 import org.orekit.errors.OrekitMessages;
30 import org.orekit.time.AbsoluteDate;
31 import org.orekit.time.DateComponents;
32 import org.orekit.time.TimeScale;
33 import org.orekit.utils.IERSConventions;
34 import org.orekit.utils.IERSConventions.NutationCorrectionConverter;
35 import org.orekit.utils.units.Unit;
36
37
38
39
40
41
42
43
44 class EopCsvFilesLoader extends AbstractEopLoader implements EopHistoryLoader {
45
46
47 private static final String SEPARATOR = ";";
48
49
50 private static final String MJD = "MJD";
51
52
53 private static final String YEAR = "Year";
54
55
56 private static final String MONTH = "Month";
57
58
59 private static final String DAY = "Day";
60
61
62 private static final String X_POLE = "x_pole";
63
64
65 private static final String Y_POLE = "y_pole";
66
67
68 private static final String X_RATE = "x_rate";
69
70
71 private static final String Y_RATE = "y_rate";
72
73
74 private static final String UT1_UTC = "UT1-UTC";
75
76
77 private static final String LOD = "LOD";
78
79
80 private static final String DPSI = "dPsi";
81
82
83 private static final String DEPSILON = "dEpsilon";
84
85
86 private static final String DX = "dX";
87
88
89 private static final String DY = "dY";
90
91
92 private static final Unit AS = Unit.parse("as");
93
94
95 private static final Unit AS_D = Unit.parse("as/day");
96
97
98 private static final Unit S = Unit.parse("s");
99
100
101
102
103
104
105 EopCsvFilesLoader(final String supportedNames,
106 final DataProvidersManager manager,
107 final Supplier<TimeScale> utcSupplier) {
108 super(supportedNames, manager, utcSupplier);
109 }
110
111
112 public void fillHistory(final IERSConventions.NutationCorrectionConverter converter,
113 final Collection<EOPEntry> history) {
114 final Parser parser = new Parser(converter, getUtc());
115 final EopParserLoader loader = new EopParserLoader(parser);
116 this.feed(loader);
117 history.addAll(loader.getEop());
118 }
119
120
121 class Parser extends AbstractEopParser {
122
123
124 private final ItrfVersionProvider itrfVersionProvider;
125
126
127 private int mjdColumn;
128
129
130 private int yearColumn;
131
132
133 private int monthColumn;
134
135
136 private int dayColumn;
137
138
139 private int xPoleColumn;
140
141
142 private int yPoleColumn;
143
144
145 private int xRatePoleColumn;
146
147
148 private int yRatePoleColumn;
149
150
151 private int ut1Column;
152
153
154 private int lodColumn;
155
156
157 private int dxColumn;
158
159
160 private int dyColumn;
161
162
163 private int dPsiColumn;
164
165
166 private int dEpsilonColumn;
167
168
169 private ITRFVersionLoader.ITRFVersionConfiguration configuration;
170
171
172
173
174
175 Parser(final NutationCorrectionConverter converter,
176 final TimeScale utc) {
177 super(converter, null, utc);
178 this.itrfVersionProvider = new ITRFVersionLoader(ITRFVersionLoader.SUPPORTED_NAMES,
179 getDataProvidersManager());
180 }
181
182
183 public Collection<EOPEntry> parse(final DataSource source)
184 throws IOException, OrekitException {
185
186 final List<EOPEntry> history = new ArrayList<>();
187
188
189 try (BufferedReader reader = new BufferedReader(source.getOpener().openReaderOnce())) {
190
191 int lineNumber = 0;
192 configuration = null;
193
194
195 for (String line = reader.readLine(); line != null; line = reader.readLine()) {
196 ++lineNumber;
197
198 final boolean parsed;
199 if (lineNumber == 1) {
200 parsed = parseHeaderLine(line);
201 } else {
202 history.add(parseDataLine(line, source.getName()));
203 parsed = true;
204 }
205
206 if (!parsed) {
207 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
208 lineNumber, source.getName(), line);
209 }
210 }
211
212
213 if (lineNumber < 2) {
214 throw new OrekitException(OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE, source.getName());
215 }
216 }
217
218 return history;
219 }
220
221
222
223
224
225 private boolean parseHeaderLine(final String headerLine) {
226
227
228 mjdColumn = -1;
229 yearColumn = -1;
230 monthColumn = -1;
231 dayColumn = -1;
232 xPoleColumn = -1;
233 yPoleColumn = -1;
234 xRatePoleColumn = -1;
235 yRatePoleColumn = -1;
236 ut1Column = -1;
237 lodColumn = -1;
238 dxColumn = -1;
239 dyColumn = -1;
240 dPsiColumn = -1;
241 dEpsilonColumn = -1;
242
243
244 final String[] fields = headerLine.split(SEPARATOR);
245
246
247 for (int column = 0; column < fields.length; ++column) {
248 switch (fields[column]) {
249 case MJD :
250 mjdColumn = column;
251 break;
252 case YEAR :
253 yearColumn = column;
254 break;
255 case MONTH :
256 monthColumn = column;
257 break;
258 case DAY :
259 dayColumn = column;
260 break;
261 case X_POLE :
262 xPoleColumn = column;
263 break;
264 case Y_POLE :
265 yPoleColumn = column;
266 break;
267 case X_RATE :
268 xRatePoleColumn = column;
269 break;
270 case Y_RATE :
271 yRatePoleColumn = column;
272 break;
273 case UT1_UTC :
274 ut1Column = column;
275 break;
276 case LOD :
277 lodColumn = column;
278 break;
279 case DX :
280 dxColumn = column;
281 break;
282 case DY :
283 dyColumn = column;
284 break;
285 case DPSI :
286 dPsiColumn = column;
287 break;
288 case DEPSILON :
289 dEpsilonColumn = column;
290 break;
291 default :
292
293 }
294 }
295
296
297 return mjdColumn >= 0 && yearColumn >= 0 && monthColumn >= 0 && dayColumn >= 0 &&
298 xPoleColumn >= 0 && yPoleColumn >= 0 && ut1Column >= 0 && lodColumn >= 0 &&
299 (dxColumn >= 0 && dyColumn >= 0 || dPsiColumn >= 0 && dEpsilonColumn >= 0);
300
301 }
302
303
304
305
306
307
308 private EOPEntry parseDataLine(final String line, final String name) {
309
310 final String[] fields = line.split(SEPARATOR);
311
312
313 final DateComponents dc = new DateComponents(Integer.parseInt(fields[yearColumn]),
314 Integer.parseInt(fields[monthColumn]),
315 Integer.parseInt(fields[dayColumn]));
316 final int mjd = Integer.parseInt(fields[mjdColumn]);
317 if (dc.getMJD() != mjd) {
318 throw new OrekitException(OrekitMessages.INCONSISTENT_DATES_IN_IERS_FILE,
319 name, dc.getYear(), dc.getMonth(), dc.getDay(), mjd);
320 }
321 final AbsoluteDate date = new AbsoluteDate(dc, getUtc());
322
323 if (configuration == null || !configuration.isValid(mjd)) {
324
325 configuration = itrfVersionProvider.getConfiguration(name, mjd);
326 }
327
328 final double x = parseField(fields, xPoleColumn, AS);
329 final double y = parseField(fields, yPoleColumn, AS);
330 final double xRate = parseField(fields, xRatePoleColumn, AS_D);
331 final double yRate = parseField(fields, yRatePoleColumn, AS_D);
332 final double dtu1 = parseField(fields, ut1Column, S);
333 final double lod = parseField(fields, lodColumn, S);
334
335 if (dxColumn >= 0) {
336
337 final double dx = parseField(fields, dxColumn, AS);
338 final double dy = parseField(fields, dyColumn, AS);
339 final double[] equinox = getConverter().toEquinox(date, dx, dy);
340 return new EOPEntry(dc.getMJD(), dtu1, lod, x, y, xRate, yRate,
341 equinox[0], equinox[1], dx, dy,
342 configuration.getVersion(), date, EopDataType.UNKNOWN);
343 } else {
344
345 final double ddPsi = parseField(fields, dPsiColumn, AS);
346 final double dddEpsilon = parseField(fields, dEpsilonColumn, AS);
347 final double[] nro = getConverter().toNonRotating(date, ddPsi, dddEpsilon);
348 return new EOPEntry(dc.getMJD(), dtu1, lod, x, y, xRate, yRate,
349 ddPsi, dddEpsilon, nro[0], nro[1],
350 configuration.getVersion(), date, EopDataType.UNKNOWN);
351 }
352
353
354 }
355
356
357
358
359
360
361
362 private double parseField(final String[] fields, final int index, final Unit unit) {
363 return (index < 0 || index >= fields.length || fields[index].isEmpty()) ?
364 Double.NaN :
365 unit.toSI(Double.parseDouble(fields[index]));
366 }
367
368 }
369
370 }