All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.orekit.time.TAIUTCDatFilesLoader Maven / Gradle / Ivy

Go to download

OREKIT (ORbits Extrapolation KIT) is a low level space dynamics library. It provides basic elements (orbits, dates, attitude, frames ...) and various algorithms to handle them (conversions, analytical and numerical propagation, pointing ...).

There is a newer version: 12.2
Show newest version
/* Copyright 2002-2024 CS GROUP
 * Licensed to CS GROUP (CS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * CS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.orekit.time;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.hipparchus.util.FastMath;
import org.orekit.annotation.DefaultDataContext;
import org.orekit.data.AbstractSelfFeedingLoader;
import org.orekit.data.DataContext;
import org.orekit.data.DataProvidersManager;
import org.orekit.errors.OrekitException;
import org.orekit.errors.OrekitMessages;

/** Loader for UTC-TAI extracted from tai-utc.dat file from USNO.
 * 

* This class is immutable and hence thread-safe *

* @author Luc Maisonobe * @since 7.1 */ public class TAIUTCDatFilesLoader extends AbstractSelfFeedingLoader implements UTCTAIOffsetsLoader { /** Default supported files name pattern. */ public static final String DEFAULT_SUPPORTED_NAMES = "^tai-utc\\.dat$"; /** * Build a loader for tai-utc.dat file from USNO. This constructor uses the {@link * DataContext#getDefault() default data context}. * * @param supportedNames regular expression for supported files names * @see #TAIUTCDatFilesLoader(String, DataProvidersManager) */ @DefaultDataContext public TAIUTCDatFilesLoader(final String supportedNames) { this(supportedNames, DataContext.getDefault().getDataProvidersManager()); } /** * Build a loader for tai-utc.dat file from USNO. * * @param supportedNames regular expression for supported files names * @param manager provides access to the {@code tai-utc.dat} file. */ public TAIUTCDatFilesLoader(final String supportedNames, final DataProvidersManager manager) { super(supportedNames, manager); } /** {@inheritDoc} */ @Override public List loadOffsets() { final UtcTaiOffsetLoader parser = new UtcTaiOffsetLoader(new Parser()); this.feed(parser); return parser.getOffsets(); } /** Internal class performing the parsing. */ public static class Parser implements UTCTAIOffsetsLoader.Parser { /** Regular expression for optional blanks. */ private static final String BLANKS = "\\p{Blank}*"; /** Regular expression for storage start. */ private static final String STORAGE_START = "("; /** Regular expression for storage end. */ private static final String STORAGE_END = ")"; /** Regular expression for alternative. */ private static final String ALTERNATIVE = "|"; /** Regular expression matching blanks at start of line. */ private static final String LINE_START_REGEXP = "^" + BLANKS; /** Regular expression matching blanks at end of line. */ private static final String LINE_END_REGEXP = BLANKS + "$"; /** Regular expression matching integers. */ private static final String INTEGER_REGEXP = "[-+]?\\p{Digit}+"; /** Regular expression matching real numbers. */ private static final String REAL_REGEXP = "[-+]?(?:(?:\\p{Digit}+(?:\\.\\p{Digit}*)?)|(?:\\.\\p{Digit}+))(?:[eE][-+]?\\p{Digit}+)?"; /** Regular expression matching an integer field to store. */ private static final String STORED_INTEGER_FIELD = BLANKS + STORAGE_START + INTEGER_REGEXP + STORAGE_END; /** Regular expression matching a real field to store. */ private static final String STORED_REAL_FIELD = BLANKS + STORAGE_START + REAL_REGEXP + STORAGE_END; /** Data lines pattern. */ private Pattern dataPattern; /** Simple constructor. */ public Parser() { // data lines read: // 1965 SEP 1 =JD 2439004.5 TAI-UTC= 3.8401300 S + (MJD - 38761.) X 0.001296 S // 1966 JAN 1 =JD 2439126.5 TAI-UTC= 4.3131700 S + (MJD - 39126.) X 0.002592 S // 1968 FEB 1 =JD 2439887.5 TAI-UTC= 4.2131700 S + (MJD - 39126.) X 0.002592 S // 1972 JAN 1 =JD 2441317.5 TAI-UTC= 10.0 S + (MJD - 41317.) X 0.0 S // 1972 JUL 1 =JD 2441499.5 TAI-UTC= 11.0 S + (MJD - 41317.) X 0.0 S // 1973 JAN 1 =JD 2441683.5 TAI-UTC= 12.0 S + (MJD - 41317.) X 0.0 S // 1974 JAN 1 =JD 2442048.5 TAI-UTC= 13.0 S + (MJD - 41317.) X 0.0 S // month as a three letters upper case abbreviation final StringBuilder builder = new StringBuilder(BLANKS + STORAGE_START); for (final Month month : Month.values()) { builder.append(month.getUpperCaseAbbreviation()); builder.append(ALTERNATIVE); } builder.delete(builder.length() - 1, builder.length()); builder.append(STORAGE_END); final String monthField = builder.toString(); dataPattern = Pattern.compile(LINE_START_REGEXP + STORED_INTEGER_FIELD + monthField + STORED_INTEGER_FIELD + "\\p{Blank}+=JD" + STORED_REAL_FIELD + "\\p{Blank}+TAI-UTC=" + STORED_REAL_FIELD + "\\p{Blank}+S\\p{Blank}+\\+\\p{Blank}+\\(MJD\\p{Blank}+-" + STORED_REAL_FIELD + "\\p{Blank}*\\)\\p{Blank}+X" + STORED_REAL_FIELD + "\\p{Blank}*S" + LINE_END_REGEXP); } /** Load UTC-TAI offsets entries read from some file. *

The time steps are extracted from some {@code tai-utc.dat} file. * Since entries are stored in a {@link java.util.SortedMap SortedMap}, * they are chronologically sorted and only one entry remains for a given date.

* @param input data input stream * @param name name of the file (or zip entry) * @exception IOException if data can't be read */ @Override public List parse(final InputStream input, final String name) throws IOException { final List offsets = new ArrayList<>(); int lineNumber = 0; DateComponents lastDate = null; String line = null; // set up a reader for line-oriented file try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { // read all file, ignoring not recognized lines for (line = reader.readLine(); line != null; line = reader.readLine()) { ++lineNumber; // check matching for data lines final Matcher matcher = dataPattern.matcher(line); if (matcher.matches()) { // build an entry from the extracted fields final DateComponents dc1 = new DateComponents(Integer.parseInt(matcher.group(1)), Month.parseMonth(matcher.group(2)), Integer.parseInt(matcher.group(3))); final DateComponents dc2 = new DateComponents(DateComponents.JULIAN_EPOCH, (int) FastMath.ceil(Double.parseDouble(matcher.group(4)))); if (!dc1.equals(dc2)) { throw new OrekitException(OrekitMessages.INCONSISTENT_DATES_IN_IERS_FILE, name, dc1.getYear(), dc1.getMonth(), dc1.getDay(), dc2.getMJD()); } if (lastDate != null && dc1.compareTo(lastDate) <= 0) { throw new OrekitException(OrekitMessages.NON_CHRONOLOGICAL_DATES_IN_FILE, name, lineNumber); } lastDate = dc1; final double offset = Double.parseDouble(matcher.group(5)); final double mjdRef = Double.parseDouble(matcher.group(6)); final double slope = Double.parseDouble(matcher.group(7)); offsets.add(new OffsetModel(dc1, (int) FastMath.rint(mjdRef), offset, slope)); } } } catch (NumberFormatException nfe) { throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, lineNumber, name, line); } if (offsets.isEmpty()) { throw new OrekitException(OrekitMessages.NO_ENTRIES_IN_IERS_UTC_TAI_HISTORY_FILE, name); } return offsets; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy