KlobucharIonoCoefficientsLoader.java
- /* Copyright 2002-2025 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.models.earth.ionosphere;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.nio.charset.StandardCharsets;
- import java.text.ParseException;
- import java.util.Locale;
- import java.util.regex.Pattern;
- import org.orekit.annotation.DefaultDataContext;
- import org.orekit.data.AbstractSelfFeedingLoader;
- import org.orekit.data.DataContext;
- import org.orekit.data.DataLoader;
- import org.orekit.data.DataProvidersManager;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitMessages;
- import org.orekit.time.DateComponents;
- /** Loads Klobuchar-Style ionospheric coefficients a given input stream.
- * A stream contains the alphas and betas coefficient for a given day.
- * <p>
- * They are obtained from <a href="ftp://ftp.aiub.unibe.ch/CODE/">University of Bern Astronomical Institute ftp</a>.
- * Find more on the files at the <a href="http://www.aiub.unibe.ch/research/code___analysis_center/klobuchar_style_ionospheric_coefficients/index_eng.html">Astronomical Institute site</a>.
- * <p>
- * The files are UNIX-style compressed (.Z) files.
- * They have to be extracted to UTF-8 text files before being read by this loader.
- * <p>
- * After extraction, it is assumed they are named CGIMDDD0.YYN where DDD and YY substitute day of year and 2-digits year.
- * <p>
- * The format is always the same, with and example shown below. Only the last 2 lines contains the Klobuchar coefficients.
- * <p>
- * Example:
- * </p>
- * <pre>
- * 2 NAVIGATION DATA GPS RINEX VERSION / TYPE
- * INXFIT V5.3 AIUB 06-JAN-17 09:12 PGM / RUN BY / DATE
- * CODE'S KLOBUCHAR-STYLE IONOSPHERE MODEL FOR DAY 001, 2017 COMMENT
- * Contact address: code(at)aiub.unibe.ch COMMENT
- * Data archive: ftp.unibe.ch/aiub/CODE/ COMMENT
- * www.aiub.unibe.ch/download/CODE/ COMMENT
- * WARNING: USE DATA AT SOUTHERN POLAR REGION WITH CARE COMMENT
- * 1.2821D-08 -9.6222D-09 -3.5982D-07 -6.0901D-07 ION ALPHA
- * 1.0840D+05 -1.3197D+05 -2.6331D+05 4.0570D+05 ION BETA
- * END OF HEADER
- * </pre>
- *
- * <p>It is not safe for multiple threads to share a single instance of this class.
- *
- * @author Maxime Journot
- */
- public class KlobucharIonoCoefficientsLoader extends AbstractSelfFeedingLoader
- implements DataLoader {
- /** Default supported files name pattern. */
- public static final String DEFAULT_SUPPORTED_NAMES = "CGIM*0\\.*N$";
- /** Pattern for delimiting regular expressions. */
- private static final Pattern SEPARATOR = Pattern.compile("\\s+");
- /** The alpha coefficients loaded. */
- private double[] alpha;
- /** The beta coefficients loaded. */
- private double[] beta;
- /**
- * Constructor with supported names given by user. This constructor uses the {@link
- * DataContext#getDefault() default data context}.
- *
- * @param supportedNames regular expression that matches the names of the RINEX files
- * with Klobuchar coefficients.
- * @see #KlobucharIonoCoefficientsLoader(String, DataProvidersManager)
- */
- @DefaultDataContext
- public KlobucharIonoCoefficientsLoader(final String supportedNames) {
- this(supportedNames, DataContext.getDefault().getDataProvidersManager());
- }
- /**
- * Constructor that uses user defined supported names and data context.
- *
- * @param supportedNames regular expression that matches the names of the RINEX
- * files with Klobuchar coefficients.
- * @param dataProvidersManager provides access to auxiliary data files.
- */
- public KlobucharIonoCoefficientsLoader(final String supportedNames,
- final DataProvidersManager dataProvidersManager) {
- super(supportedNames, dataProvidersManager);
- this.alpha = null;
- this.beta = null;
- }
- /**
- * Constructor with default supported names. This constructor uses the {@link
- * DataContext#getDefault() default data context}.
- *
- * @see #KlobucharIonoCoefficientsLoader(String, DataProvidersManager)
- * @see #KlobucharIonoCoefficientsLoader(String)
- */
- @DefaultDataContext
- public KlobucharIonoCoefficientsLoader() {
- this(DEFAULT_SUPPORTED_NAMES);
- }
- /** Returns the alpha coefficients array.
- * @return the alpha coefficients array
- */
- public double[] getAlpha() {
- return alpha.clone();
- }
- /** Returns the beta coefficients array.
- * @return the beta coefficients array
- */
- public double[] getBeta() {
- return beta.clone();
- }
- @Override
- public String getSupportedNames() {
- return super.getSupportedNames();
- }
- /** Load the data using supported names .
- */
- public void loadKlobucharIonosphericCoefficients() {
- feed(this);
- // Throw an exception if alphas or betas were not loaded properly
- if (alpha == null || beta == null) {
- throw new OrekitException(OrekitMessages.KLOBUCHAR_ALPHA_BETA_NOT_LOADED,
- getSupportedNames());
- }
- }
- /** Load the data for a given day.
- * @param dateComponents day given but its DateComponents
- */
- public void loadKlobucharIonosphericCoefficients(final DateComponents dateComponents) {
- // The files are named CGIMDDD0.YYN where DDD and YY substitute day of year and 2-digits year
- final int doy = dateComponents.getDayOfYear();
- final String yearString = String.valueOf(dateComponents.getYear());
- this.setSupportedNames(String.format(Locale.US, "CGIM%03d0.%2sN",
- doy, yearString.substring(yearString.length() - 2)));
- try {
- this.loadKlobucharIonosphericCoefficients();
- } catch (OrekitException oe) {
- throw new OrekitException(oe,
- OrekitMessages.KLOBUCHAR_ALPHA_BETA_NOT_AVAILABLE_FOR_DATE,
- dateComponents.toString());
- }
- }
- /** {@inheritDoc} */
- public boolean stillAcceptsData() {
- return true;
- }
- /** Load Klobuchar-Style ionospheric coefficients read from some file.
- * @param input data input stream
- * @param name name of the file (or zip entry)
- * @exception IOException if data can't be read
- * @exception ParseException if data can't be parsed
- */
- public void loadData(final InputStream input, final String name)
- throws IOException, ParseException {
- int lineNumber = 0;
- String line = null;
- // Open stream and parse data
- try (BufferedReader br = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
- for (line = br.readLine(); line != null; line = br.readLine()) {
- ++lineNumber;
- line = line.trim();
- // Read alphas
- if (line.length() > 0 && line.endsWith("ALPHA")) {
- final String[] alpha_line = SEPARATOR.split(line);
- alpha = new double[4];
- for (int j = 0; j < 4; j++) {
- alpha[j] = Double.parseDouble(alpha_line[j].replace("D", "E"));
- }
- }
- // Read betas
- if (line.length() > 0 && line.endsWith("BETA")) {
- final String[] beta_line = SEPARATOR.split(line);
- beta = new double[4];
- for (int j = 0; j < 4; j++) {
- beta[j] = Double.parseDouble(beta_line[j].replace("D", "E"));
- }
- }
- }
- } catch (NumberFormatException nfe) {
- throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
- lineNumber, name, line);
- }
- // Check that alphas and betas were found
- if (alpha == null || beta == null) {
- throw new OrekitException(OrekitMessages.NO_KLOBUCHAR_ALPHA_BETA_IN_FILE, name);
- }
- }
- }