KlobucharIonoCoefficientsLoader.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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.models.earth;

  18. import java.io.BufferedReader;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.InputStreamReader;
  22. import java.text.ParseException;

  23. import org.orekit.data.DataLoader;
  24. import org.orekit.data.DataProvidersManager;
  25. import org.orekit.errors.OrekitException;
  26. import org.orekit.errors.OrekitMessages;
  27. import org.orekit.time.DateComponents;

  28. /** Loads Klobuchar-Style ionospheric coefficients a given input stream.
  29.  * A stream contains the alphas and betas coefficient for a given day.
  30.  * <p>
  31.  * They are obtained from <a href="ftp://ftp.aiub.unibe.ch/aiub/CODE/">University of Bern Astronomical Institute ftp</a>.
  32.  * 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>.
  33.  * <p>
  34.  * The files are UNIX-style compressed (.Z) files.
  35.  * They have to be extracted to UTF-8 text files before being read by this loader.
  36.  * <p>
  37.  * After extraction, it is assumed they are named CGIMDDD0.YYN where DDD and YY substitute day of year and 2-digits year.
  38.  * <p>
  39.  * The format is always the same, with and example shown below. Only the last 2 lines contains the Klobuchar coefficients.
  40.  * <p>
  41.  * Example:
  42.  * </p>
  43.  * <pre>
  44.  *      2              NAVIGATION DATA     GPS                 RINEX VERSION / TYPE
  45.  * INXFIT V5.3         AIUB                06-JAN-17 09:12     PGM / RUN BY / DATE
  46.  * CODE'S KLOBUCHAR-STYLE IONOSPHERE MODEL FOR DAY 001, 2017   COMMENT
  47.  * Contact address: code(at)aiub.unibe.ch                      COMMENT
  48.  * Data archive:    ftp.unibe.ch/aiub/CODE/                    COMMENT
  49.  *                  www.aiub.unibe.ch/download/CODE/           COMMENT
  50.  * WARNING: USE DATA AT SOUTHERN POLAR REGION WITH CARE        COMMENT
  51.  *     1.2821D-08 -9.6222D-09 -3.5982D-07 -6.0901D-07          ION ALPHA
  52.  *     1.0840D+05 -1.3197D+05 -2.6331D+05  4.0570D+05          ION BETA
  53.  *                                                             END OF HEADER
  54.  * </pre>
  55.  * @author Maxime Journot
  56.  */
  57. public class KlobucharIonoCoefficientsLoader implements DataLoader {

  58.     /** Default supported files name pattern. */
  59.     public static final String DEFAULT_SUPPORTED_NAMES = "CGIM*0\\.*N$";

  60.     /** Regular expression for supported file name. */
  61.     private String supportedNames;

  62.     /** The alpha coefficients loaded. */
  63.     private double alpha[];

  64.     /** The beta coefficients loaded. */
  65.     private double beta[];

  66.     /** Constructor with supported names given by user.
  67.      * @param supportedNames Supported names
  68.      */
  69.     public KlobucharIonoCoefficientsLoader(final String supportedNames) {
  70.         this.alpha = null;
  71.         this.beta = null;
  72.         this.supportedNames = supportedNames;
  73.     }

  74.     /** Constructor with default supported names. */
  75.     public KlobucharIonoCoefficientsLoader() {
  76.         this(DEFAULT_SUPPORTED_NAMES);
  77.     }

  78.     /** Returns the alpha coefficients array.
  79.      * @return the alpha coefficients array
  80.      */
  81.     public double[] getAlpha() {
  82.         return alpha.clone();
  83.     }

  84.     /** Returns the beta coefficients array.
  85.      * @return the beta coefficients array
  86.      */
  87.     public double[] getBeta() {
  88.         return beta.clone();
  89.     }

  90.     /** Returns the supported names of the loader.
  91.      * @return the supported names
  92.      */
  93.     public String getSupportedNames() {
  94.         return supportedNames;
  95.     }

  96.     /** Load the data using supported names .
  97.      * @throws OrekitException */
  98.     public void loadKlobucharIonosphericCoefficients() throws OrekitException {
  99.         DataProvidersManager.getInstance().feed(supportedNames, this);

  100.         // Throw an exception if alphas or betas were not loaded properly
  101.         if (alpha == null || beta == null) {
  102.             throw new OrekitException(OrekitMessages.KLOBUCHAR_ALPHA_BETA_NOT_LOADED, supportedNames);
  103.         }
  104.     }

  105.     /** Load the data for a given day.
  106.      * @param dateComponents day given but its DateComponents
  107.      * @throws OrekitException if the coefficients could not be loaded
  108.      */
  109.     public void loadKlobucharIonosphericCoefficients(final DateComponents dateComponents) throws OrekitException {

  110.         // The files are named CGIMDDD0.YYN where DDD and YY substitute day of year and 2-digits year
  111.         final int    doy        = dateComponents.getDayOfYear();
  112.         final String yearString = String.valueOf(dateComponents.getYear());

  113.         this.supportedNames = String.format("CGIM%03d0.%2sN", doy, yearString.substring(yearString.length() - 2));

  114.         try {
  115.             this.loadKlobucharIonosphericCoefficients();
  116.         } catch (OrekitException oe) {
  117.             throw new OrekitException(oe,
  118.                                       OrekitMessages.KLOBUCHAR_ALPHA_BETA_NOT_AVAILABLE_FOR_DATE,
  119.                                       dateComponents.toString());
  120.         }
  121.     }

  122.     /** {@inheritDoc} */
  123.     public boolean stillAcceptsData() {
  124.         return true;
  125.     }

  126.     /** Load Klobuchar-Style ionospheric coefficients read from some file.
  127.      * @param input data input stream
  128.      * @param name name of the file (or zip entry)
  129.      * @exception IOException if data can't be read
  130.      * @exception ParseException if data can't be parsed
  131.      * @exception OrekitException if some data is missing
  132.      * or if some loader specific error occurs
  133.      */
  134.     public void loadData(final InputStream input, final String name)
  135.         throws IOException, ParseException, OrekitException {

  136.         // Open stream and parse data
  137.         final BufferedReader br = new BufferedReader(new InputStreamReader(input, "UTF-8"));
  138.         int lineNumber = 0;
  139.         final String splitter = "\\s+";
  140.         for (String line = br.readLine(); line != null; line = br.readLine()) {
  141.             ++lineNumber;
  142.             line = line.trim();

  143.             try {
  144.                 // Read alphas
  145.                 if (line.length() > 0 && line.endsWith("ALPHA")) {
  146.                     final String[] alpha_line = line.split(splitter);
  147.                     alpha = new double[4];
  148.                     for (int j = 0; j < 4; j++) {
  149.                         alpha[j] = Double.valueOf(alpha_line[j].replace("D", "E"));
  150.                     }
  151.                 }

  152.                 // Read betas
  153.                 if (line.length() > 0 && line.endsWith("BETA")) {
  154.                     final String[] beta_line = line.split(splitter);
  155.                     beta = new double[4];
  156.                     for (int j = 0; j < 4; j++) {
  157.                         beta[j] = Double.valueOf(beta_line[j].replace("D", "E"));
  158.                     }
  159.                 }
  160.             } catch (NumberFormatException nfe) {
  161.                 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
  162.                                           lineNumber, name, line);
  163.             }
  164.         }

  165.         // Check that alphas and betas were found
  166.         if (alpha == null || beta == null) {
  167.             throw new OrekitException(OrekitMessages.NO_KLOBUCHAR_ALPHA_BETA_IN_FILE, name);
  168.         }

  169.         // Close the stream after reading
  170.         input.close();
  171.     }
  172. }