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  
18  package org.orekit.files.ccsds.ndm.tdm;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.TreeMap;
24  
25  import org.orekit.errors.OrekitException;
26  import org.orekit.errors.OrekitMessages;
27  import org.orekit.files.ccsds.definitions.FrameFacade;
28  import org.orekit.files.ccsds.section.Metadata;
29  import org.orekit.frames.Frame;
30  import org.orekit.time.AbsoluteDate;
31  import org.orekit.utils.Constants;
32  
33  /** The TDMMetadata class gathers the meta-data present in the Tracking Data Message (TDM).<p>
34   *  References:<p>
35   *  <a href="https://public.ccsds.org/Pubs/503x0b1c1.pdf">CCSDS 503.0-B-1 recommended standard</a>. §3.3 ("Tracking Data Message", Blue Book, Version 1.0, November 2007).
36   *
37   * @author Maxime Journot
38   * @since 9.0
39   */
40  public class TdmMetadata extends Metadata {
41  
42      /** Identifier for the tracking data. */
43      private String trackId;
44  
45      /** List of data types in the data section. */
46      private List<ObservationType> dataTypes;
47  
48      /** Start epoch of total time span covered by observations block. */
49      private AbsoluteDate startTime;
50  
51      /** End epoch of total time span covered by observations block. */
52      private AbsoluteDate stopTime;
53  
54      /** Map of participants in the tracking data session (minimum 1 and up to 5).<p>
55       *  Participants may include ground stations, spacecraft, and/or quasars.<p>
56       *  Participants represent the classical transmitting parties, transponding parties, and receiving parties.
57       */
58      private Map<Integer, String> participants;
59  
60      /** Tracking mode. */
61      private TrackingMode mode;
62  
63      /** The path shall reflect the signal path by listing the index of each participant
64       *  in order, separated by commas, with no inserted white space.<p>
65       *  The integers 1, 2, 3, 4, 5 used to specify the signal path correlate
66       *  with the indices of the PARTICIPANT keywords.<p>
67       *  The first entry in the PATH shall be the transmit participant.<p>
68       *  The non-indexed ‘PATH’ keyword shall be used if the MODE is ‘SEQUENTIAL’.<p>
69       *  The indexed ‘PATH_1’ and ‘PATH_2’ keywords shall be used where the MODE is ‘SINGLE_DIFF’.
70       */
71      private int[] path;
72  
73      /** Path 1 (see above). */
74      private int[] path1;
75  
76      /** Path 2 (see above). */
77      private int[] path2;
78  
79      /** Map of external ephemeris names for participants (minimum 1 and up to 5). */
80      private Map<Integer, String> ephemerisNames;
81  
82      /** Frequency band for transmitted frequencies. */
83      private String transmitBand;
84  
85      /** Frequency band for received frequencies. */
86      private String receiveBand;
87  
88      /** Turn-around ratio numerator.<p>
89       *  Numerator of the turn-around ratio that is necessary to calculate the coherent downlink from the uplink frequency.
90       */
91      private int turnaroundNumerator;
92  
93      /** Turn-around ratio denominator .*/
94      private int turnaroundDenominator;
95  
96      /** Timetag reference.<p>
97       *  Provides a reference for time tags in the tracking data.<p>
98       *  It indicates whether the timetag associated with the data is the transmit time or the receive time.
99       */
100     private TimetagReference timetagRef;
101 
102     /** Integration interval. <p>
103      *  Provides the Doppler count time in seconds for Doppler data or for the creation
104      *  of normal points.
105      */
106     private double integrationInterval;
107 
108     /** Integration reference.<p>
109      *  Used in conjunction with timetag reference and integration interval.<p>
110      *  Indicates whether the timetag represents the start, middle or end of the integration interval.
111      */
112     private IntegrationReference integrationRef;
113 
114     /** Frequency offset.<p>
115      *  A frequency in Hz that must be added to every RECEIVE_FREQ to reconstruct it.
116      */
117     private double freqOffset;
118 
119     /** Range mode. */
120     private RangeMode rangeMode;
121 
122     /** Raw range modulus (in RangeUnits). */
123     private double rawRangeModulus;
124 
125     /** Range units. */
126     private RangeUnits rangeUnits;
127 
128     /** Angle type. */
129     private AngleType angleType;
130 
131     /** Reference frame in which data are given: used in combination with ANGLE_TYPE=RADEC. */
132     private FrameFacade referenceFrame;
133 
134     /** The interpolation method to be used. */
135     private String interpolationMethod;
136 
137     /** The interpolation degree. */
138     private int interpolationDegree;
139 
140     /** Bias that was added to Doppler count in the data section. */
141     private double doppplerCountBias;
142 
143     /** Scaled by which Doppler count was multiplied in the data section. */
144     private double dopplerCountScale;
145 
146     /** Indicator for occurred rollover in Doppler count. */
147     private boolean doppplerCountRollover;
148 
149     /** Transmit delays map.<p>
150      *  Specifies a fixed interval of time, in seconds, for the signal to travel from the transmitting
151      *  electronics to the transmit point. Each item in the list corresponds to the each participants.
152      */
153     private Map<Integer, Double> transmitDelays;
154 
155     /** Receive delays list.<p>
156      *  Specifies a fixed interval of time, in seconds, for the signal to travel from the tracking
157      *  point to the receiving electronics. Each item in the list corresponds to the each participants.
158      */
159     private Map<Integer, Double> receiveDelays;
160 
161     /** Data quality. */
162     private DataQuality dataQuality;
163 
164     /** Correction angle 1.<p>
165      *  Angle correction that has been added or should be added to the ANGLE_1 data.
166      */
167     private double correctionAngle1;
168 
169     /** Correction angle 2.<p>
170      *  Angle correction that has been added or should be added to the ANGLE_2 data.
171      */
172     private double correctionAngle2;
173 
174     /** Correction Doppler.<p>
175      *  Doppler correction that has been added or should be added to the DOPPLER data.
176      */
177     private double correctionDoppler;
178 
179     /** Correction magnitude.<p>
180      *  Magnitude correction that has been added or should be added to the MAGNITUDE data.
181      */
182     private double correctionMagnitude;
183 
184     /** Raw correction Range in {@link #getRangeUnits()}.<p>
185      *  Range correction that has been added or should be added to the RANGE data.
186      */
187     private double rawCorrectionRange;
188 
189     /** Correction radar cross section.<p>
190      *  Radar cross section correction that has been added or should be added to the RCS data.
191      */
192     private double correctionRcs;
193 
194     /** Correction receive.<p>
195      *  Receive correction that has been added or should be added to the RECEIVE data.
196      */
197     private double correctionReceive;
198 
199     /** Correction transmit.<p>
200      *  Transmit correction that has been added or should be added to the TRANSMIT data.
201      */
202     private double correctionTransmit;
203 
204     /** Yearly aberration correction.<p>
205      *  Yearly correction that has been added or should be added to the ANGLE data.
206      */
207     private double correctionAberrationYearly;
208 
209     /** Diurnal aberration correction.<p>
210      *  Diurnl correction that has been added or should be added to the ANGLE data.
211      */
212     private double correctionAberrationDiurnal;
213 
214     /** Correction applied ? YES/NO<p>
215      *  Indicate whethers or not the values associated with the CORRECTION_* keywords have been
216      *  applied to the tracking data.
217      */
218     private CorrectionApplied correctionsApplied;
219 
220     /** Create a new TDM meta-data.
221      */
222     public TdmMetadata() {
223         super(null);
224         participants          = new TreeMap<>();
225         ephemerisNames        = new TreeMap<>();
226         doppplerCountBias     = Double.NaN;
227         dopplerCountScale     = 1;
228         doppplerCountRollover = false;
229         transmitDelays        = new TreeMap<>();
230         receiveDelays         = new TreeMap<>();
231     }
232 
233     /** {@inheritDoc} */
234     @Override
235     public void validate(final double version) {
236         super.validate(version);
237         if (participants.isEmpty()) {
238             throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, TdmMetadataKey.PARTICIPANT_1);
239         }
240     }
241 
242     /** Getter for the tracking data identifier.
243      * @return tracking data identifier
244      */
245     public String getTrackId() {
246         return trackId;
247     }
248 
249     /** Setter for the tracking data identifier.
250      * @param trackId tracking data identifier
251      */
252     public void setTrackId(final String trackId) {
253         refuseFurtherComments();
254         this.trackId = trackId;
255     }
256 
257     /** Getter for the data types in the data section.
258      * @return data types in the data section
259      */
260     public List<ObservationType> getDataTypes() {
261         return dataTypes;
262     }
263 
264     /** Setter for the data types in the data section.
265      * @param dataTypes data types in the data section
266      */
267     public void setDataTypes(final List<ObservationType> dataTypes) {
268         refuseFurtherComments();
269         this.dataTypes = new ArrayList<>();
270         this.dataTypes.addAll(dataTypes);
271     }
272 
273     /** Getter for the startTime.
274      * @return the startTime
275      */
276     public AbsoluteDate getStartTime() {
277         return startTime;
278     }
279 
280     /** Setter for the startTime.
281      * @param startTime the startTime to set
282      */
283     public void setStartTime(final AbsoluteDate startTime) {
284         refuseFurtherComments();
285         this.startTime = startTime;
286     }
287 
288     /** Getter for the stopTime.
289      * @return the stopTime
290      */
291     public AbsoluteDate getStopTime() {
292         return stopTime;
293     }
294 
295     /** Setter for the stopTime.
296      * @param stopTime the stopTime to set
297      */
298     public void setStopTime(final AbsoluteDate stopTime) {
299         refuseFurtherComments();
300         this.stopTime = stopTime;
301     }
302 
303     /** Getter for the participants.
304      * @return the participants
305      */
306     public Map<Integer, String> getParticipants() {
307         return participants;
308     }
309 
310     /** Setter for the participants.
311      * @param participants the participants to set
312      */
313     public void setParticipants(final Map<Integer, String> participants) {
314         refuseFurtherComments();
315         this.participants = new TreeMap<>();
316         this.participants.putAll(participants);
317     }
318 
319     /** Adds a participant to the list.
320      * @param participantNumber the number of the participant to add
321      * @param participant the name of the participant to add
322      */
323     public void addParticipant(final int participantNumber, final String participant) {
324         refuseFurtherComments();
325         this.participants.put(participantNumber, participant);
326     }
327 
328     /** Getter for the mode.
329      * @return the mode
330      */
331     public TrackingMode getMode() {
332         return mode;
333     }
334 
335     /** Setter for the mode.
336      * @param mode the mode to set
337      */
338     public void setMode(final TrackingMode mode) {
339         refuseFurtherComments();
340         this.mode = mode;
341     }
342 
343     /** Getter for the path.
344      * @return the path
345      */
346     public int[] getPath() {
347         return safeCopy(path);
348     }
349 
350     /** Setter for the path.
351      * @param path the path to set
352      */
353     public void setPath(final int[] path) {
354         refuseFurtherComments();
355         this.path = safeCopy(path);
356     }
357 
358     /** Getter for the path1.
359      * @return the path1
360      */
361     public int[] getPath1() {
362         return safeCopy(path1);
363     }
364 
365     /** Setter for the path1.
366      * @param path1 the path1 to set
367      */
368     public void setPath1(final int[] path1) {
369         refuseFurtherComments();
370         this.path1 = safeCopy(path1);
371     }
372 
373     /** Getter for the path2.
374      * @return the path2
375      */
376     public int[] getPath2() {
377         return safeCopy(path2);
378     }
379 
380     /** Setter for the path2.
381      * @param path2 the path2 to set
382      */
383     public void setPath2(final int[] path2) {
384         refuseFurtherComments();
385         this.path2 = safeCopy(path2);
386     }
387 
388     /** Getter for external ephemeris names for participants.
389      * @return external ephemeris names for participants
390      */
391     public Map<Integer, String> getEphemerisNames() {
392         return ephemerisNames;
393     }
394 
395     /** Setter for the external ephemeris names for participants.
396      * @param ephemerisNames external ephemeris names for participants
397      */
398     public void setEphemerisNames(final Map<Integer, String> ephemerisNames) {
399         refuseFurtherComments();
400         this.ephemerisNames = new TreeMap<>();
401         this.ephemerisNames.putAll(ephemerisNames);
402     }
403 
404     /** Adds an ephemeris name to the list.
405      * @param participantNumber the number of the participant
406      * @param ephemerisName name of the ephemeris for the participant
407      */
408     public void addEphemerisName(final int participantNumber, final String ephemerisName) {
409         refuseFurtherComments();
410         this.ephemerisNames.put(participantNumber, ephemerisName);
411     }
412 
413     /** Getter for the transmitBand.
414      * @return the transmitBand
415      */
416     public String getTransmitBand() {
417         return transmitBand;
418     }
419 
420     /** Setter for the transmitBand.
421      * @param transmitBand the transmitBand to set
422      */
423     public void setTransmitBand(final String transmitBand) {
424         refuseFurtherComments();
425         this.transmitBand = transmitBand;
426     }
427 
428     /** Getter for the receiveBand.
429      * @return the receiveBand
430      */
431     public String getReceiveBand() {
432         return receiveBand;
433     }
434 
435     /** Setter for the receiveBand.
436      * @param receiveBand the receiveBand to set
437      */
438     public void setReceiveBand(final String receiveBand) {
439         refuseFurtherComments();
440         this.receiveBand = receiveBand;
441     }
442 
443     /** Getter for the turnaroundNumerator.
444      * @return the turnaroundNumerator
445      */
446     public int getTurnaroundNumerator() {
447         return turnaroundNumerator;
448     }
449 
450     /** Setter for the turnaroundNumerator.
451      * @param turnaroundNumerator the turnaroundNumerator to set
452      */
453     public void setTurnaroundNumerator(final int turnaroundNumerator) {
454         refuseFurtherComments();
455         this.turnaroundNumerator = turnaroundNumerator;
456     }
457 
458     /** Getter for the turnaroundDenominator.
459      * @return the turnaroundDenominator
460      */
461     public int getTurnaroundDenominator() {
462         return turnaroundDenominator;
463     }
464 
465     /** Setter for the turnaroundDenominator.
466      * @param turnaroundDenominator the turnaroundDenominator to set
467      */
468     public void setTurnaroundDenominator(final int turnaroundDenominator) {
469         refuseFurtherComments();
470         this.turnaroundDenominator = turnaroundDenominator;
471     }
472 
473     /** Getter for the timetagRef.
474      * @return the timetagRef
475      */
476     public TimetagReference getTimetagRef() {
477         return timetagRef;
478     }
479 
480     /** Setter for the timetagRef.
481      * @param timetagRef the timetagRef to set
482      */
483     public void setTimetagRef(final TimetagReference timetagRef) {
484         refuseFurtherComments();
485         this.timetagRef = timetagRef;
486     }
487 
488     /** Getter for the integrationInterval.
489      * @return the integrationInterval
490      */
491     public double getIntegrationInterval() {
492         return integrationInterval;
493     }
494 
495     /** Setter for the integrationInterval.
496      * @param integrationInterval the integrationInterval to set
497      */
498     public void setIntegrationInterval(final double integrationInterval) {
499         refuseFurtherComments();
500         this.integrationInterval = integrationInterval;
501     }
502 
503     /** Getter for the integrationRef.
504      * @return the integrationRef
505      */
506     public IntegrationReference getIntegrationRef() {
507         return integrationRef;
508     }
509 
510     /** Setter for the integrationRef.
511      * @param integrationRef the integrationRef to set
512      */
513     public void setIntegrationRef(final IntegrationReference integrationRef) {
514         refuseFurtherComments();
515         this.integrationRef = integrationRef;
516     }
517 
518     /** Getter for the freqOffset.
519      * @return the freqOffset
520      */
521     public double getFreqOffset() {
522         return freqOffset;
523     }
524 
525     /** Setter for the freqOffset.
526      * @param freqOffset the freqOffset to set
527      */
528     public void setFreqOffset(final double freqOffset) {
529         refuseFurtherComments();
530         this.freqOffset = freqOffset;
531     }
532 
533     /** Getter for the rangeMode.
534      * @return the rangeMode
535      */
536     public RangeMode getRangeMode() {
537         return rangeMode;
538     }
539 
540     /** Setter for the rangeMode.
541      * @param rangeMode the rangeMode to set
542      */
543     public void setRangeMode(final RangeMode rangeMode) {
544         refuseFurtherComments();
545         this.rangeMode = rangeMode;
546     }
547 
548     /** Getter for the range modulus in meters.
549      * @param converter converter to use if {@link #getRangeUnits() range units}
550      * are set to {@link RangeUnits#RU}
551      * @return the range modulus in meters
552      */
553     public double getRangeModulus(final RangeUnitsConverter converter) {
554         if (rangeUnits == RangeUnits.km) {
555             return rawRangeModulus * 1000;
556         } else if (rangeUnits == RangeUnits.s) {
557             return rawRangeModulus * Constants.SPEED_OF_LIGHT;
558         } else {
559             return converter.ruToMeters(this, startTime, rawRangeModulus);
560         }
561     }
562 
563     /** Getter for the raw range modulus.
564      * @return the raw range modulus in range units
565      */
566     public double getRawRangeModulus() {
567         return rawRangeModulus;
568     }
569 
570     /** Setter for the raw range modulus.
571      * @param rawRangeModulus the raw range modulus to set
572      */
573     public void setRawRangeModulus(final double rawRangeModulus) {
574         refuseFurtherComments();
575         this.rawRangeModulus = rawRangeModulus;
576     }
577 
578     /** Getter for the rangeUnits.
579      * @return the rangeUnits
580      */
581     public RangeUnits getRangeUnits() {
582         return rangeUnits;
583     }
584 
585     /** Setter for the rangeUnits.
586      * @param rangeUnits the rangeUnits to set
587      */
588     public void setRangeUnits(final RangeUnits rangeUnits) {
589         refuseFurtherComments();
590         this.rangeUnits = rangeUnits;
591     }
592 
593     /** Getter for angleType.
594      * @return the angleType
595      */
596     public AngleType getAngleType() {
597         return angleType;
598     }
599 
600     /** Setter for the angleType.
601      * @param angleType the angleType to set
602      */
603     public void setAngleType(final AngleType angleType) {
604         refuseFurtherComments();
605         this.angleType = angleType;
606     }
607 
608     /** Get the the value of {@code REFERENCE_FRAME} as an Orekit {@link Frame}.
609      * @return The reference frame specified by the {@code REFERENCE_FRAME} keyword.
610      */
611     public FrameFacade getReferenceFrame() {
612         return referenceFrame;
613     }
614 
615     /** Set the reference frame in which data are given: used for RADEC tracking data.
616      * @param referenceFrame the reference frame to be set
617      */
618     public void setReferenceFrame(final FrameFacade referenceFrame) {
619         refuseFurtherComments();
620         this.referenceFrame = referenceFrame;
621     }
622 
623     /**
624      * Get the interpolation method to be used.
625      *
626      * @return the interpolation method
627      */
628     public String getInterpolationMethod() {
629         return interpolationMethod;
630     }
631 
632     /**
633      * Set the interpolation method to be used.
634      * @param interpolationMethod the interpolation method to be set
635      */
636     public void setInterpolationMethod(final String interpolationMethod) {
637         refuseFurtherComments();
638         this.interpolationMethod = interpolationMethod;
639     }
640 
641     /**
642      * Get the interpolation degree.
643      * @return the interpolation degree
644      */
645     public int getInterpolationDegree() {
646         return interpolationDegree;
647     }
648 
649     /**
650      * Set the interpolation degree.
651      * @param interpolationDegree the interpolation degree to be set
652      */
653     public void setInterpolationDegree(final int interpolationDegree) {
654         refuseFurtherComments();
655         this.interpolationDegree = interpolationDegree;
656     }
657 
658     /**
659      * Get the Doppler count bias.
660      * @return the Doppler count bias in Hz
661      */
662     public double getDopplerCountBias() {
663         return doppplerCountBias;
664     }
665 
666     /**
667      * Set the Doppler count bias.
668      * @param dopplerCountBias Doppler count bias in Hz to set
669      */
670     public void setDopplerCountBias(final double dopplerCountBias) {
671         refuseFurtherComments();
672         this.doppplerCountBias = dopplerCountBias;
673     }
674 
675     /**
676      * Get the Doppler count scale.
677      * @return the Doppler count scale
678      */
679     public double getDopplerCountScale() {
680         return dopplerCountScale;
681     }
682 
683     /**
684      * Set the Doppler count Scale.
685      * @param dopplerCountScale Doppler count scale to set
686      */
687     public void setDopplerCountScale(final double dopplerCountScale) {
688         refuseFurtherComments();
689         this.dopplerCountScale = dopplerCountScale;
690     }
691 
692     /**
693      * Check if there is a Doppler count rollover.
694      * @return true if there is a Doppler count rollover
695      */
696     public boolean hasDopplerCountRollover() {
697         return doppplerCountRollover;
698     }
699 
700     /**
701      * Set the indicator for Doppler count rollover.
702      * @param dopplerCountRollover indicator for Doppler count rollover
703      */
704     public void setDopplerCountRollover(final boolean dopplerCountRollover) {
705         refuseFurtherComments();
706         this.doppplerCountRollover = dopplerCountRollover;
707     }
708 
709     /** Getter for the transmitDelays.
710      * @return the transmitDelays
711      */
712     public Map<Integer, Double> getTransmitDelays() {
713         return transmitDelays;
714     }
715 
716     /** Setter for the transmitDelays.
717      * @param transmitDelays the transmitDelays to set
718      */
719     public void setTransmitDelays(final Map<Integer, Double> transmitDelays) {
720         refuseFurtherComments();
721         this.transmitDelays = new TreeMap<>();
722         this.transmitDelays.putAll(transmitDelays);
723     }
724 
725     /** Adds a transmit delay to the list.
726      *  @param participantNumber the number of the participants for which the transmit delay is given
727      *  @param transmitDelay the transmit delay value to add
728      */
729     public void addTransmitDelay(final int participantNumber, final double transmitDelay) {
730         refuseFurtherComments();
731         this.transmitDelays.put(participantNumber, transmitDelay);
732     }
733 
734     /** Getter for receiveDelays.
735      * @return the receiveDelays
736      */
737     public Map<Integer, Double> getReceiveDelays() {
738         return receiveDelays;
739     }
740 
741     /** Setter for the receiveDelays.
742      * @param receiveDelays the receiveDelays to set
743      */
744     public void setReceiveDelays(final Map<Integer, Double> receiveDelays) {
745         refuseFurtherComments();
746         this.receiveDelays = new TreeMap<>();
747         this.receiveDelays.putAll(receiveDelays);
748     }
749 
750     /** Adds a receive delay to the list.
751      * @param participantNumber the number of the participants for which the receive delay is given
752      * @param receiveDelay the receive delay value to add
753      */
754     public void addReceiveDelay(final int participantNumber, final double receiveDelay) {
755         refuseFurtherComments();
756         this.receiveDelays.put(participantNumber, receiveDelay);
757     }
758     /** Getter for the dataQuality.
759      * @return the dataQuality
760      */
761     public DataQuality getDataQuality() {
762         return dataQuality;
763     }
764 
765     /** Setter for the dataQuality.
766      * @param dataQuality the dataQuality to set
767      */
768     public void setDataQuality(final DataQuality dataQuality) {
769         refuseFurtherComments();
770         this.dataQuality = dataQuality;
771     }
772 
773     /** Getter for the correctionAngle1.
774      * @return the correctionAngle1 (in radians)
775      */
776     public double getCorrectionAngle1() {
777         return correctionAngle1;
778     }
779 
780     /** Setter for the correctionAngle1.
781      * @param correctionAngle1 the correctionAngle1 to set (in radians)
782      */
783     public void setCorrectionAngle1(final double correctionAngle1) {
784         refuseFurtherComments();
785         this.correctionAngle1 = correctionAngle1;
786     }
787 
788     /** Getter for the correctionAngle2.
789      * @return the correctionAngle2 (in radians)
790      */
791     public double getCorrectionAngle2() {
792         return correctionAngle2;
793     }
794 
795     /** Setter for the correctionAngle2.
796      * @param correctionAngle2 the correctionAngle2 to set (in radians)
797      */
798     public void setCorrectionAngle2(final double correctionAngle2) {
799         refuseFurtherComments();
800         this.correctionAngle2 = correctionAngle2;
801     }
802 
803     /** Getter for the correctionDoppler.
804      * @return the correctionDoppler (in m/s)
805      */
806     public double getCorrectionDoppler() {
807         return correctionDoppler;
808     }
809 
810     /** Setter for the correctionDoppler.
811      * @param correctionDoppler the correctionDoppler to set (in m/s)
812      */
813     public void setCorrectionDoppler(final double correctionDoppler) {
814         refuseFurtherComments();
815         this.correctionDoppler = correctionDoppler;
816     }
817 
818     /** Getter for the magnitude correction.
819      * @return the magnitude correction
820      */
821     public double getCorrectionMagnitude() {
822         return correctionMagnitude;
823     }
824 
825     /** Setter for the magnitude correction.
826      * @param correctionMagnitude the magnitude correction to set
827      */
828     public void setCorrectionMagnitude(final double correctionMagnitude) {
829         refuseFurtherComments();
830         this.correctionMagnitude = correctionMagnitude;
831     }
832 
833     /** Getter for the raw correction for range in meters.
834      * @param converter converter to use if {@link #getRangeUnits() range units}
835      * are set to {@link RangeUnits#RU}
836      * @return the raw correction for range in meters
837      */
838     public double getCorrectionRange(final RangeUnitsConverter converter) {
839         if (rangeUnits == RangeUnits.km) {
840             return rawCorrectionRange * 1000;
841         } else if (rangeUnits == RangeUnits.s) {
842             return rawCorrectionRange * Constants.SPEED_OF_LIGHT;
843         } else {
844             return converter.ruToMeters(this, startTime, rawCorrectionRange);
845         }
846     }
847 
848     /** Getter for the raw correction for range.
849      * @return the raw correction for range (in {@link #getRangeUnits()})
850      */
851     public double getRawCorrectionRange() {
852         return rawCorrectionRange;
853     }
854 
855     /** Setter for the raw correction for range.
856      * @param rawCorrectionRange the raw correction for range to set (in {@link #getRangeUnits()})
857      */
858     public void setRawCorrectionRange(final double rawCorrectionRange) {
859         refuseFurtherComments();
860         this.rawCorrectionRange = rawCorrectionRange;
861     }
862 
863     /** Getter for the radar cross section correction.
864      * @return the radar cross section correction in m²
865      */
866     public double getCorrectionRcs() {
867         return correctionRcs;
868     }
869 
870     /** Setter for the radar cross section correction.
871      * @param correctionRcs the radar cross section correction in m² to set
872      */
873     public void setCorrectionRcs(final double correctionRcs) {
874         refuseFurtherComments();
875         this.correctionRcs = correctionRcs;
876     }
877 
878     /** Getter for the yearly aberration correction.
879      * @return the yearly aberration correction in radians
880      */
881     public double getCorrectionAberrationYearly() {
882         return correctionAberrationYearly;
883     }
884 
885     /** Setter for the yearly aberration correction.
886      * @param correctionAberrationYearly the yearly aberration correction in radians to set
887      */
888     public void setCorrectionAberrationYearly(final double correctionAberrationYearly) {
889         refuseFurtherComments();
890         this.correctionAberrationYearly = correctionAberrationYearly;
891     }
892 
893     /** Getter for the diurnal aberration correction.
894      * @return the diurnal aberration correction in radians
895      */
896     public double getCorrectionAberrationDiurnal() {
897         return correctionAberrationDiurnal;
898     }
899 
900     /** Setter for the diurnal aberration correction.
901      * @param correctionAberrationDiurnal the diurnal aberration correction in radians to set
902      */
903     public void setCorrectionAberrationDiurnal(final double correctionAberrationDiurnal) {
904         refuseFurtherComments();
905         this.correctionAberrationDiurnal = correctionAberrationDiurnal;
906     }
907 
908     /** Getter for the correctionReceive.
909      * @return the correctionReceive (in TDM units, without conversion)
910      */
911     public double getCorrectionReceive() {
912         return correctionReceive;
913     }
914 
915     /** Setter for the correctionReceive.
916      * @param correctionReceive the correctionReceive to set (in TDM units, without conversion)
917      */
918     public void setCorrectionReceive(final double correctionReceive) {
919         refuseFurtherComments();
920         this.correctionReceive = correctionReceive;
921     }
922 
923     /** Getter for the correctionTransmit.
924      * @return the correctionTransmit (in TDM units, without conversion)
925      */
926     public double getCorrectionTransmit() {
927         return correctionTransmit;
928     }
929 
930     /** Setter for the correctionTransmit.
931      * @param correctionTransmit the correctionTransmit to set (in TDM units, without conversion)
932      */
933     public void setCorrectionTransmit(final double correctionTransmit) {
934         refuseFurtherComments();
935         this.correctionTransmit = correctionTransmit;
936     }
937 
938     /** Getter for the correctionApplied.
939      * @return the correctionApplied (in TDM units, without conversion)
940      */
941     public CorrectionApplied getCorrectionsApplied() {
942         return correctionsApplied;
943     }
944 
945     /** Setter for the correctionApplied.
946      * @param correctionsApplied the correctionApplied to set (in TDM units, without conversion)
947      */
948     public void setCorrectionsApplied(final CorrectionApplied correctionsApplied) {
949         refuseFurtherComments();
950         this.correctionsApplied = correctionsApplied;
951     }
952 
953     /** Safe copy of an integer array.
954      * @param original original array
955      * @return copy of the array
956      */
957     private int[] safeCopy(final int[] original) {
958         return original == null ? null : original.clone();
959     }
960 
961 }