TimeSpanEstimatedModel.java

  1. /* Copyright 2002-2025 CS GROUP
  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.models.earth.troposphere;

  18. import java.util.ArrayList;
  19. import java.util.List;

  20. import org.hipparchus.CalculusFieldElement;
  21. import org.hipparchus.util.MathArrays;
  22. import org.orekit.annotation.DefaultDataContext;
  23. import org.orekit.bodies.FieldGeodeticPoint;
  24. import org.orekit.bodies.GeodeticPoint;
  25. import org.orekit.time.AbsoluteDate;
  26. import org.orekit.time.FieldAbsoluteDate;
  27. import org.orekit.time.TimeScale;
  28. import org.orekit.time.TimeScalesFactory;
  29. import org.orekit.utils.FieldTrackingCoordinates;
  30. import org.orekit.utils.ParameterDriver;
  31. import org.orekit.utils.ParameterDriversProvider;
  32. import org.orekit.utils.TimeSpanMap;
  33. import org.orekit.utils.TimeSpanMap.Span;
  34. import org.orekit.utils.TrackingCoordinates;

  35. /**
  36.  * Time span estimated tropospheric model.
  37.  * <p>
  38.  * This class is closely related to {@link org.orekit.models.earth.troposphere EstimatedModel} class.<br>
  39.  * The difference is that it has a {@link TimeSpanMap} of {@link EstimatedModel} objects as attribute. <br>
  40.  * The idea behind this model is to allow the user to design a tropospheric model that can see its physical parameters
  41.  * (total zenith delay) change with time, at dates chosen by the user. <br>
  42.  * </p>
  43.  * @author Bryan Cazabonne
  44.  * @since 10.2
  45.  */
  46. public class TimeSpanEstimatedModel implements TroposphericModel {

  47.     /** Prefix for dates before in the tropospheric parameter drivers' name. */
  48.     public static final String DATE_BEFORE = " - Before ";

  49.     /** Prefix for dates after in the tropospheric parameter drivers' name. */
  50.     public static final String DATE_AFTER = " - After ";

  51.     /** Time scale for transition dates. */
  52.     private final TimeScale timeScale;

  53.     /** It contains all the models use for the whole period of measurements. */
  54.     private final TimeSpanMap<EstimatedModel> troposphericModelMap;

  55.     /**
  56.      * Constructor with default UTC time scale.
  57.      * @param model the initial model which going to be used for all the models initialization.
  58.      */
  59.     @DefaultDataContext
  60.     public TimeSpanEstimatedModel(final EstimatedModel model) {
  61.         this(model, TimeScalesFactory.getUTC());
  62.     }

  63.     /**
  64.      * Constructor with default UTC time scale.
  65.      * @param model the initial model which going to be used for all the models initialization.
  66.      * @param timeScale  timeScale Time scale used for the default names of the tropospheric parameter drivers
  67.      */
  68.     public TimeSpanEstimatedModel(final EstimatedModel model, final TimeScale timeScale) {
  69.         this.troposphericModelMap = new TimeSpanMap<>(model);
  70.         this.timeScale            = timeScale;
  71.     }

  72.     /** {@inheritDoc}
  73.      * <p>
  74.      * All the parameter drivers of all Estimated models are returned in an array.
  75.      * Models are ordered chronologically.
  76.      * </p>
  77.      */
  78.     @Override
  79.     public List<ParameterDriver> getParametersDrivers() {

  80.         // Get all transitions from the TimeSpanMap
  81.         final List<ParameterDriver> listTroposphericParameterDrivers = new ArrayList<>();

  82.         // Loop on the spans
  83.         for (Span<EstimatedModel> span = getFirstSpan(); span != null; span = span.next()) {
  84.             // Add all the parameter drivers of each span
  85.             for (ParameterDriver tropoDriver : span.getData().getParametersDrivers()) {
  86.                 // Add the driver only if the name does not exist already
  87.                 if (!ParameterDriversProvider.findByName(listTroposphericParameterDrivers, tropoDriver.getName())) {
  88.                     listTroposphericParameterDrivers.add(tropoDriver);
  89.                 }
  90.             }
  91.         }

  92.         // Return an array of parameter drivers with no duplicated name
  93.         return listTroposphericParameterDrivers;

  94.     }

  95.     /** Add an EstimatedTroposphericModel entry valid before a limit date.<br>
  96.      * Using <code>addTroposphericValidBefore(entry, t)</code> will make <code>entry</code>
  97.      * valid in ]-∞, t[ (note the open bracket).
  98.      * @param model EstimatedTroposphericModel entry
  99.      * @param latestValidityDate date before which the entry is valid
  100.      * (must be different from <b>all</b> dates already used for transitions)
  101.      */
  102.     public void addTroposphericModelValidBefore(final EstimatedModel model, final AbsoluteDate latestValidityDate) {
  103.         troposphericModelMap.addValidBefore(changeTroposphericParameterDriversNames(model,
  104.                                                                                     latestValidityDate,
  105.                                                                                     DATE_BEFORE),
  106.                                             latestValidityDate, false);
  107.     }

  108.     /** Add a EstimatedTroposphericModel entry valid after a limit date.<br>
  109.      * Using <code>addTroposphericModelValidAfter(entry, t)</code> will make <code>entry</code>
  110.      * valid in [t, +∞[ (note the closed bracket).
  111.      * @param model EstimatedTroposphericModel entry
  112.      * @param earliestValidityDate date after which the entry is valid
  113.      * (must be different from <b>all</b> dates already used for transitions)
  114.      */
  115.     public void addTroposphericModelValidAfter(final EstimatedModel model, final AbsoluteDate earliestValidityDate) {
  116.         troposphericModelMap.addValidAfter(changeTroposphericParameterDriversNames(model,
  117.                                                                                    earliestValidityDate,
  118.                                                                                    DATE_AFTER),
  119.                                            earliestValidityDate, false);
  120.     }

  121.     /** Get the {@link EstimatedModel} model valid at a date.
  122.      * @param date the date of validity
  123.      * @return the EstimatedTroposphericModel model valid at date
  124.      */
  125.     public EstimatedModel getTroposphericModel(final AbsoluteDate date) {
  126.         return troposphericModelMap.get(date);
  127.     }

  128.     /** Get the first {@link Span time span} of the tropospheric model time span map.
  129.      * @return the first {@link Span time span} of the tropospheric model time span map
  130.      * @since 11.1
  131.      */
  132.     public Span<EstimatedModel> getFirstSpan() {
  133.         return troposphericModelMap.getFirstSpan();
  134.     }

  135.     /** Extract the proper parameter drivers' values from the array in input of the
  136.      * {@link #pathDelay(TrackingCoordinates, GeodeticPoint, double[], AbsoluteDate) pathDelay}  method.
  137.      *  Parameters are filtered given an input date.
  138.      * @param parameters the input parameters array
  139.      * @param date the date
  140.      * @return the parameters given the date
  141.      */
  142.     public double[] extractParameters(final double[] parameters, final AbsoluteDate date) {

  143.         // Get the tropospheric parameter drivers of the date
  144.         final List<ParameterDriver> troposphericParameterDriver = getTroposphericModel(date).getParametersDrivers();

  145.         // Find out the indexes of the parameters in the whole array of parameters
  146.         final List<ParameterDriver> allTroposphericParameters = getParametersDrivers();
  147.         final double[] outParameters = new double[troposphericParameterDriver.size()];
  148.         int index = 0;
  149.         for (int i = 0; i < allTroposphericParameters.size(); i++) {
  150.             final String driverName = allTroposphericParameters.get(i).getName();
  151.             for (ParameterDriver tropoDriver : troposphericParameterDriver) {
  152.                 if (tropoDriver.getName().equals(driverName)) {
  153.                     outParameters[index++] = parameters[i];
  154.                 }
  155.             }
  156.         }
  157.         return outParameters;
  158.     }

  159.     /** Extract the proper parameter drivers' values from the array in input of the
  160.      * {@link #pathDelay(TrackingCoordinates, GeodeticPoint, double[], AbsoluteDate) pathDelay}  method.
  161.      *  Parameters are filtered given an input date.
  162.      * @param parameters the input parameters array
  163.      * @param date the date
  164.      * @param <T> extends CalculusFieldElements
  165.      * @return the parameters given the date
  166.      */
  167.     public <T extends CalculusFieldElement<T>> T[] extractParameters(final T[] parameters,
  168.                                                                  final FieldAbsoluteDate<T> date) {

  169.         // Get the tropospheric parameter drivers of the date
  170.         final List<ParameterDriver> troposphericParameterDriver = getTroposphericModel(date.toAbsoluteDate()).getParametersDrivers();

  171.         // Find out the indexes of the parameters in the whole array of parameters
  172.         final List<ParameterDriver> allTroposphericParameters = getParametersDrivers();
  173.         final T[] outParameters = MathArrays.buildArray(date.getField(), troposphericParameterDriver.size());
  174.         int index = 0;
  175.         for (int i = 0; i < allTroposphericParameters.size(); i++) {
  176.             final String driverName = allTroposphericParameters.get(i).getName();
  177.             for (ParameterDriver tropoDriver : troposphericParameterDriver) {
  178.                 if (tropoDriver.getName().equals(driverName)) {
  179.                     outParameters[index++] = parameters[i];
  180.                 }
  181.             }
  182.         }
  183.         return outParameters;
  184.     }

  185.     /** {@inheritDoc} */
  186.     @Override
  187.     public TroposphericDelay pathDelay(final TrackingCoordinates trackingCoordinates,
  188.                                        final GeodeticPoint point,
  189.                                        final double[] parameters, final AbsoluteDate date) {
  190.         // Extract the proper parameters valid at date from the input array
  191.         final double[] extractedParameters = extractParameters(parameters, date);
  192.         // Compute and return the path delay
  193.         return getTroposphericModel(date).pathDelay(trackingCoordinates, point, extractedParameters, date);
  194.     }

  195.     /** {@inheritDoc} */
  196.     @Override
  197.     public <T extends CalculusFieldElement<T>> FieldTroposphericDelay<T> pathDelay(final FieldTrackingCoordinates<T> trackingCoordinates,
  198.                                                                                    final  FieldGeodeticPoint<T> point,
  199.                                                                                    final T[] parameters, final FieldAbsoluteDate<T> date) {
  200.         // Extract the proper parameters valid at date from the input array
  201.         final T[] extractedParameters = extractParameters(parameters, date);
  202.         // Compute and return the path delay
  203.         return getTroposphericModel(date.toAbsoluteDate()).pathDelay(trackingCoordinates, point,
  204.                                                                      extractedParameters, date);
  205.     }

  206.     /** Change the parameter drivers names of a {@link EstimatedModel} model, if needed.
  207.      * <p>
  208.      * This is done to avoid that several parameter drivers have the same name.<br>
  209.      * It is done only if the user hasn't modify the EstimatedTroposphericModel parameter drivers default names.
  210.      * </p>
  211.      * @param troposphericModel the EstimatedTroposphericModel model
  212.      * @param date the date used in the parameter driver's name
  213.      * @param datePrefix the date prefix used in the parameter driver's name
  214.      * @return the EstimatedTroposphericModel with its drivers' names changed
  215.      */
  216.     private EstimatedModel changeTroposphericParameterDriversNames(final EstimatedModel troposphericModel,
  217.                                                                    final AbsoluteDate date,
  218.                                                                    final String datePrefix) {
  219.         // Loop on the parameter drivers of the EstimatedTroposphericModel model
  220.         for (ParameterDriver driver: troposphericModel.getParametersDrivers()) {
  221.             final String driverName = driver.getName();

  222.             // If the name is the default name for EstimatedTroposphericModel parameter drivers
  223.             // Modify the name to add the prefix and the date
  224.             if (driverName.equals(EstimatedModel.TOTAL_ZENITH_DELAY)) {
  225.                 driver.setName(driverName + datePrefix + date.toString(timeScale));
  226.             }
  227.         }
  228.         return troposphericModel;
  229.     }

  230. }