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