1   /* Copyright 2002-2017 CS Systèmes d'Information
2    * Licensed to CS Systèmes d'Information (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.files.ccsds;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.net.URISyntaxException;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.junit.Assert;
26  import org.junit.Before;
27  import org.junit.Test;
28  import org.orekit.Utils;
29  import org.orekit.errors.OrekitException;
30  import org.orekit.errors.OrekitMessages;
31  import org.orekit.files.ccsds.TDMParser.TDMFileFormat;
32  import org.orekit.frames.FramesFactory;
33  import org.orekit.time.AbsoluteDate;
34  import org.orekit.time.TimeScale;
35  import org.orekit.time.TimeScalesFactory;
36  
37  /**
38   * Test class for CCSDS Tracking Data Message parsing.<p>
39   * Examples are taken from Annexe D of
40   * <a href="https://public.ccsds.org/Pubs/503x0b1c1.pdf">CCSDS 503.0-B-1 recommended standard [1]</a> ("Tracking Data Message", Blue Book, Version 1.0, November 2007).<p>
41   * Both KeyValue and XML formats are tested here on equivalent files.
42   * @author mjournot
43   *
44   */
45  public class TDMParserTest {
46  
47      @Before
48      public void setUp()
49                      throws Exception {
50          Utils.setDataRoot("regular-data");
51      }
52  
53      @Test
54      public void testParseTdmKeyValueExample2() throws OrekitException, IOException {
55          // Example 2 of [1]
56          // See Figure D-2: TDM Example: One-Way Data w/Frequency Offset
57          // Data lines number was cut down to 7
58          final String ex = "/ccsds/TDMExample2.txt";
59          final InputStream inEntry = getClass().getResourceAsStream(ex);
60          final TDMParser parser = new TDMParser().withFileFormat(TDMParser.TDMFileFormat.KEYVALUE);
61          final TDMFile file = parser.parse(inEntry, ex);
62          validateTDMExample2(file);
63      }
64  
65      @Test
66      public void testParseTdmKeyValueExample4() throws OrekitException, IOException {
67  
68          // Example 4 of [1]
69          // See Figure D-4: TDM Example: Two-Way Ranging Data Only
70          // Data lines number was cut down to 20
71          final String ex = "/ccsds/TDMExample4.txt";
72          final InputStream inEntry = getClass().getResourceAsStream(ex);
73          final TDMParser parser = new TDMParser();
74          final TDMFile file = parser.parseKeyValue(inEntry, ex);
75          validateTDMExample4(file);
76      }
77  
78      @Test
79      public void testParseTdmKeyValueExample6() throws OrekitException, IOException {
80  
81          // Example 6 of [1]
82          // See Figure D-6: TDM Example: Four-Way Data
83          // Data lines number was cut down to 16
84          final String ex = "/ccsds/TDMExample6.txt";
85          final InputStream inEntry = getClass().getResourceAsStream(ex);
86          final TDMParser parser = new TDMParser();
87          final TDMFile file = parser.parse(inEntry, ex);
88          validateTDMExample6(file);
89      }
90  
91      @Test
92      public void testParseTdmKeyValueExample8() throws OrekitException, IOException {
93  
94          // Example 8 of [1]
95          // See Figure D-8: TDM Example: Angles, Range, Doppler Combined in Single TDM
96          // Data lines number was cut down to 18
97          final String ex = "/ccsds/TDMExample8.txt";
98          final InputStream inEntry = getClass().getResourceAsStream(ex);
99          final TDMParser parser = new TDMParser();
100         final TDMFile file = parser.parse(inEntry, ex);
101         validateTDMExample8(file);
102     }
103 
104     @Test
105     public void testParseTdmKeyValueExample15() throws OrekitException, IOException {
106 
107         // Example 15 of [1]
108         // See Figure D-15: TDM Example: Clock Bias/Drift Only
109         final String ex = "/ccsds/TDMExample15.txt";
110         final InputStream inEntry = getClass().getResourceAsStream(ex);
111         final TDMParser parser = new TDMParser();
112         final TDMFile file = parser.parse(inEntry, ex);
113         validateTDMExample15(file);
114     }
115 
116     @Test
117     public void testParseTdmKeyValueExampleAllKeywords() throws OrekitException, IOException {
118 
119         // Testing all TDM keywords
120         final String ex = "/ccsds/TDMExampleAllKeywords.txt";
121         final InputStream inEntry = getClass().getResourceAsStream(ex);
122         final TDMParser parser = new TDMParser();
123         final TDMFile file = parser.parse(inEntry, ex);
124         validateTDMExampleAllKeywords(file);
125     }
126 
127     @Test
128     public void testParseTdmXmlExample2() throws OrekitException, IOException {
129 
130         // Example 2 of [1]
131         // See Figure D-2: TDM Example: One-Way Data w/Frequency Offset
132         // Data lines number was cut down to 7
133         final String ex = "/ccsds/XML/TDMExample2.xml";
134         final InputStream inEntry = getClass().getResourceAsStream(ex);
135         final TDMParser parser = new TDMParser().withFileFormat(TDMParser.TDMFileFormat.XML);
136         final TDMFile file = parser.parse(inEntry, ex);
137         validateTDMExample2(file);
138     }
139 
140     @Test
141     public void testParseTdmXmlExample4() throws OrekitException, IOException {
142 
143         // Example 4 of [1]
144         // See Figure D-4: TDM Example: Two-Way Ranging Data Only
145         // Data lines number was cut down to 20
146         final String ex = "/ccsds/XML/TDMExample4.xml";
147         final InputStream inEntry = getClass().getResourceAsStream(ex);
148         final TDMParser parser = new TDMParser();
149         final TDMFile file = parser.parseXml(inEntry, ex);
150         validateTDMExample4(file);
151     }
152 
153     @Test
154     public void testParseTdmXmlExample6() throws OrekitException, IOException {
155 
156         // Example 6 of [1]
157         // See Figure D-6: TDM Example: Four-Way Data
158         // Data lines number was cut down to 16
159         final String ex = "/ccsds/XML/TDMExample6.xml";
160         final InputStream inEntry = getClass().getResourceAsStream(ex);
161         final TDMParser parser = new TDMParser();
162         final TDMFile file = parser.parse(inEntry, ex);
163         validateTDMExample6(file);
164     }
165 
166     @Test
167     public void testParseTdmXmlExample8() throws OrekitException, IOException {
168 
169         // Example 8 of [1]
170         // See Figure D-8: TDM Example: Angles, Range, Doppler Combined in Single TDM
171         // Data lines number was cut down to 18
172         final String ex = "/ccsds/XML/TDMExample8.xml";
173         final InputStream inEntry = getClass().getResourceAsStream(ex);
174         final TDMParser parser = new TDMParser();
175         final TDMFile file = parser.parse(inEntry, ex);
176         validateTDMExample8(file);
177     }
178 
179     @Test
180     public void testParseTdmXmlExample15() throws OrekitException, IOException {
181 
182         // Example 15 of [1]
183         // See Figure D-15: TDM Example: Clock Bias/Drift Only
184         final String ex = "/ccsds/XML/TDMExample15.xml";
185         final InputStream inEntry = getClass().getResourceAsStream(ex);
186         final TDMParser parser = new TDMParser();
187         final TDMFile file = parser.parse(inEntry, ex);
188         validateTDMExample15(file);
189     }
190 
191     @Test
192     public void testParseTdmXmlExampleAllKeywords() throws OrekitException, IOException {
193 
194         // Testing all TDM keywords
195         final String ex = "/ccsds/XML/TDMExampleAllKeywords.xml";
196         final InputStream inEntry = getClass().getResourceAsStream(ex);
197         final TDMParser parser = new TDMParser();
198         final TDMFile file = parser.parse(inEntry, ex);
199         validateTDMExampleAllKeywords(file);
200     }
201 
202     @Test
203     public void testDataNumberFormatErrorTypeKeyValue() {
204         try {
205             // Number format exception in data part
206             final String ex = "/ccsds/TDM-data-number-format-error.txt";
207             final InputStream inEntry = getClass().getResourceAsStream(ex);
208             final TDMParser parser = new TDMParser();
209             parser.parse(inEntry, ex);
210             Assert.fail("An Orekit Exception \"UNABLE_TO_PARSE_LINE_IN_FILE\" should have been thrown");
211         } catch (OrekitException oe) {
212             Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
213             Assert.assertEquals(26, oe.getParts()[0]);
214             Assert.assertEquals("/ccsds/TDM-data-number-format-error.txt", oe.getParts()[1]);
215             Assert.assertEquals(String.format("\t%s","RECEIVE_FREQ_1 = 2005-159T17:41:03 this-is-not-a-number"), oe.getParts()[2]);
216         }
217     }
218 
219     @Test
220     public void testDataNumberFormatErrorTypeXml() {
221         try {
222             // Number format exception in data part
223             final String ex = "/ccsds/XML/TDM-data-number-format-error.xml";
224             final InputStream inEntry = getClass().getResourceAsStream(ex);
225             final TDMParser parser = new TDMParser();
226             parser.parse(inEntry, ex);
227             Assert.fail("An Orekit Exception \"UNABLE_TO_PARSE_LINE_IN_FILE\" should have been thrown");
228         } catch (OrekitException oe) {
229             String specifier = String.format("%s\n%s",
230                                              "unable to parse line 47 of file /ccsds/XML/TDM-data-number-format-error.xml:",
231                                              "<RECEIVE_FREQ_1>this-is-not-a-number</RECEIVE_FREQ_1>");
232             Assert.assertEquals(specifier,oe.getMessage());
233         }
234     }
235 
236     @Test
237     public void testMetaDataNumberFormatErrorTypeKeyValue() {
238         try {
239             // Number format exception in metadata part
240             final String ex = "/ccsds/TDM-metadata-number-format-error.txt";
241             final InputStream inEntry = getClass().getResourceAsStream(ex);
242             final TDMParser parser = new TDMParser();
243             parser.parse(inEntry, ex);
244             Assert.fail("An Orekit Exception \"UNABLE_TO_PARSE_LINE_IN_FILE\" should have been thrown");
245         } catch (OrekitException oe) {
246             Assert.assertEquals(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, oe.getSpecifier());
247             Assert.assertEquals(17, oe.getParts()[0]);
248             Assert.assertEquals("/ccsds/TDM-metadata-number-format-error.txt", oe.getParts()[1]);
249             Assert.assertEquals(String.format("\t%s","TRANSMIT_DELAY_1 = this-is-not-a-number"), oe.getParts()[2]);
250         }
251     }
252 
253     @Test
254     public void testMetaDataNumberFormatErrorTypeXml() {
255         try {
256             // Number format exception in metadata part
257             final String ex = "/ccsds/XML/TDM-metadata-number-format-error.xml";
258             final InputStream inEntry = getClass().getResourceAsStream(ex);
259             final TDMParser parser = new TDMParser();
260             parser.parse(inEntry, ex);
261             Assert.fail("An Orekit Exception \"UNABLE_TO_PARSE_LINE_IN_FILE\" should have been thrown");
262         } catch (OrekitException oe) {
263             String specifier = String.format("%s\n%s",
264                                              "unable to parse line 26 of file /ccsds/XML/TDM-metadata-number-format-error.xml:",
265                                              "<TRANSMIT_DELAY_1>this-is-not-a-number</TRANSMIT_DELAY_1>");
266             Assert.assertEquals(specifier,oe.getMessage());
267         }
268     }
269 
270     @Test
271     public void testNonExistentFile() throws URISyntaxException {
272         // Try parsing a file that does not exist
273         final String realName = getClass().getResource("/ccsds/OEMExample2.txt").toURI().getPath();
274         final String wrongName = realName + "xxxxx";
275         try {
276             new TDMParser().parse(wrongName);
277             Assert.fail("An Orekit Exception \"UNABLE_TO_FIND_FILE\" should have been thrown");
278         } catch (OrekitException oe) {
279             Assert.assertEquals(OrekitMessages.UNABLE_TO_FIND_FILE, oe.getSpecifier());
280             Assert.assertEquals(wrongName, oe.getParts()[0]);
281         }
282     }
283 
284     @Test
285     public void testInconsistentTimeSystemsKeyValue() {
286         // Inconsistent time systems between two sets of data
287         try {
288             new TDMParser().withFileFormat(TDMFileFormat.KEYVALUE).parse(getClass().getResourceAsStream("/ccsds/TDM-inconsistent-time-systems.txt"));
289             Assert.fail("An Orekit Exception \"CCSDS_TDM_INCONSISTENT_TIME_SYSTEMS\" should have been thrown");
290         } catch (OrekitException oe) {
291             Assert.assertEquals(OrekitMessages.CCSDS_TDM_INCONSISTENT_TIME_SYSTEMS, oe.getSpecifier());
292             Assert.assertEquals(CcsdsTimeScale.UTC, oe.getParts()[0]);
293             Assert.assertEquals(CcsdsTimeScale.TCG, oe.getParts()[1]);
294         }
295     }
296 
297     @Test
298     public void testInconsistentTimeSystemsXml() {
299         // Inconsistent time systems between two sets of data
300         try {
301             new TDMParser().withFileFormat(TDMFileFormat.XML).parse(getClass().getResourceAsStream("/ccsds/XML/TDM-inconsistent-time-systems.xml"));
302             Assert.fail("An Orekit Exception \"CCSDS_TDM_INCONSISTENT_TIME_SYSTEMS\" should have been thrown");
303         } catch (OrekitException oe) {
304             Assert.assertEquals(OrekitMessages.CCSDS_TDM_INCONSISTENT_TIME_SYSTEMS, oe.getSpecifier());
305             Assert.assertEquals(CcsdsTimeScale.UTC, oe.getParts()[0]);
306             Assert.assertEquals(CcsdsTimeScale.TCG, oe.getParts()[1]);
307         }
308     }
309 
310     @Test
311     public void testWrongDataKeywordKeyValue()
312                     throws OrekitException, URISyntaxException {
313         // Unknown CCSDS keyword was read in data part
314         final String ex = "/ccsds/TDM-data-wrong-keyword.txt";
315         final InputStream inEntry = getClass().getResourceAsStream(ex);
316         try {
317             new TDMParser().parse(inEntry, ex);
318             Assert.fail("An exception \"CCSDS_UNEXPECTED_KEYWORD\"should have been thrown");
319         } catch (OrekitException oe) {
320             Assert.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
321             Assert.assertEquals(26, oe.getParts()[0]);
322             Assert.assertEquals("%s","/ccsds/TDM-data-wrong-keyword.txt", oe.getParts()[1]);
323             Assert.assertEquals(String.format("\t%s","WRONG_KEYWORD  = 2005-159T17:41:03 -294.9673"), oe.getParts()[2]);
324         }
325     }
326 
327     @Test
328     public void testWrongDataKeywordXml()
329                     throws OrekitException, URISyntaxException {
330         // Unknown CCSDS keyword was read in data part
331         final String ex = "/ccsds/XML/TDM-data-wrong-keyword.xml";
332         final InputStream inEntry = getClass().getResourceAsStream(ex);
333         try {
334             new TDMParser().parse(inEntry, ex);
335             Assert.fail("An exception \"CCSDS_UNEXPECTED_KEYWORD\"should have been thrown");
336         } catch (OrekitException oe) {
337             String specifier = String.format("%s\n%s",
338                                              "unexpected keyword in CCSDS line number 47 of file /ccsds/XML/TDM-data-wrong-keyword.xml:",
339                                              "<WRONG_KEYWORD>");
340             Assert.assertEquals(specifier,oe.getMessage());
341         }
342     }
343 
344     @Test
345     public void testWrongMetaDataKeywordKeyValue()
346                     throws OrekitException, URISyntaxException {
347         // Unknown CCSDS keyword was read in data part
348         final String ex = "/ccsds/TDM-metadata-wrong-keyword.txt";
349         final InputStream inEntry = getClass().getResourceAsStream(ex);
350         try {
351             new TDMParser().parse(inEntry, ex);
352             Assert.fail("An exception \"CCSDS_UNEXPECTED_KEYWORD\"should have been thrown");
353         } catch (OrekitException oe) {
354             Assert.assertEquals(OrekitMessages.CCSDS_UNEXPECTED_KEYWORD, oe.getSpecifier());
355             Assert.assertEquals(16, oe.getParts()[0]);
356             Assert.assertEquals("/ccsds/TDM-metadata-wrong-keyword.txt", oe.getParts()[1]);
357             Assert.assertEquals(String.format("\t%s", "WRONG_KEYWORD = 32021035200.0"), oe.getParts()[2]);
358         }
359     }
360 
361     @Test
362     public void testWrongMetaDataKeywordXml()
363                     throws OrekitException, URISyntaxException {
364         // Unknown CCSDS keyword was read in data part
365         final String ex = "/ccsds/XML/TDM-metadata-wrong-keyword.xml";
366         final InputStream inEntry = getClass().getResourceAsStream(ex);
367         try {
368             new TDMParser().parse(inEntry, ex);
369             Assert.fail("An exception \"CCSDS_UNEXPECTED_KEYWORD\"should have been thrown");
370         } catch (OrekitException oe) {
371             String specifier = String.format("%s\n%s",
372                                              "unexpected keyword in CCSDS line number 15 of file /ccsds/XML/TDM-metadata-wrong-keyword.xml:",
373                                              "<WRONG_KEYWORD>");
374             Assert.assertEquals(specifier,oe.getMessage());
375         }
376     }
377 
378     @Test
379     public void testWrongTimeSystemKeyValue() {
380         // Time system not implemented CCSDS keyword was read in data part
381         final String ex = "/ccsds/TDM-metadata-timesystem-not-implemented.txt";
382         final InputStream inEntry = getClass().getResourceAsStream(ex);
383         try {
384             new TDMParser().parse(inEntry, ex);
385             Assert.fail("An exception \"CCSDS_TIME_SYSTEM_NOT_IMPLEMENTED\"should have been thrown");
386         } catch (OrekitException oe) {
387             Assert.assertEquals(OrekitMessages.CCSDS_TIME_SYSTEM_NOT_IMPLEMENTED, oe.getSpecifier());
388             Assert.assertEquals("WRONG-TIME-SYSTEM", oe.getParts()[0]);
389         }
390     }
391 
392     @Test
393     public void testWrongTimeSystemXml() {
394         // Time system not implemented CCSDS keyword was read in data part
395         final String ex = "/ccsds/XML/TDM-metadata-timesystem-not-implemented.xml";
396         final InputStream inEntry = getClass().getResourceAsStream(ex);
397         try {
398             new TDMParser().parse(inEntry, ex);
399             Assert.fail("An exception \"CCSDS_TIME_SYSTEM_NOT_IMPLEMENTED\"should have been thrown");
400         } catch (OrekitException oe) {
401             String specifier = "use of time system WRONG-TIME-SYSTEM in CCSDS files requires an additional ICD and is not implemented in Orekit";
402             Assert.assertEquals(specifier,oe.getMessage());
403         }
404     }
405 
406     @Test
407     public void testInconsistentDataLineKeyValue() {
408         // Inconsistent data line in KeyValue file (3 fields after keyword instead of 2)
409         final String ex = "/ccsds/TDM-data-inconsistent-line.txt";
410         final InputStream inEntry = getClass().getResourceAsStream(ex);
411         try {
412             new TDMParser().parse(inEntry, ex);
413             Assert.fail("An exception \"CCSDS_TDM_INCONSISTENT_DATA_LINE\"should have been thrown");
414         } catch (OrekitException oe) {
415             Assert.assertEquals(OrekitMessages.CCSDS_TDM_INCONSISTENT_DATA_LINE, oe.getSpecifier());
416             Assert.assertEquals(25, oe.getParts()[0]);
417             Assert.assertEquals("/ccsds/TDM-data-inconsistent-line.txt", oe.getParts()[1]);
418             Assert.assertEquals("RECEIVE_FREQ_1 = 2005-159T17:41:02 -333.0551 this-should-not-be-here", oe.getParts()[2]);
419         }
420     }
421 
422     @Test
423     public void testInconsistentDataBlockXml() {
424         // Inconsistent data block in XML file
425         final String ex = "/ccsds/XML/TDM-data-inconsistent-block.xml";
426         final InputStream inEntry = getClass().getResourceAsStream(ex);
427         try {
428             new TDMParser().parse(inEntry, ex);
429             Assert.fail("An exception \"CCSDS_TDM_XML_INCONSISTENT_DATA_BLOCK\"should have been thrown");
430         } catch (OrekitException oe) {
431             String specifier = String.format("%s\n%s\n\t%s\n\t\t%s\n\t\t%s\n\t%s",
432                                              "Inconsistent XML observation block at line 33 of TDM file /ccsds/XML/TDM-data-inconsistent-block.xml.",
433                                              "A TDM observation block should be as follows",
434                                              "<observation>","<EPOCH>epoch</EPOCH>","<KEYWORD>value</KEYWORD>","</observation>");
435             Assert.assertEquals(specifier,oe.getMessage());
436         }
437     }
438 
439     @Test
440     public void testUnknownFileFormat() {
441         // Unknown file format
442         final String ex = "/ccsds/TDM-unknown-file-format.unknown";
443         final InputStream inEntry = getClass().getResourceAsStream(ex);
444         try {
445             new TDMParser().parse(inEntry, ex);
446             Assert.fail("An exception \"CCSDS_TDM_UNKNOWN_FORMAT\"should have been thrown");
447         } catch (OrekitException oe) {
448             Assert.assertEquals(OrekitMessages.CCSDS_TDM_UNKNOWN_FORMAT, oe.getSpecifier());
449             Assert.assertEquals("/ccsds/TDM-unknown-file-format.unknown", oe.getParts()[0]);
450         }
451     }
452 
453     /**
454      * Validation function for example 2.
455      * @param file Parsed TDMFile to validate
456      * @throws OrekitException if UTC time scale cannot be retrieved
457      */
458     public static void validateTDMExample2(TDMFile file) throws OrekitException {
459         final TimeScale utc = TimeScalesFactory.getUTC();
460 
461         // Header
462         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
463         Assert.assertEquals(new AbsoluteDate("2005-160T20:15:00", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
464         Assert.assertEquals("NASA/JPL",file.getOriginator());
465         final List<String> headerComment = new ArrayList<String>();
466         headerComment.add("TDM example created by yyyyy-nnnA Nav Team (NASA/JPL)");
467         headerComment.add("StarTrek 1-way data, Ka band down");
468         Assert.assertEquals(headerComment, file.getHeaderComment());
469 
470         // Meta-Data
471         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
472 
473         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
474         Assert.assertEquals(new AbsoluteDate("2005-159T17:41:00", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
475         Assert.assertEquals(new AbsoluteDate("2005-159T17:41:40", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
476         Assert.assertEquals("DSS-25", metaData.getParticipants().get(1));
477         Assert.assertEquals("YYYY-NNNA", metaData.getParticipants().get(2));
478         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
479         Assert.assertEquals("2,1", metaData.getPath());
480         Assert.assertEquals(1.0, metaData.getIntegrationInterval(), 0.0);
481         Assert.assertEquals("MIDDLE", metaData.getIntegrationRef());
482         Assert.assertEquals(32021035200.0, metaData.getFreqOffset(), 0.0);
483         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(1), 0.0);
484         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(1), 0.0);
485         Assert.assertEquals("RAW", metaData.getDataQuality());
486         final List<String> metaDataComment = new ArrayList<String>();
487         metaDataComment.add("This is a meta-data comment");
488         Assert.assertEquals(metaDataComment, metaData.getComment());
489 
490         // Data
491         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
492 
493         // Reference data
494         final String[] keywords = {"TRANSMIT_FREQ_2", "RECEIVE_FREQ_1", "RECEIVE_FREQ_1", "RECEIVE_FREQ_1",
495             "RECEIVE_FREQ_1", "RECEIVE_FREQ_1", "RECEIVE_FREQ_1"};
496 
497         final String[] epochs   = {"2005-159T17:41:00", "2005-159T17:41:00", "2005-159T17:41:01", "2005-159T17:41:02",
498             "2005-159T17:41:03", "2005-159T17:41:04", "2005-159T17:41:05"};
499 
500         final double[] values   = {32023442781.733, -409.2735, -371.1568, -333.0551,
501             -294.9673, -256.9054, -218.7951};
502         // Check consistency
503         for (int i = 0; i < keywords.length; i++) {
504             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
505             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
506             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
507         }
508 
509         // Comment
510         final List<String> dataComment = new ArrayList<String>();
511         dataComment.add("This is a data comment");
512         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
513     }
514 
515     /**
516      * Validation function for example 4.
517      * @param file Parsed TDMFile to validate
518      * @throws OrekitException if UTC time scale cannot be retrieved
519      */
520     public static void validateTDMExample4(TDMFile file) throws OrekitException {
521 
522         final TimeScale utc = TimeScalesFactory.getUTC();
523 
524         // Header
525         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
526         Assert.assertEquals(new AbsoluteDate("2005-191T23:00:00", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
527         Assert.assertEquals("NASA/JPL",file.getOriginator());
528         final List<String> headerComment = new ArrayList<String>();
529         headerComment.add("TDM example created by yyyyy-nnnA Nav Team (NASA/JPL)");
530         Assert.assertEquals(headerComment, file.getHeaderComment());
531 
532         // Meta-Data
533         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
534 
535         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
536         Assert.assertEquals("DSS-24", metaData.getParticipants().get(1));
537         Assert.assertEquals("YYYY-NNNA", metaData.getParticipants().get(2));
538         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
539         Assert.assertEquals("1,2,1", metaData.getPath());
540         Assert.assertEquals("START", metaData.getIntegrationRef());
541         Assert.assertEquals("COHERENT", metaData.getRangeMode());
542         Assert.assertEquals(2.0e+26, metaData.getRangeModulus(), 0.0);
543         Assert.assertEquals("RU", metaData.getRangeUnits());
544         Assert.assertEquals(7.7e-5, metaData.getTransmitDelays().get(1), 0.0);
545         Assert.assertEquals(0.0, metaData.getTransmitDelays().get(2), 0.0);
546         Assert.assertEquals(7.7e-5, metaData.getReceiveDelays().get(1), 0.0);
547         Assert.assertEquals(0.0, metaData.getReceiveDelays().get(2), 0.0);
548         Assert.assertEquals(46.7741, metaData.getCorrectionRange(), 0.0);
549         Assert.assertEquals("YES", metaData.getCorrectionsApplied());
550         final List<String> metaDataComment = new ArrayList<String>();
551         metaDataComment.add("Range correction applied is range calibration to DSS-24.");
552         metaDataComment.add("Estimated RTLT at begin of pass = 950 seconds");
553         metaDataComment.add("Antenna Z-height correction 0.0545 km applied to uplink signal");
554         metaDataComment.add("Antenna Z-height correction 0.0189 km applied to downlink signal");
555         Assert.assertEquals(metaDataComment, metaData.getComment());
556 
557         // Data
558         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
559 
560         // Reference data
561         final String[] keywords = {"TRANSMIT_FREQ_1", "TRANSMIT_FREQ_RATE_1", "RANGE", "PR_N0",
562             "TRANSMIT_FREQ_1", "TRANSMIT_FREQ_RATE_1", "RANGE", "PR_N0",
563             "TRANSMIT_FREQ_1", "TRANSMIT_FREQ_RATE_1", "RANGE", "PR_N0",
564             "TRANSMIT_FREQ_1", "TRANSMIT_FREQ_RATE_1", "RANGE", "PR_N0"};
565 
566         final String[] epochs   = {"2005-191T00:31:51", "2005-191T00:31:51", "2005-191T00:31:51", "2005-191T00:31:51",
567             "2005-191T00:34:48", "2005-191T00:34:48", "2005-191T00:34:48", "2005-191T00:34:48",
568             "2005-191T00:37:45", "2005-191T00:37:45", "2005-191T00:37:45", "2005-191T00:37:45",
569             "2005-191T00:40:42", "2005-191T00:40:42", "2005-191T00:40:42", "2005-191T00:40:42",
570             "2005-191T00:58:24", "2005-191T00:58:24", "2005-191T00:58:24", "2005-191T00:58:24"};
571 
572         final double[] values   = {7180064367.3536 , 0.59299, 39242998.5151986, 28.52538,
573             7180064472.3146 , 0.59305, 61172265.3115234, 28.39347,
574             7180064577.2756 , 0.59299, 15998108.8168328, 28.16193,
575             7180064682.2366 , 0.59299, 37938284.4138008, 29.44597,
576             7180065327.56141, 0.62085, 35478729.4012973, 30.48199};
577         // Check consistency
578         for (int i = 0; i < keywords.length; i++) {
579             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
580             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
581             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
582         }
583         // Comment
584         final List<String> dataComment = new ArrayList<String>();
585         dataComment.add("This is a data comment");
586         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
587     }
588 
589     /**
590      * Validation function for example 6.
591      * @param file Parsed TDMFile to validate
592      * @throws OrekitException if UTC time scale cannot be retrieved
593      */
594     public static void validateTDMExample6(TDMFile file) throws OrekitException {
595 
596         final TimeScale utc = TimeScalesFactory.getUTC();
597 
598         // Header
599         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
600         Assert.assertEquals(new AbsoluteDate("1998-06-10T01:00:00", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
601         Assert.assertEquals("JAXA",file.getOriginator());
602         final List<String> headerComment = new ArrayList<String>();
603         headerComment.add("TDM example created by yyyyy-nnnA Nav Team (JAXA)");
604         Assert.assertEquals(headerComment, file.getHeaderComment());
605 
606         // Meta-Data
607         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
608 
609         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
610         Assert.assertEquals(new AbsoluteDate("1998-06-10T00:57:37", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
611         Assert.assertEquals(new AbsoluteDate("1998-06-10T00:57:44", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
612         Assert.assertEquals("NORTH", metaData.getParticipants().get(1));
613         Assert.assertEquals("F07R07", metaData.getParticipants().get(2));
614         Assert.assertEquals("E7", metaData.getParticipants().get(3));
615         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
616         Assert.assertEquals("1,2,3,2,1", metaData.getPath());
617         Assert.assertEquals(1.0, metaData.getIntegrationInterval(), 0.0);
618         Assert.assertEquals("MIDDLE", metaData.getIntegrationRef());
619         Assert.assertEquals("CONSTANT", metaData.getRangeMode());
620         Assert.assertEquals(0.0, metaData.getRangeModulus(), 0.0);
621         Assert.assertEquals("KM", metaData.getRangeUnits());
622         Assert.assertEquals("AZEL", metaData.getAngleType());
623 
624         // Data
625         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
626 
627         // Reference data
628         final String[] keywords = {"RANGE", "ANGLE_1", "ANGLE_2", "TRANSMIT_FREQ_1", "RECEIVE_FREQ",
629             "RANGE", "ANGLE_1", "ANGLE_2", "TRANSMIT_FREQ_1", "RECEIVE_FREQ",
630             "RANGE", "ANGLE_1", "ANGLE_2", "TRANSMIT_FREQ_1", "RECEIVE_FREQ",
631             "RANGE", "ANGLE_1", "ANGLE_2", "TRANSMIT_FREQ_1", "RECEIVE_FREQ",};
632 
633         final String[] epochs   = {"1998-06-10T00:57:37", "1998-06-10T00:57:37", "1998-06-10T00:57:37", "1998-06-10T00:57:37", "1998-06-10T00:57:37",
634             "1998-06-10T00:57:38", "1998-06-10T00:57:38", "1998-06-10T00:57:38", "1998-06-10T00:57:38", "1998-06-10T00:57:38",
635             "1998-06-10T00:57:39", "1998-06-10T00:57:39", "1998-06-10T00:57:39", "1998-06-10T00:57:39", "1998-06-10T00:57:39",
636             "1998-06-10T00:57:44", "1998-06-10T00:57:44", "1998-06-10T00:57:44", "1998-06-10T00:57:44", "1998-06-10T00:57:44",};
637 
638         final double[] values   = { 80452.7542, 256.64002393, 13.38100016, 2106395199.07917, 2287487999.0,
639             80452.7368, 256.64002393, 13.38100016, 2106395199.07917, 2287487999.0,
640             80452.7197, 256.64002393, 13.38100016, 2106395199.07917, 2287487999.0,
641             80452.6331, 256.64002393, 13.38100016, 2106395199.07917, 2287487999.0};
642         // Check consistency
643         for (int i = 0; i < keywords.length; i++) {
644             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
645             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
646             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
647         }
648         // Comment
649         final List<String> dataComment = new ArrayList<String>();
650         dataComment.add("This is a data comment");
651         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
652     }
653 
654     /**
655      * Validation function for example 8.
656      * @param file Parsed TDMFile to validate
657      * @throws OrekitException if UTC time scale cannot be retrieved
658      */
659     public static void validateTDMExample8(TDMFile file) throws OrekitException {
660 
661         final TimeScale utc = TimeScalesFactory.getUTC();
662 
663         // Header
664         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
665         Assert.assertEquals(new AbsoluteDate("2007-08-30T12:01:44.749", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
666         Assert.assertEquals("GSOC",file.getOriginator());
667         final List<String> headerComment = new ArrayList<String>();
668         headerComment.add("GEOSCX_INP");
669         Assert.assertEquals(headerComment, file.getHeaderComment());
670 
671         // Meta-Data 1
672         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
673 
674         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
675         Assert.assertEquals(new AbsoluteDate("2007-08-29T07:00:02.000", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
676         Assert.assertEquals(new AbsoluteDate("2007-08-29T14:00:02.000", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
677         Assert.assertEquals("HBSTK", metaData.getParticipants().get(1));
678         Assert.assertEquals("SAT", metaData.getParticipants().get(2));
679         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
680         Assert.assertEquals("1,2,1", metaData.getPath());
681         Assert.assertEquals(1.0, metaData.getIntegrationInterval(), 0.0);
682         Assert.assertEquals("END", metaData.getIntegrationRef());
683         Assert.assertEquals("XSYE", metaData.getAngleType());
684         Assert.assertEquals("RAW", metaData.getDataQuality());
685         final List<String> metaDataComment = new ArrayList<String>();
686         metaDataComment.add("This is a meta-data comment");
687         Assert.assertEquals(metaDataComment, metaData.getComment());
688 
689         // Data 1
690         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
691 
692         // Reference data 1
693         final String[] keywords = {"DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2",
694             "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2",
695             "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2"};
696 
697         final String[] epochs   = {"2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000",
698             "2007-08-29T08:00:02.000", "2007-08-29T08:00:02.000", "2007-08-29T08:00:02.000",
699             "2007-08-29T14:00:02.000", "2007-08-29T14:00:02.000", "2007-08-29T14:00:02.000"};
700 
701         final double[] values   = {-1.498776048, 67.01312389, 18.28395556,
702             -2.201305217, 67.01982278, 21.19609167,
703             0.929545817, -89.35626083, 2.78791667};
704         // Check consistency
705         for (int i = 0; i < keywords.length; i++) {
706             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
707             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
708             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
709         }
710         // Comment
711         final List<String> dataComment = new ArrayList<String>();
712         dataComment.add("This is a data comment");
713         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
714 
715         // Meta-Data 2
716         final TDMFile.TDMMetaData metaData2 = file.getObservationsBlocks().get(1).getMetaData();
717 
718         Assert.assertEquals(CcsdsTimeScale.UTC, metaData2.getTimeSystem());
719         Assert.assertEquals("2007-08-29T06:00:02.000", metaData2.getStartTimeString());
720         Assert.assertEquals(new AbsoluteDate("2007-08-29T06:00:02.000", utc).durationFrom(metaData2.getStartTime()), 0.0, 0.0);
721         Assert.assertEquals("2007-08-29T13:00:02.000", metaData2.getStopTimeString());
722         Assert.assertEquals(new AbsoluteDate("2007-08-29T13:00:02.000", utc).durationFrom(metaData2.getStopTime()), 0.0, 0.0);
723         Assert.assertEquals("WHM1", metaData2.getParticipants().get(1));
724         Assert.assertEquals("SAT", metaData2.getParticipants().get(2));
725         Assert.assertEquals("SEQUENTIAL", metaData2.getMode());
726         Assert.assertEquals("1,2,1", metaData2.getPath());
727         Assert.assertEquals(1.0, metaData2.getIntegrationInterval(), 0.0);
728         Assert.assertEquals("END", metaData2.getIntegrationRef());
729         Assert.assertEquals("AZEL", metaData2.getAngleType());
730         Assert.assertEquals("RAW", metaData2.getDataQuality());
731         final List<String> metaDataComment2 = new ArrayList<String>();
732         metaDataComment2.add("This is a meta-data comment");
733         Assert.assertEquals(metaDataComment2, metaData2.getComment());
734 
735         // Data 2
736         final List<TDMFile.Observation> observations2 = file.getObservationsBlocks().get(1).getObservations();
737 
738         // Reference data 2
739         final String[] keywords2 = {"RANGE", "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2",
740             "RANGE", "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2",
741             "RANGE", "DOPPLER_INTEGRATED", "ANGLE_1", "ANGLE_2"};
742 
743         final String[] epochs2   = {"2007-08-29T06:00:02.000", "2007-08-29T06:00:02.000", "2007-08-29T06:00:02.000", "2007-08-29T06:00:02.000",
744             "2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000", "2007-08-29T07:00:02.000",
745             "2007-08-29T13:00:02.000", "2007-08-29T13:00:02.000", "2007-08-29T13:00:02.000", "2007-08-29T13:00:02.000"};
746 
747         final double[] values2   = {4.00165248953670E+04, -0.885640091,  99.53204250, 1.26724167,
748             3.57238793591890E+04, -1.510223139, 103.33061750, 4.77875278,
749             3.48156855860090E+04,  1.504082291, 243.73365222, 8.78254167};
750         // Check consistency
751         for (int i = 0; i < keywords2.length; i++) {
752             Assert.assertEquals(keywords2[i], observations2.get(i).getKeyword());
753             Assert.assertEquals(new AbsoluteDate(epochs2[i], utc).durationFrom(observations2.get(i).getEpoch()), 0.0, 0.0);
754             Assert.assertEquals(values2[i], observations2.get(i).getMeasurement(), 0.0);
755         }
756         // Comment
757         final List<String> dataComment2 = new ArrayList<String>();
758         dataComment2.add("This is a data comment");
759         Assert.assertEquals(dataComment2, file.getObservationsBlocks().get(1).getObservationsComment());
760     }
761 
762     /**
763      * Validation function for example 15.
764      * @param file Parsed TDMFile to validate
765      * @throws OrekitException if UTC time scale cannot be retrieved
766      */
767     public static void validateTDMExample15(TDMFile file) throws OrekitException {
768 
769         final TimeScale utc = TimeScalesFactory.getUTC();
770 
771         // Header
772         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
773         Assert.assertEquals(new AbsoluteDate("2005-161T15:45:00", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
774         Assert.assertEquals("NASA/JPL",file.getOriginator());
775         final List<String> headerComment = new ArrayList<String>();
776         headerComment.add("TDM example created by yyyyy-nnnA Nav Team (NASA/JPL)");
777         headerComment.add("The following are clock offsets, in seconds between the");
778         headerComment.add("clocks at each DSN complex relative to UTC(NIST). The offset");
779         headerComment.add("is a mean of readings using several GPS space vehicles in");
780         headerComment.add("common view. Value is \"station clock minus UTC”.");
781         Assert.assertEquals(headerComment, file.getHeaderComment());
782 
783         // Meta-Data 1
784         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
785 
786         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
787         Assert.assertEquals(new AbsoluteDate("2005-142T12:00:00", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
788         Assert.assertEquals(new AbsoluteDate("2005-145T12:00:00", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
789         Assert.assertEquals("DSS-10", metaData.getParticipants().get(1));
790         Assert.assertEquals("UTC-NIST", metaData.getParticipants().get(2));
791         final List<String> metaDataComment = new ArrayList<String>();
792         metaDataComment.add("Note: SPC10 switched back to Maser1 from Maser2 on 2005-142");
793         Assert.assertEquals(metaDataComment, metaData.getComment());
794 
795         // Data 1
796         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
797 
798         // Reference data 1
799         final String[] keywords = {"CLOCK_BIAS", "CLOCK_DRIFT",
800             "CLOCK_BIAS", "CLOCK_DRIFT",
801             "CLOCK_BIAS", "CLOCK_DRIFT",
802         "CLOCK_BIAS"};
803 
804         final String[] epochs   = {"2005-142T12:00:00", "2005-142T12:00:00",
805             "2005-143T12:00:00", "2005-143T12:00:00",
806             "2005-144T12:00:00", "2005-144T12:00:00",
807         "2005-145T12:00:00"};
808 
809         final double[] values   = {9.56e-7,  6.944e-14,
810             9.62e-7, -2.083e-13,
811             9.44e-7, -2.778e-13,
812             9.20e-7};
813         // Check consistency
814         for (int i = 0; i < keywords.length; i++) {
815             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
816             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
817             Assert.assertEquals(values[i], observations.get(i).getMeasurement(), 0.0);
818         }
819         // Comment
820         final List<String> dataComment = new ArrayList<String>();
821         dataComment.add("This is a data comment");
822         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
823 
824 
825         // Meta-Data 2
826         final TDMFile.TDMMetaData metaData2 = file.getObservationsBlocks().get(1).getMetaData();
827 
828         Assert.assertEquals(CcsdsTimeScale.UTC, metaData2.getTimeSystem());
829         Assert.assertEquals(new AbsoluteDate("2005-142T12:00:00", utc).durationFrom(metaData2.getStartTime()), 0.0, 0.0);
830         Assert.assertEquals(new AbsoluteDate("2005-145T12:00:00", utc).durationFrom(metaData2.getStopTime()), 0.0, 0.0);
831         Assert.assertEquals("DSS-40", metaData2.getParticipants().get(1));
832         Assert.assertEquals("UTC-NIST", metaData2.getParticipants().get(2));
833         final List<String> metaDataComment2 = new ArrayList<String>();
834         metaDataComment2.add("This is a meta-data comment");
835         Assert.assertEquals(metaDataComment2, metaData2.getComment());
836 
837         // Data 2
838         final List<TDMFile.Observation> observations2 = file.getObservationsBlocks().get(1).getObservations();
839 
840         // Reference data 2
841         // Same keywords and dates than 1
842         final double[] values2   = {-7.40e-7, -3.125e-13,
843             -7.67e-7, -1.620e-13,
844             -7.81e-7, -4.745e-13,
845             -8.22e-7};
846         // Check consistency
847         for (int i = 0; i < keywords.length; i++) {
848             Assert.assertEquals(keywords[i], observations2.get(i).getKeyword());
849             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations2.get(i).getEpoch()), 0.0, 0.0);
850             Assert.assertEquals(values2[i], observations2.get(i).getMeasurement(), 0.0);
851         }
852         // Comment
853         final List<String> dataComment2 = new ArrayList<String>();
854         dataComment2.add("This is a data comment");
855         Assert.assertEquals(dataComment2, file.getObservationsBlocks().get(1).getObservationsComment());
856 
857 
858         // Meta-Data 3
859         final TDMFile.TDMMetaData metaData3 = file.getObservationsBlocks().get(2).getMetaData();
860 
861         Assert.assertEquals(CcsdsTimeScale.UTC, metaData3.getTimeSystem());
862         Assert.assertEquals(new AbsoluteDate("2005-142T12:00:00", utc).durationFrom(metaData3.getStartTime()), 0.0, 0.0);
863         Assert.assertEquals(new AbsoluteDate("2005-145T12:00:00", utc).durationFrom(metaData3.getStopTime()), 0.0, 0.0);
864         Assert.assertEquals("DSS-60", metaData3.getParticipants().get(1));
865         Assert.assertEquals("UTC-NIST", metaData3.getParticipants().get(2));
866         final List<String> metaDataComment3 = new ArrayList<String>();
867         metaDataComment3.add("This is a meta-data comment");
868         Assert.assertEquals(metaDataComment3, metaData3.getComment());
869 
870         // Data 3
871         final List<TDMFile.Observation> observations3 = file.getObservationsBlocks().get(2).getObservations();
872 
873         // Reference data 2
874         // Same keywords and dates than 1
875         final double[] values3   = {-1.782e-6, 1.736e-13,
876             -1.767e-6, 1.157e-14,
877             -1.766e-6, 8.102e-14,
878             -1.759e-6};
879         // Check consistency
880         for (int i = 0; i < keywords.length; i++) {
881             Assert.assertEquals(keywords[i], observations3.get(i).getKeyword());
882             Assert.assertEquals(new AbsoluteDate(epochs[i], utc).durationFrom(observations3.get(i).getEpoch()), 0.0, 0.0);
883             Assert.assertEquals(values3[i], observations3.get(i).getMeasurement(), 0.0);
884         }
885         // Comment
886         final List<String> dataComment3 = new ArrayList<String>();
887         dataComment3.add("This is a data comment");
888         Assert.assertEquals(dataComment3, file.getObservationsBlocks().get(2).getObservationsComment());
889     }
890 
891     /**
892      * Validation function for example displaying all keywords.
893      * @param file Parsed TDMFile to validate
894      * @throws OrekitException if UTC time scale cannot be retrieved
895      */
896     public static void validateTDMExampleAllKeywords(TDMFile file) throws OrekitException {
897 
898         final TimeScale utc = TimeScalesFactory.getUTC();
899 
900         // Header
901         Assert.assertEquals(1.0, file.getFormatVersion(), 0.0);
902         Assert.assertEquals(new AbsoluteDate("2017-06-14T10:53:00.000", utc).durationFrom(file.getCreationDate()), 0.0, 0.0);
903         Assert.assertEquals("CSSI",file.getOriginator());
904         final List<String> headerComment = new ArrayList<String>();
905         headerComment.add("TDM example created by CSSI");
906         headerComment.add("Testing all TDM known meta-data and data keywords");
907         Assert.assertEquals(headerComment, file.getHeaderComment());
908 
909         // Meta-Data
910         final TDMFile.TDMMetaData metaData = file.getObservationsBlocks().get(0).getMetaData();
911 
912         Assert.assertEquals(CcsdsTimeScale.UTC, metaData.getTimeSystem());
913         Assert.assertEquals(new AbsoluteDate("2017-06-14T10:53:00.000", utc).durationFrom(metaData.getStartTime()), 0.0, 0.0);
914         Assert.assertEquals("2017-06-14T10:53:00.000", metaData.getStartTimeString());
915         Assert.assertEquals(new AbsoluteDate("2017-06-15T10:53:00.000", utc).durationFrom(metaData.getStopTime()), 0.0, 0.0);
916         Assert.assertEquals("2017-06-15T10:53:00.000", metaData.getStopTimeString());
917         Assert.assertEquals("DSS-25", metaData.getParticipants().get(1));
918         Assert.assertEquals("YYYY-NNNA", metaData.getParticipants().get(2));
919         Assert.assertEquals("P3", metaData.getParticipants().get(3));
920         Assert.assertEquals("P4", metaData.getParticipants().get(4));
921         Assert.assertEquals("P5", metaData.getParticipants().get(5));
922         Assert.assertEquals("SEQUENTIAL", metaData.getMode());
923         Assert.assertEquals("2,1", metaData.getPath());
924         Assert.assertEquals("4,5", metaData.getPath1());
925         Assert.assertEquals("3,2", metaData.getPath2());
926         Assert.assertEquals("S", metaData.getTransmitBand());
927         Assert.assertEquals("L", metaData.getReceiveBand());
928         Assert.assertEquals(240, metaData.getTurnaroundNumerator(), 0);
929         Assert.assertEquals(221, metaData.getTurnaroundDenominator(), 0);
930         Assert.assertEquals("TRANSMIT", metaData.getTimetagRef());
931         Assert.assertEquals(1.0, metaData.getIntegrationInterval(), 0.0);
932         Assert.assertEquals("MIDDLE", metaData.getIntegrationRef());
933         Assert.assertEquals(32021035200.0, metaData.getFreqOffset(), 0.0);
934         Assert.assertEquals("COHERENT", metaData.getRangeMode());
935         Assert.assertEquals(32768.0, metaData.getRangeModulus(), 0.0);
936         Assert.assertEquals("RU", metaData.getRangeUnits());
937         Assert.assertEquals("RADEC", metaData.getAngleType());
938         Assert.assertEquals("EME2000", metaData.getReferenceFrameString());
939         Assert.assertEquals(true,FramesFactory.getEME2000().equals(metaData.getReferenceFrame()));
940         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(1), 0.0);
941         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(2), 0.0);
942         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(3), 0.0);
943         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(4), 0.0);
944         Assert.assertEquals(0.000077, metaData.getTransmitDelays().get(5), 0.0);
945         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(1), 0.0);
946         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(2), 0.0);
947         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(3), 0.0);
948         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(4), 0.0);
949         Assert.assertEquals(0.000077, metaData.getReceiveDelays().get(5), 0.0);
950         Assert.assertEquals("RAW", metaData.getDataQuality());
951         Assert.assertEquals(1.0, metaData.getCorrectionAngle1(), 0.0);
952         Assert.assertEquals(2.0, metaData.getCorrectionAngle2(), 0.0);
953         Assert.assertEquals(3.0, metaData.getCorrectionDoppler(), 0.0);
954         Assert.assertEquals(4.0, metaData.getCorrectionRange(), 0.0);
955         Assert.assertEquals(5.0, metaData.getCorrectionReceive(), 0.0);
956         Assert.assertEquals(6.0, metaData.getCorrectionTransmit(), 0.0);
957         Assert.assertEquals("YES", metaData.getCorrectionsApplied());
958 
959         final List<String> metaDataComment = new ArrayList<String>();
960         metaDataComment.add("All known meta-data keywords displayed");
961         Assert.assertEquals(metaDataComment, metaData.getComment());
962 
963         // Data
964         final List<TDMFile.Observation> observations = file.getObservationsBlocks().get(0).getObservations();
965 
966         // Reference data
967         final String[] keywords = {"CARRIER_POWER", "DOPPLER_INSTANTANEOUS", "DOPPLER_INTEGRATED", "PC_N0", "PR_N0", "RANGE",
968                                    "RECEIVE_FREQ_1", "RECEIVE_FREQ_2", "RECEIVE_FREQ_3", "RECEIVE_FREQ_4", "RECEIVE_FREQ_5", "RECEIVE_FREQ",
969                                    "TRANSMIT_FREQ_1", "TRANSMIT_FREQ_2", "TRANSMIT_FREQ_3", "TRANSMIT_FREQ_4","TRANSMIT_FREQ_5",
970                                    "TRANSMIT_FREQ_RATE_1", "TRANSMIT_FREQ_RATE_2", "TRANSMIT_FREQ_RATE_3", "TRANSMIT_FREQ_RATE_4", "TRANSMIT_FREQ_RATE_5",
971                                    "DOR", "VLBI_DELAY",
972                                    "ANGLE_1", "ANGLE_2",
973                                    "CLOCK_BIAS", "CLOCK_DRIFT",
974                                    "STEC", "TROPO_DRY", "TROPO_WET",
975                                    "PRESSURE", "RHUMIDITY", "TEMPERATURE"};
976 
977         final AbsoluteDate epoch = new AbsoluteDate("2017-06-14T10:53:00.000", utc);
978         // Check consistency
979         for (int i = 0; i < keywords.length; i++) {
980             Assert.assertEquals(keywords[i], observations.get(i).getKeyword());
981             Assert.assertEquals(epoch.shiftedBy((double) (i+1)).durationFrom(observations.get(i).getEpoch()), 0.0, 0.0);
982             Assert.assertEquals((double) (i+1), observations.get(i).getMeasurement(), 0.0);
983         }
984 
985         // Comment
986         final List<String> dataComment = new ArrayList<String>();
987         dataComment.add("Signal related Keywords");
988         dataComment.add("VLBI/Delta-DOR Related Keywords");
989         dataComment.add("Angle Related Keywords");
990         dataComment.add("Time Related Keywords");
991         dataComment.add("Media Related Keywords");
992         dataComment.add("Meteorological Related Keywords");
993         Assert.assertEquals(dataComment, file.getObservationsBlocks().get(0).getObservationsComment());
994     }
995 }