1   /* Copyright 2002-2021 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.gnss.clock;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.function.Function;
25  
26  import org.orekit.errors.OrekitIllegalArgumentException;
27  import org.orekit.errors.OrekitMessages;
28  import org.orekit.frames.Frame;
29  import org.orekit.gnss.AppliedDCBS;
30  import org.orekit.gnss.AppliedPCVS;
31  import org.orekit.gnss.ObservationType;
32  import org.orekit.gnss.SatelliteSystem;
33  import org.orekit.gnss.TimeSystem;
34  import org.orekit.time.AbsoluteDate;
35  import org.orekit.time.DateComponents;
36  import org.orekit.time.TimeComponents;
37  import org.orekit.time.TimeScale;
38  import org.orekit.utils.TimeSpanMap;
39  
40  /** Represents a parsed clock file from the IGS.
41   * <p> A time system should be specified in the file. However, if it is not, default time system will be chosen
42   * regarding the satellite system. If it is mixed or not specified, default time system will be UTC. </p>
43   * <p> Some fields might be null after parsing. It is expected because of the numerous kind of data that can be stored in clock data file. </p>
44   * <p> Caution, files with missing information in header can lead to wrong data dates and station positions.
45   * It is adviced to check the correctness and format compliance of the clock file to be parsed.
46   * Some values such as file time scale still can be set by user. </p>
47   * @see <a href="ftp://igs.org/pub/data/format/rinex_clock300.txt"> 3.00 clock file format</a>
48   * @see <a href="ftp://igs.org/pub/data/format/rinex_clock302.txt"> 3.02 clock file format</a>
49   * @see <a href="ftp://igs.org/pub/data/format/rinex_clock304.txt"> 3.04 clock file format</a>
50   *
51   * @author Thomas Paulet
52   * @since 11.0
53   */
54  public class RinexClock {
55  
56      /** Format version. */
57      private double formatVersion;
58  
59      /** Satellite system. */
60      private SatelliteSystem satelliteSystem;
61  
62      /** Name of the program creating current file. */
63      private String programName;
64  
65      /** Name of the agency creating the current file. */
66      private String agencyName;
67  
68      /** Date of the file creation as a string. */
69      private String creationDateString;
70  
71      /** Time of the file creation as a string. */
72      private String creationTimeString;
73  
74      /** Time zone of the file creation as a string. */
75      private String creationTimeZoneString;
76  
77      /** Creation date as absolute date. */
78      private AbsoluteDate creationDate;
79  
80      /** Comments. */
81      private String comments;
82  
83      /** Satellite system code. */
84      private Map<SatelliteSystem, List<ObservationType>> systemObservationTypes;
85  
86      /** Time system. */
87      private TimeSystem timeSystem;
88  
89      /** Data time scale related to time system. */
90      private TimeScale timeScale;
91  
92      /** Number of leap seconds separating UTC and TAI (UTC = TAI - numberOfLeapSeconds). */
93      private int numberOfLeapSeconds;
94  
95      /** Number of leap seconds separating UTC and GNSS time systems. */
96      private int numberOfLeapSecondsGNSS;
97  
98      /** List of applied differential code bias corrections. */
99      private List<AppliedDCBS> listAppliedDCBS;
100 
101     /** List of antenna center variation corrections. */
102     private List<AppliedPCVS> listAppliedPCVS;
103 
104     /** List of the data types in the file. */
105     private List<ClockDataType> clockDataTypes;
106 
107     /** Station name for calibration and discontinuity data. */
108     private String stationName;
109 
110     /** Station identifier for calibration and discontinuity data. */
111     private String stationIdentifier;
112 
113     /** External reference clock identifier for calibration. */
114     private String externalClockReference;
115 
116     /** Analysis center ID. */
117     private String analysisCenterID;
118 
119     /** Full analysis center name. */
120     private String analysisCenterName;
121 
122     /** Reference clocks. */
123     private TimeSpanMap<List<ReferenceClock>> referenceClocks;
124 
125     /** Earth centered frame name as a string. */
126     private String frameName;
127 
128     /** Maps {@link #coordinateSystem} to a {@link Frame}. */
129     private final Function<? super String, ? extends Frame> frameBuilder;
130 
131     /** List of the receivers in the file. */
132     private List<Receiver> receivers;
133 
134     /** List of the satellites in the file. */
135     private List<String> satellites;
136 
137     /** A map containing receiver/satellite information. */
138     private Map<String, List<ClockDataLine>> clockData;
139 
140     /** Constructor.
141      * @param frameBuilder for constructing a reference frame from the identifier
142      */
143     public RinexClock(final Function<? super String, ? extends Frame> frameBuilder) {
144         // Initialize fields with default data
145         this.systemObservationTypes  = new HashMap<SatelliteSystem, List<ObservationType>>();
146         this.listAppliedDCBS         = new ArrayList<AppliedDCBS>();
147         this.listAppliedPCVS         = new ArrayList<AppliedPCVS>();
148         this.clockDataTypes          = new ArrayList<ClockDataType>();
149         this.receivers               = new ArrayList<Receiver>();
150         this.satellites              = new ArrayList<String>();
151         this.clockData               = new HashMap<String, List<ClockDataLine>>();
152         this.agencyName              = "";
153         this.analysisCenterID        = "";
154         this.analysisCenterName      = "";
155         this.comments                = "";
156         this.creationDate            = null;
157         this.creationDateString      = "";
158         this.creationTimeString      = "";
159         this.creationTimeZoneString  = "";
160         this.externalClockReference  = "";
161         this.formatVersion           = 0.0;
162         this.frameBuilder            = frameBuilder;
163         this.frameName               = "";
164         this.numberOfLeapSeconds     = 0;
165         this.numberOfLeapSecondsGNSS = 0;
166         this.programName             = "";
167         this.referenceClocks         = null;
168         this.satelliteSystem         = null;
169         this.stationIdentifier       = "";
170         this.stationName             = "";
171         this.timeScale               = null;
172         this.timeSystem              = null;
173     }
174 
175     /** Add a new satellite with a given identifier to the list of stored satellites.
176      * @param satId the satellite identifier
177      */
178     public void addSatellite(final String satId) {
179         // only add satellites which have not been added before
180         if (!satellites.contains(satId)) {
181             satellites.add(satId);
182         }
183     }
184 
185     /** Add a new receiver to the list of stored receivers.
186      * @param receiver the receiver
187      */
188     public void addReceiver(final Receiver receiver) {
189 
190         boolean notInList = true;
191         for (Receiver rec : receivers) {
192             if (rec.designator.equals(receiver.designator)) {
193                 notInList = false;
194             }
195         }
196         // only add satellites which have not been added before
197         if (notInList) {
198             receivers.add(receiver);
199         }
200     }
201 
202     /** Get the number of different clock data types in the file.
203      * @return the number of different clock data types
204      */
205     public int getNumberOfClockDataTypes() {
206         return clockDataTypes.size();
207     }
208 
209     /** Get the total number of complete data lines in the file.
210      * @return the total number of complete data lines in the file
211      */
212     public int getTotalNumberOfDataLines() {
213         int result = 0;
214         final Map<String, List<ClockDataLine>> data = getClockData();
215         for (final Map.Entry<String, List<ClockDataLine>> entry : data.entrySet()) {
216             result += entry.getValue().size();
217         }
218         return result;
219     }
220 
221     /** Get the number of observation types for a given system.
222      * @param system the satellite system to consider
223      * @return the number of observation types for a given system
224      */
225     public int numberOfObsTypes(final SatelliteSystem system) {
226         if (systemObservationTypes.containsKey(system)) {
227             return systemObservationTypes.get(system).size();
228         } else {
229             return 0;
230         }
231     }
232 
233     /** Get the number of receivers that are considered in the file.
234      * @return the number of receivers that are considered in the file
235      */
236     public int getNumberOfReceivers() {
237         return receivers.size();
238     }
239 
240     /** Get the number of satellites that are considered in the file.
241      * @return the number of satellites that are considered in the file
242      */
243     public int getNumberOfSatellites() {
244         return satellites.size();
245     }
246 
247     /** Getter for the format version.
248      * @return the format version
249      */
250     public double getFormatVersion() {
251         return formatVersion;
252     }
253 
254     /** Setter for the format version.
255      * @param formatVersion the format version to set
256      */
257     public void setFormatVersion(final double formatVersion) {
258         this.formatVersion = formatVersion;
259     }
260 
261     /** Getter for the satellite system.
262      * @return the satellite system
263      */
264     public SatelliteSystem getSatelliteSystem() {
265         return satelliteSystem;
266     }
267 
268     /** Setter for the satellite system.
269      * @param satelliteSystem the satellite system to set
270      */
271     public void setSatelliteSystem(final SatelliteSystem satelliteSystem) {
272         this.satelliteSystem = satelliteSystem;
273     }
274 
275     /** Getter for the program name.
276      * @return the program name
277      */
278     public String getProgramName() {
279         return programName;
280     }
281 
282     /** Setter for the program name.
283      * @param programName the program name to set
284      */
285     public void setProgramName(final String programName) {
286         this.programName = programName;
287     }
288 
289     /** Getter for the agency name.
290      * @return the agencyName
291      */
292     public String getAgencyName() {
293         return agencyName;
294     }
295 
296     /** Setter for the agency name.
297      * @param agencyName the agency name to set
298      */
299     public void setAgencyName(final String agencyName) {
300         this.agencyName = agencyName;
301     }
302 
303     /** Getter for the creation date of the file as a string.
304      * @return the creation date as a string
305      */
306     public String getCreationDateString() {
307         return creationDateString;
308     }
309 
310     /** Setter for the creation date as a string.
311      * @param creationDateString the creation date as a string to set
312      */
313     public void setCreationDateString(final String creationDateString) {
314         this.creationDateString = creationDateString;
315     }
316 
317     /** Getter for the creation time of the file as a string.
318      * @return the creation time as a string
319      */
320     public String getCreationTimeString() {
321         return creationTimeString;
322     }
323 
324     /** Setter for the creation time as a string.
325      * @param creationTimeString the creation time as a string to set
326      */
327     public void setCreationTimeString(final String creationTimeString) {
328         this.creationTimeString = creationTimeString;
329     }
330 
331     /** Getter for the creation time zone of the file as a string.
332      * @return the creation time zone as a string
333      */
334     public String getCreationTimeZoneString() {
335         return creationTimeZoneString;
336     }
337 
338     /** Setter for the creation time zone.
339      * @param creationTimeZoneString the creation time zone as a string to set
340      */
341     public void setCreationTimeZoneString(final String creationTimeZoneString) {
342         this.creationTimeZoneString = creationTimeZoneString;
343     }
344 
345     /** Getter for the creation date.
346      * @return the creation date
347      */
348     public AbsoluteDate getCreationDate() {
349         return creationDate;
350     }
351 
352     /** Setter for the creation date.
353      * @param creationDate the creation date to set
354      */
355     public void setCreationDate(final AbsoluteDate creationDate) {
356         this.creationDate = creationDate;
357     }
358 
359     /** Getter for the comments.
360      * @return the comments
361      */
362     public String getComments() {
363         return comments;
364     }
365 
366     /** Add a comment line.
367      * @param comment the comment line to add
368      */
369     public void addComment(final String comment) {
370         this.comments = comments.concat(comment + "\n");
371     }
372 
373     /** Getter for the different observation type for each satellite system.
374      * @return the map of the different observation type per satellite system
375      */
376     public Map<SatelliteSystem, List<ObservationType>> getSystemObservationTypes() {
377         return Collections.unmodifiableMap(systemObservationTypes);
378     }
379 
380     /** Add an observation type for a specified satellite system.
381      * @param satSystem the satellite system to add observation type
382      * @param observationType the system observation type to set
383      */
384     public void addSystemObservationType(final SatelliteSystem satSystem,
385                                          final ObservationType observationType) {
386         systemObservationTypes.putIfAbsent(satSystem, new ArrayList<ObservationType>());
387         systemObservationTypes.get(satSystem).add(observationType);
388     }
389 
390     /** Getter for the file time system.
391      * @return the file time system
392      */
393     public TimeSystem getTimeSystem() {
394         return timeSystem;
395     }
396 
397     /** Setter for the file time system.
398      * @param timeSystem the file time system to set
399      */
400     public void setTimeSystem(final TimeSystem timeSystem) {
401         this.timeSystem = timeSystem;
402     }
403 
404     /** Getter for the data time scale.
405      * @return the data time scale
406      */
407     public TimeScale getTimeScale() {
408         return timeScale;
409     }
410 
411     /** Setter for the data time scale.
412      * @param timeScale the data time scale to set
413      */
414     public void setTimeScale(final TimeScale timeScale) {
415         this.timeScale = timeScale;
416     }
417 
418     /** Getter for the number of leap seconds.
419      * @return the number of leap seconds
420      */
421     public int getNumberOfLeapSeconds() {
422         return numberOfLeapSeconds;
423     }
424 
425     /** Setter for the number of leap seconds.
426      * @param numberOfLeapSeconds the number of leap seconds to set
427      */
428     public void setNumberOfLeapSeconds(final int numberOfLeapSeconds) {
429         this.numberOfLeapSeconds = numberOfLeapSeconds;
430     }
431 
432     /** Getter for the number of leap second for GNSS time scales.
433      * @return the number of leap seconds for GNSS time scales
434      */
435     public int getNumberOfLeapSecondsGNSS() {
436         return numberOfLeapSecondsGNSS;
437     }
438 
439     /** Setter for the number of leap seconds for GNSS time scales.
440      * @param numberOfLeapSecondsGNSS the number of leap seconds for GNSS time scales to set
441      */
442     public void setNumberOfLeapSecondsGNSS(final int numberOfLeapSecondsGNSS) {
443         this.numberOfLeapSecondsGNSS = numberOfLeapSecondsGNSS;
444     }
445 
446     /** Getter for the applied differential code bias corrections.
447      * @return the list of applied differential code bias corrections
448      */
449     public List<AppliedDCBS> getListAppliedDCBS() {
450         return Collections.unmodifiableList(listAppliedDCBS);
451     }
452 
453     /** Add an applied differencial code bias corrections.
454      * @param appliedDCBS the applied differencial code bias corrections to add
455      */
456     public void addAppliedDCBS(final AppliedDCBS appliedDCBS) {
457         listAppliedDCBS.add(appliedDCBS);
458     }
459 
460     /** Getter for the applied phase center variations.
461      * @return the list of the applied phase center variations
462      */
463     public List<AppliedPCVS> getListAppliedPCVS() {
464         return Collections.unmodifiableList(listAppliedPCVS);
465     }
466 
467     /** Add an applied phase center variations.
468      * @param appliedPCVS the phase center variations to add
469      */
470     public void addAppliedPCVS(final AppliedPCVS appliedPCVS) {
471         listAppliedPCVS.add(appliedPCVS);
472     }
473 
474     /** Getter for the different clock data types.
475      * @return the list of the different clock data types
476      */
477     public List<ClockDataType> getClockDataTypes() {
478         return Collections.unmodifiableList(clockDataTypes);
479     }
480 
481     /** Add a clock data types.
482      * @param clockDataType the clock data types to add
483      */
484     public void addClockDataType(final ClockDataType clockDataType) {
485         clockDataTypes.add(clockDataType);
486     }
487 
488     /** Getter for the station name.
489      * @return the station name
490      */
491     public String getStationName() {
492         return stationName;
493     }
494 
495     /** Setter for the station name.
496      * @param stationName the station name to set
497      */
498     public void setStationName(final String stationName) {
499         this.stationName = stationName;
500     }
501 
502     /** Getter for the station identifier.
503      * @return the station identifier
504      */
505     public String getStationIdentifier() {
506         return stationIdentifier;
507     }
508 
509     /** Setter for the station identifier.
510      * @param stationIdentifier the station identifier to set
511      */
512     public void setStationIdentifier(final String stationIdentifier) {
513         this.stationIdentifier = stationIdentifier;
514     }
515 
516     /** Getter for the external clock reference.
517      * @return the external clock reference
518      */
519     public String getExternalClockReference() {
520         return externalClockReference;
521     }
522 
523     /** Setter for the external clock reference.
524      * @param externalClockReference the external clock reference to set
525      */
526     public void setExternalClockReference(final String externalClockReference) {
527         this.externalClockReference = externalClockReference;
528     }
529 
530     /** Getter for the analysis center ID.
531      * @return the analysis center ID
532      */
533     public String getAnalysisCenterID() {
534         return analysisCenterID;
535     }
536 
537     /** Setter for the analysis center ID.
538      * @param analysisCenterID the analysis center ID to set
539      */
540     public void setAnalysisCenterID(final String analysisCenterID) {
541         this.analysisCenterID = analysisCenterID;
542     }
543 
544     /** Getter for the analysis center name.
545      * @return the analysis center name
546      */
547     public String getAnalysisCenterName() {
548         return analysisCenterName;
549     }
550 
551     /** Setter for the analysis center name.
552      * @param analysisCenterName the analysis center name to set
553      */
554     public void setAnalysisCenterName(final String analysisCenterName) {
555         this.analysisCenterName = analysisCenterName;
556     }
557 
558     /** Getter for the reference clocks.
559      * @return the time span map of the different refence clocks
560      */
561     public TimeSpanMap<List<ReferenceClock>> getReferenceClocks() {
562         return referenceClocks;
563     }
564 
565     /** Add a list of reference clocks wich will be used after a specified date.
566      * If the reference map has not been already created, it will be.
567      * @param referenceClockList the reference clock list
568      * @param startDate the date the list will be valid after.
569      */
570     public void addReferenceClockList(final List<ReferenceClock> referenceClockList,
571                                       final AbsoluteDate startDate) {
572         if (referenceClocks == null) {
573             referenceClocks = new TimeSpanMap<List<ReferenceClock>>(referenceClockList);
574         }
575         referenceClocks.addValidAfter(referenceClockList, startDate);
576     }
577 
578     /** Getter for the frame name.
579      * @return the frame name
580      */
581     public String getFrameName() {
582         return frameName;
583     }
584 
585 
586     /** Setter for the frame name.
587      * @param frameName the frame name to set
588      */
589     public void setFrameName(final String frameName) {
590         this.frameName = frameName;
591     }
592 
593 
594     /** Getter for the receivers.
595      * @return the list of the receivers
596      */
597     public List<Receiver> getReceivers() {
598         return Collections.unmodifiableList(receivers);
599     }
600 
601     /** Getter for the satellites.
602      * @return the list of the satellites
603      */
604     public List<String> getSatellites() {
605         return Collections.unmodifiableList(satellites);
606     }
607 
608     /** Get the reference frame for the station positions.
609      * @return the reference frame for station positions
610      */
611     public Frame getFrame() {
612         return frameBuilder.apply(frameName);
613     }
614 
615 
616     /** Getter for an unmodifiable map of clock data.
617      * @return the clock data
618      */
619     public Map<String, List<ClockDataLine>> getClockData() {
620         return Collections.unmodifiableMap(clockData);
621     }
622 
623 
624     /** Add a clock data line to a specified receiver/satellite.
625      * @param id the satellite system to add observation type
626      * @param clockDataLine the clock data line to add
627      */
628     public void addClockData(final String id,
629                              final ClockDataLine clockDataLine) {
630         clockData.putIfAbsent(id, new ArrayList<ClockDataLine>());
631         clockData.get(id).add(clockDataLine);
632     }
633 
634     /** Clock data for a single station.
635      * <p> Data epoch is not linked to any time system in order to pars files with missing lines.
636      * Though, the default version of the getEpoch() method links the data time components with the clock file object time scale.
637      * The latter can be set with a default value (UTC). Caution is recommanded.
638      */
639     public class ClockDataLine {
640 
641         /** Clock data type. */
642         private ClockDataType dataType;
643 
644         /** Receiver/Satellite name. */
645         private String name;
646 
647         /** Epoch date components. */
648         private DateComponents dateComponents;
649 
650         /** Epoch time components. */
651         private TimeComponents timeComponents;
652 
653         /** Number of data values to follow.
654          * This number might not represent the non zero values in the line.
655          */
656         private int numberOfValues;
657 
658         /** Clock bias (seconds). */
659         private double clockBias;
660 
661         /** Clock bias sigma (seconds). */
662         private double clockBiasSigma;
663 
664         /** Clock rate (dimensionless). */
665         private double clockRate;
666 
667         /** Clock rate sigma (dimensionless). */
668         private double clockRateSigma;
669 
670         /** Clock acceleration (seconds^-1). */
671         private double clockAcceleration;
672 
673         /** Clock acceleration sigma (seconds^-1). */
674         private double clockAccelrerationSigma;
675 
676         /** Constructor.
677          * @param type the clock data type
678          * @param name the receiver/satellite name
679          * @param dateComponents the epoch date components
680          * @param timeComponents the epoch time components
681          * @param numberOfValues the number of values to follow
682          * @param clockBias the clock bias in seconds
683          * @param clockBiasSigma the clock bias sigma in seconds
684          * @param clockRate the clock rate
685          * @param clockRateSigma the clock rate sigma
686          * @param clockAcceleration the clock acceleration in seconds^-1
687          * @param clockAccelerationSigma the clock acceleration in seconds^-1
688          */
689         public ClockDataLine (final ClockDataType type, final String name,
690                               final DateComponents dateComponents,
691                               final TimeComponents timeComponents,
692                               final int numberOfValues,
693                               final double clockBias, final double clockBiasSigma,
694                               final double clockRate, final double clockRateSigma,
695                               final double clockAcceleration, final double clockAccelerationSigma) {
696 
697             this.dataType                = type;
698             this.name                    = name;
699             this.dateComponents          = dateComponents;
700             this.timeComponents          = timeComponents;
701             this.numberOfValues          = numberOfValues;
702             this.clockBias               = clockBias;
703             this.clockBiasSigma          = clockBiasSigma;
704             this.clockRate               = clockRate;
705             this.clockRateSigma          = clockRateSigma;
706             this.clockAcceleration       = clockAcceleration;
707             this.clockAccelrerationSigma = clockAccelerationSigma;
708         }
709 
710         /** Getter for the clock data type.
711          * @return the clock data type
712          */
713         public ClockDataType getDataType() {
714             return dataType;
715         }
716 
717         /** Getter for the receiver/satellite name.
718          * @return the receiver/satellite name
719          */
720         public String getName() {
721             return name;
722         }
723 
724         /** Getter for the number of values to follow.
725          * @return the number of values to follow
726          */
727         public int getNumberOfValues() {
728             return numberOfValues;
729         }
730 
731         /** Get data line epoch.
732          * This method should be used if Time System ID line is present in the clock file.
733          * If it is missing, UTC time scale will be applied.
734          * To specify tim scale, use {@link #getEpoch(TimeScale) getEpoch(TimeScale)} method.
735          * @return the data line epoch
736          */
737         public AbsoluteDate getEpoch() {
738             return new AbsoluteDate(dateComponents, timeComponents, timeScale);
739         }
740 
741         /** Get data line epoch.
742          * This method should be used in case Time System ID line is missing.
743          * Otherwise, it is adviced to rather use {@link #getEpoch() getEpoch()} method.
744          * @param epochTimeScale the time scale in which the epoch is defined
745          * @return the data line epoch set in the specified time scale
746          */
747         public AbsoluteDate getEpoch(final TimeScale epochTimeScale) {
748             return new AbsoluteDate(dateComponents, timeComponents, epochTimeScale);
749         }
750 
751         /** Getter for the clock bias.
752          * @return the clock bias in seconds
753          */
754         public double getClockBias() {
755             return clockBias;
756         }
757 
758         /** Getter for the clock bias sigma.
759          * @return the clock bias sigma in seconds
760          */
761         public double getClockBiasSigma() {
762             return clockBiasSigma;
763         }
764 
765         /** Getter for the clock rate.
766          * @return the clock rate
767          */
768         public double getClockRate() {
769             return clockRate;
770         }
771 
772         /** Getter for the clock rate sigma.
773          * @return the clock rate sigma
774          */
775         public double getClockRateSigma() {
776             return clockRateSigma;
777         }
778 
779         /** Getter for the clock acceleration.
780          * @return the clock acceleration in seconds^-1
781          */
782         public double getClockAcceleration() {
783             return clockAcceleration;
784         }
785 
786         /** Getter for the clock acceleration sigma.
787          * @return the clock acceleration sigma in seconds^-1
788          */
789         public double getClockAccelerationSigma() {
790             return clockAccelrerationSigma;
791         }
792 
793     }
794 
795     /** Represents a reference clock with its validity time span. */
796     public static class ReferenceClock {
797 
798         /** Receiver/satellite embedding the reference clock name. */
799         private String referenceName;
800 
801         /** Clock ID. */
802         private String clockID;
803 
804         /** A priori clock constraint (in seconds). */
805         private double clockConstraint;
806 
807         /** Start date of the validity period. */
808         private AbsoluteDate startDate;
809 
810         /** End date of the validity period. */
811         private AbsoluteDate endDate;
812 
813         /** Constructor.
814          * @param referenceName the name of the receiver/satellite embedding the reference clock
815          * @param clockID the clock ID
816          * @param clockConstraint the a priori clock constraint
817          * @param startDate the validity period start date
818          * @param endDate the validity period end date
819          */
820         public ReferenceClock (final String referenceName, final String clockID, final double clockConstraint,
821                                final AbsoluteDate startDate, final AbsoluteDate endDate) {
822             this.referenceName   = referenceName;
823             this.clockID         = clockID;
824             this.clockConstraint = clockConstraint;
825             this.startDate       = startDate;
826             this.endDate         = endDate;
827         }
828 
829         /** Getter for the name of the receiver/satellite embedding the reference clock.
830          * @return the name of the receiver/satellite embedding the reference clock
831          */
832         public String getReferenceName() {
833             return referenceName;
834         }
835 
836         /** Getter for the clock ID.
837          * @return the clock ID
838          */
839         public String getClockID() {
840             return clockID;
841         }
842 
843         /** Getter for the clock constraint.
844          * @return the clock constraint
845          */
846         public double getClockConstraint() {
847             return clockConstraint;
848         }
849 
850         /** Getter for the validity period start date.
851          * @return the validity period start date
852          */
853         public AbsoluteDate getStartDate() {
854             return startDate;
855         }
856 
857         /** Getter for the validity period end date.
858          * @return the validity period end date
859          */
860         public AbsoluteDate getEndDate() {
861             return endDate;
862         }
863 
864     }
865 
866     /** Represents a receiver or a satellite with its position in the considered frame. */
867     public static class Receiver {
868 
869         /** Designator. */
870         private String designator;
871 
872         /** Receiver identifier. */
873         private String receiverIdentifier;
874 
875         /** X coordinates in file considered Earth centered frame (in meters). */
876         private double x;
877 
878         /** Y coordinates in file considered Earth centered frame (in meters). */
879         private double y;
880 
881         /** Z coordinates in file considered Earth centered frame (in meters). */
882         private double z;
883 
884         /** Constructor.
885          * @param designator the designator
886          * @param receiverIdentifier the receiver identifier
887          * @param x the X coordinate in meters in considered Earth centered frame
888          * @param y the Y coordinate in meters in considered Earth centered frame
889          * @param z the Z coordinate in meters in considered Earth centered frame
890          */
891         public Receiver(final String designator, final String receiverIdentifier,
892                         final double x, final double y, final double z) {
893             this.designator         = designator;
894             this.receiverIdentifier = receiverIdentifier;
895             this.x                  = x;
896             this.y                  = y;
897             this.z                  = z;
898         }
899 
900         /** Getter for the designator.
901          * @return the designator
902          */
903         public String getDesignator() {
904             return designator;
905         }
906 
907         /** Getter for the receiver identifier.
908          * @return the receiver identifier
909          */
910         public String getReceiverIdentifier() {
911             return receiverIdentifier;
912         }
913 
914         /** Getter for the X coordinate in meters in considered Earth centered frame.
915          * @return  the X coordinate in meters in considered Earth centered frame
916          */
917         public double getX() {
918             return x;
919         }
920 
921         /** Getter for the Y coordinate in meters in considered Earth centered frame.
922          * @return  the Y coordinate in meters in considered Earth centered frame
923          */
924         public double getY() {
925             return y;
926         }
927 
928         /** Getter for the Z coordinate in meters in considered Earth centered frame.
929          * @return  the Z coordinate in meters in considered Earth centered frame
930          */
931         public double getZ() {
932             return z;
933         }
934     }
935 
936     /** Clock data type.
937      * In case of a DR type, clock data are in the sense of clock value after discontinuity minus prior.
938      * In other cases, clock data are in the sense of reported station/satellite clock minus reference clock value. */
939     public enum ClockDataType {
940 
941         /** Data analysis for receiver clocks. Clock Data are*/
942         AR("AR"),
943 
944         /** Data analysis for satellite clocks. */
945         AS("AS"),
946 
947         /** Calibration measurement for a single GPS receiver. */
948         CR("CR"),
949 
950         /** Discontinuity measurements for a single GPS receiver. */
951         DR("DR"),
952 
953         /** Monitor measurements for the broadcast satellite clocks. */
954         MS("MS");
955 
956         /** Parsing map. */
957         private static final Map<String, ClockDataType> KEYS_MAP = new HashMap<>();
958         static {
959             for (final ClockDataType timeSystem : values()) {
960                 KEYS_MAP.put(timeSystem.getKey(), timeSystem);
961             }
962         }
963 
964         /** Key for the system. */
965         private final String key;
966 
967         /** Simple constructor.
968          * @param key key letter
969          */
970         ClockDataType(final String key) {
971             this.key = key;
972         }
973 
974         /** Get the key for the system.
975          * @return key for the system
976          */
977         public String getKey() {
978             return key;
979         }
980 
981         /** Parse a string to get the time system.
982          * <p>
983          * The string must be the time system.
984          * </p>
985          * @param s string to parse
986          * @return the time system
987          * @exception OrekitIllegalArgumentException if the string does not correspond to a time system key
988          */
989         public static ClockDataType parseClockDataType(final String s)
990             throws OrekitIllegalArgumentException {
991             final ClockDataType clockDataType = KEYS_MAP.get(s);
992             if (clockDataType == null) {
993                 throw new OrekitIllegalArgumentException(OrekitMessages.UNKNOWN_CLOCK_DATA_TYPE, s);
994             }
995             return clockDataType;
996         }
997     }
998 }