Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
LALInitBarycenter.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010 Reinhard Prix (XLALified)
3* Copyright (C) 2007 Curt Cutler, Jolien Creighton, Reinhard Prix, Teviet Creighton, Bernd Machenschalk
4*
5* This program is free software; you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation; either version 2 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with with program; see the file COPYING. If not, write to the
17* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18* MA 02110-1301 USA
19*/
20
21#include <lal/FileIO.h>
22#include <lal/LALBarycenter.h>
23#include <lal/LALInitBarycenter.h>
24#include <lal/ConfigFile.h>
25#include <lal/LALString.h>
26#include <lal/Date.h>
27
28/** \cond DONT_DOXYGEN */
29
30/* ----- defines and macros ---------- */
31#define SQ(x) ((x) * (x))
32#define NORM3D(x) ( SQ( (x)[0]) + SQ( (x)[1] ) + SQ ( (x)[2] ) )
33#define LENGTH3D(x) ( sqrt( NORM3D ( (x) ) ) )
34
35/** \endcond */
36
37/* ----- local type definitions ---------- */
38
39/**
40 * Generic ephemeris-vector type, holding one timeseries of pos, vel, acceleration.
41 * This is used for the generic ephemeris-reader XLAL-function, at the end the resulting
42 * ephemeris-data will be stored in the 'old type \a EphemerisData for backwards compatibility.
43 */
44typedef struct {
45 UINT4 length; /**< number of ephemeris-data entries */
46 REAL8 dt; /**< spacing in seconds between consecutive instants in ephemeris table.*/
47 PosVelAcc *data; /**< array containing pos,vel,acc as extracted from ephem file. Units are sec, 1, 1/sec respectively */
48}
50
51/* ----- internal prototypes ---------- */
54
56int XLALCheckEphemerisRanges( const EphemerisVector *ephemEarth, REAL8 avg[3], REAL8 range[3] );
57
58/* ----- function definitions ---------- */
59
60/* ========== exported API ========== */
61
62/// \addtogroup LALBarycenter_h
63/// @{
64
65/**
66 * An XLAL interface for reading a time correction file containing a table
67 * of values for converting between Terrestrial Time TT (or TDT) to either
68 * TDB (i.e. the file contains time corrections related to the Einstein delay)
69 * or Teph (a time system from Irwin and Fukushima, 1999, closely related to
70 * Coordinate Barycentric Time, TCB) depending on the file.
71 *
72 * The file contains a header with the GPS start time, GPS end time, time
73 * interval between subsequent entries (seconds), and the number of entries.
74 *
75 * The rest of the file contains a list of the time delays (in seconds).
76 *
77 * The tables for the conversion to TDB and Teph are derived from the ephemeris
78 * file TDB.1950.2050 and TIMEEPH_short.te405 within TEMPO2
79 * http://www.atnf.csiro.au/research/pulsar/tempo2/. They are created from the
80 * Chebychev polynomials in these files using the conversion in the code
81 * lalpulsar_create_time_correction_ephemeris
82 *
83 * \ingroup LALBarycenter_h
84 */
86XLALInitTimeCorrections( const CHAR *timeCorrectionFile /**< File containing Earth's position. */
87 )
88{
89 REAL8 *tvec = NULL; /* create time vector */
90 LALParsedDataFile *flines = NULL;
91 UINT4 numLines = 0, j = 0;
92 REAL8 endtime = 0.;
93
94 /* check user input consistency */
95 if ( !timeCorrectionFile ) {
96 XLAL_ERROR_NULL( XLAL_EINVAL, "Invalid NULL input for 'timeCorrectionFile'\n" );
97 }
98
99 char *fname_path;
100 XLAL_CHECK_NULL( ( fname_path = XLAL_FILE_RESOLVE_PATH( timeCorrectionFile ) ) != NULL, XLAL_EINVAL );
101
102 /* read in file with XLALParseDataFile to ignore comment header lines */
103 if ( XLALParseDataFile( &flines, fname_path ) != XLAL_SUCCESS ) {
104 XLALFree( fname_path );
106 }
107 XLALFree( fname_path );
108
109 /* prepare output ephemeris struct for returning */
111 if ( ( tdat = XLALCalloc( 1, sizeof( *tdat ) ) ) == NULL ) {
112 XLAL_ERROR_NULL( XLAL_ENOMEM, "XLALCalloc ( 1, %zu ) failed.\n", sizeof( *tdat ) );
113 }
114
115 numLines = flines->lines->nTokens;
116
117 /* read in info from first line (an uncommented header) */
118 if ( 4 != sscanf( flines->lines->tokens[0], "%lf %lf %lf %u", &tdat->timeCorrStart, &endtime, &tdat->dtTtable, &tdat->nentriesT ) ) {
121 XLAL_ERROR_NULL( XLAL_EDOM, "Couldn't parse first line of %s\n", timeCorrectionFile );
122 }
123
124 if ( numLines - 1 != tdat->nentriesT ) {
127 XLAL_ERROR_NULL( XLAL_EDOM, "Header says file has '%d' data-lines, but found '%d'.\n", tdat->nentriesT, numLines - 1 );
128 }
129
130 /* allocate memory for table entries */
131 if ( ( tvec = XLALCalloc( tdat->nentriesT, sizeof( REAL8 ) ) ) == NULL ) {
134 XLAL_ERROR_NULL( XLAL_ENOMEM, " XLALCalloc(%u, sizeof(REAL8))\n", tdat->nentriesT );
135 }
136
137 /* read in table data */
138 int ret;
139 for ( j = 1; j < numLines; j++ ) {
140 if ( ( ret = sscanf( flines->lines->tokens[j], "%lf", &tvec[j - 1] ) ) != 1 ) {
141 XLALFree( tvec );
144 XLAL_ERROR_NULL( XLAL_EDOM, "Couldn't parse line %d of %s: read %d instead of 1\n", j + 2, timeCorrectionFile, ret );
145 }
146 } // for j < numLines
147
149
150 /* set output time delay vector */
151 tdat->timeCorrs = tvec;
152
153 /* store *copy* of ephemeris-file name in output structure */
154 tdat->timeEphemeris = XLALStringDuplicate( timeCorrectionFile );
155
156 return tdat;
157
158} /* XLALInitTimeCorrections() */
159
160/**
161 * Destructor for TimeCorrectionData struct, NULL robust.
162 * \ingroup LALBarycenter_h
163 */
164void
166{
167 if ( !tcd ) {
168 return;
169 }
170
171 if ( tcd->timeCorrs ) {
172 XLALFree( tcd->timeCorrs );
173 }
174
175 if ( tcd->timeEphemeris ) {
176 XLALFree( tcd->timeEphemeris );
177 }
178
179 XLALFree( tcd );
180
181 return;
182
183} /* XLALDestroyTimeCorrectionData() */
184
185/**
186 * XLAL interface to reading ephemeris files 'earth' and 'sun', and return
187 * ephemeris-data in old backwards-compatible type \a EphemerisData
188 *
189 * These ephemeris data files contain arrays
190 * of center-of-mass positions for the Earth and Sun, respectively.
191 *
192 * The tables are derived from the JPL ephemeris.
193 *
194 * Files tabulate positions for one calendar year
195 * (actually, a little more than one year, to deal
196 * with overlaps). The first line of each table summarizes
197 * what is in it. Subsequent lines give the time (GPS) and the
198 * Earth's position \f$ (x,y,z) \f$ ,
199 * velocity \f$ (v_x, v_y, v_z) \f$ , and acceleration \f$ (a_x, a_y, a_z) \f$
200 * at that instant. All in units of seconds; e.g. positions have
201 * units of seconds, and accelerations have units 1/sec.
202 *
203 * \ingroup LALBarycenter_h
204 */
206XLALInitBarycenter( const CHAR *earthEphemerisFile, /**< File containing Earth's position. */
207 const CHAR *sunEphemerisFile /**< File containing Sun's position. */
208 )
209{
210 EphemerisType sun_etype, earth_etype, etype;
211
212 /* check user input consistency */
213 if ( !earthEphemerisFile || !sunEphemerisFile ) {
214 XLAL_ERROR_NULL( XLAL_EINVAL, "Invalid NULL input earthEphemerisFile=%p, sunEphemerisFile=%p\n", earthEphemerisFile, sunEphemerisFile );
215 }
216
217 /* determine EARTH ephemeris type from file name*/
218 if ( strstr( earthEphemerisFile, "DE200" ) ) {
219 earth_etype = EPHEM_DE200;
220 } else if ( strstr( earthEphemerisFile, "DE405" ) ) {
221 earth_etype = EPHEM_DE405;
222 } else if ( strstr( earthEphemerisFile, "DE414" ) ) {
223 earth_etype = EPHEM_DE414;
224 } else if ( strstr( earthEphemerisFile, "DE421" ) ) {
225 earth_etype = EPHEM_DE421;
226 } else if ( strstr( earthEphemerisFile, "DE430" ) ) {
227 earth_etype = EPHEM_DE430;
228 } else {
229 earth_etype = EPHEM_DE405;
230 }
231
232 /* determine SUN ephemeris type from file name */
233 if ( strstr( sunEphemerisFile, "DE200" ) ) {
234 sun_etype = EPHEM_DE200;
235 } else if ( strstr( sunEphemerisFile, "DE405" ) ) {
236 sun_etype = EPHEM_DE405;
237 } else if ( strstr( sunEphemerisFile, "DE414" ) ) {
238 sun_etype = EPHEM_DE414;
239 } else if ( strstr( sunEphemerisFile, "DE421" ) ) {
240 sun_etype = EPHEM_DE421;
241 } else if ( strstr( sunEphemerisFile, "DE430" ) ) {
242 sun_etype = EPHEM_DE430;
243 } else {
244 sun_etype = EPHEM_DE405;
245 }
246
247 // check consistency
248 if ( earth_etype != sun_etype )
249 XLAL_ERROR_NULL( XLAL_EINVAL, "Earth '%s' and Sun '%s' ephemeris-files have inconsistent coordinate-types %d != %d\n",
250 earthEphemerisFile, sunEphemerisFile, earth_etype, sun_etype );
251 else {
252 etype = earth_etype;
253 }
254
255 EphemerisVector *ephemV;
256 /* ----- read EARTH ephemeris file ---------- */
257 if ( ( ephemV = XLALReadEphemerisFile( earthEphemerisFile ) ) == NULL ) {
258 XLAL_ERROR_NULL( XLAL_EFUNC, "XLALReadEphemerisFile('%s') failed\n", earthEphemerisFile );
259 }
260
261 /* typical position, velocity and acceleration and allowed ranged */
262 REAL8 avgE[3] = {499.0, 1e-4, 2e-11 };
263 REAL8 rangeE[3] = {25.0, 1e-5, 3e-12 };
264
265 if ( XLALCheckEphemerisRanges( ephemV, avgE, rangeE ) != XLAL_SUCCESS ) {
267 XLAL_ERROR_NULL( XLAL_EFUNC, "Earth-ephemeris range error in XLALCheckEphemerisRanges()!\n" );
268 }
269
270 /* prepare output ephemeris struct for returning */
272 if ( ( edat = XLALCalloc( 1, sizeof( *edat ) ) ) == NULL ) {
273 XLAL_ERROR_NULL( XLAL_ENOMEM, "XLALCalloc ( 1, %zu ) failed.\n", sizeof( *edat ) );
274 }
275
276 /* store in ephemeris-struct */
277 edat->nentriesE = ephemV->length;
278 edat->dtEtable = ephemV->dt;
279 edat->ephemE = ephemV->data;
280 edat->etype = etype;
281 XLALFree( ephemV ); /* don't use 'destroy', as we linked the data into edat! */
282 ephemV = NULL;
283
284 /* ----- read SUN ephemeris file ---------- */
285 if ( ( ephemV = XLALReadEphemerisFile( sunEphemerisFile ) ) == NULL ) {
287 XLAL_ERROR_NULL( XLAL_EFUNC, "XLALReadEphemerisFile('%s') failed\n", sunEphemerisFile );
288 }
289
290 /* typical position, velocity and acceleration and allowed ranged */
291 REAL8 avgS[3] = { 2.7, 4.2e-8, 7.0e-16 };
292 REAL8 rangeS[3] = { 2.5, 1.4e-8, 2.8e-16 };
293
294 if ( XLALCheckEphemerisRanges( ephemV, avgS, rangeS ) != XLAL_SUCCESS ) {
297 XLAL_ERROR_NULL( XLAL_EFUNC, "Sun-ephemeris range error in XLALCheckEphemerisRanges()!\n" );
298 }
299
300 /* store in ephemeris-struct */
301 edat->nentriesS = ephemV->length;
302 edat->dtStable = ephemV->dt;
303 edat->ephemS = ephemV->data;
304 XLALFree( ephemV ); /* don't use 'destroy', as we linked the data into edat! */
305 ephemV = NULL;
306
307 // store *copy* of ephemeris-file names in output structure
308 edat->filenameE = XLALStringDuplicate( earthEphemerisFile );
309 edat->filenameS = XLALStringDuplicate( sunEphemerisFile );
310
311 /* return resulting ephemeris-data */
312 return edat;
313
314} /* XLALInitBarycenter() */
315
316
317/**
318 * Destructor for EphemerisData struct, NULL robust.
319 * \ingroup LALBarycenter_h
320 */
321void
323{
324 if ( !edat ) {
325 return;
326 }
327
328 if ( edat->filenameE ) {
329 XLALFree( edat->filenameE );
330 }
331
332 if ( edat->filenameS ) {
333 XLALFree( edat->filenameS );
334 }
335
336 if ( edat->ephemE ) {
337 XLALFree( edat->ephemE );
338 }
339
340 if ( edat->ephemS ) {
341 XLALFree( edat->ephemS );
342 }
343
344 XLALFree( edat );
345
346 return;
347
348} /* XLALDestroyEphemerisData() */
349
350
351/**
352 * Restrict the EphemerisData 'edat' to the smallest number of entries
353 * required to cover the GPS time range ['startGPS', 'endGPS']
354 *
355 * \ingroup LALBarycenter_h
356 */
358{
359
360 // Check input
361 XLAL_CHECK( edat != NULL, XLAL_EFAULT );
362 XLAL_CHECK( startGPS != NULL, XLAL_EFAULT );
363 XLAL_CHECK( endGPS != NULL, XLAL_EFAULT );
364 XLAL_CHECK( XLALGPSCmp( startGPS, endGPS ) < 0, XLAL_EINVAL );
365
366 // Convert 'startGPS' and 'endGPS' to REAL8s
367 const REAL8 start = XLALGPSGetREAL8( startGPS ), end = XLALGPSGetREAL8( endGPS );
368
369 // Increase 'ephemE' and decrease 'nentriesE' to fit the range ['start', 'end']
370 PosVelAcc *const old_ephemE = edat->ephemE;
371 do {
372 if ( edat->nentriesE > 1 && edat->ephemE[0].gps < start && edat->ephemE[1].gps <= start ) {
373 ++edat->ephemE;
374 --edat->nentriesE;
375 } else if ( edat->nentriesE > 1 && edat->ephemE[edat->nentriesE - 1].gps > end && edat->ephemE[edat->nentriesE - 2].gps >= end ) {
376 --edat->nentriesE;
377 } else {
378 break;
379 }
380 } while ( 1 );
381
382 // Reallocate 'ephemE' to new table size, and free old table
383 PosVelAcc *const new_ephemE = XLALMalloc( edat->nentriesE * sizeof( *new_ephemE ) );
384 XLAL_CHECK( new_ephemE != NULL, XLAL_ENOMEM );
385 memcpy( new_ephemE, edat->ephemE, edat->nentriesE * sizeof( *new_ephemE ) );
386 edat->ephemE = new_ephemE;
387 XLALFree( old_ephemE );
388
389 // Increase 'ephemS' and decrease 'nentriesS' to fit the range ['start', 'end']
390 PosVelAcc *const old_ephemS = edat->ephemS;
391 do {
392 if ( edat->nentriesS > 1 && edat->ephemS[0].gps < start && edat->ephemS[1].gps <= start ) {
393 ++edat->ephemS;
394 --edat->nentriesS;
395 } else if ( edat->nentriesS > 1 && edat->ephemS[edat->nentriesS - 1].gps > end && edat->ephemS[edat->nentriesS - 2].gps >= end ) {
396 --edat->nentriesS;
397 } else {
398 break;
399 }
400 } while ( 1 );
401
402 // Reallocate 'ephemS' to new table size, and free old table
403 PosVelAcc *const new_ephemS = XLALMalloc( edat->nentriesS * sizeof( *new_ephemS ) );
404 XLAL_CHECK( new_ephemS != NULL, XLAL_ENOMEM );
405 memcpy( new_ephemS, edat->ephemS, edat->nentriesS * sizeof( *new_ephemS ) );
406 edat->ephemS = new_ephemS;
407 XLALFree( old_ephemS );
408
409 return XLAL_SUCCESS;
410
411} /* XLALRestrictEphemerisData() */
412
413
414/* ========== internal function definitions ========== */
415
416/** simple creator function for EphemerisVector type */
419{
420 EphemerisVector *ret;
421 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
422 XLAL_ERROR_NULL( XLAL_ENOMEM, "Failed to XLALCalloc(1, %zu)\n", sizeof( *ret ) );
423 }
424
425 if ( ( ret->data = XLALCalloc( length, sizeof( *ret->data ) ) ) == NULL ) {
426 XLALFree( ret );
427 XLAL_ERROR_NULL( XLAL_ENOMEM, "Failed to XLALCalloc (%d, %zu)\n", length, sizeof( *ret->data ) );
428 }
429
430 ret->length = length;
431
432 return ret;
433
434} /* XLALCreateEphemerisVector() */
435
436/**
437 * Destructor for EphemerisVector, NULL robust.
438 */
439void
441{
442 if ( !ephemV ) {
443 return;
444 }
445
446 if ( ephemV->data ) {
447 XLALFree( ephemV->data );
448 }
449
450 XLALFree( ephemV );
451
452 return;
453
454} /* XLALDestroyEphemerisVector() */
455
456
457/** \cond DONT_DOXYGEN */
458/* Simple wrapper to XLAL_FILE_RESOLVE_PATH(), using hardcoded fallbackdir for LALPulsar
459 Use of XLAL_FILE_RESOLVE_PATH() directly is preferred; kept for ABI backward compatibility */
460char *
461XLALPulsarFileResolvePath( const char *fname )
462{
463 return XLAL_FILE_RESOLVE_PATH( fname );
464} // XLALPulsarFileResolvePath()
465/** \endcond */
466
467/**
468 * XLAL function to read ephemeris-data from one file, returning a EphemerisVector.
469 * This is a helper-function to XLALInitBarycenter().
470 *
471 * NOTE: This function tries to read ephemeris from "<fname>" first, if that fails it also tries
472 * to read "<fname>.gz" instead. This allows us to handle gzip-compressed ephemeris-files without having
473 * to worry about the detailed filename extension used in the case of compression.
474 *
475 * NOTE2: files are searched using XLAL_FILE_RESOLVE_PATH()
476 */
479{
480 /* check input consistency */
481 XLAL_CHECK_NULL( fname != NULL, XLAL_EINVAL );
482
483 char *fname_path = NULL;
484
485 // first check if "<fname>" can be resolved ...
486 if ( ( fname_path = XLAL_FILE_RESOLVE_PATH( fname ) ) == NULL ) {
487 // if not, check if we can find "<fname>.gz" instead ...
488 char *fname_gz;
489 XLAL_CHECK_NULL( ( fname_gz = XLALMalloc( strlen( fname ) + strlen( ".gz" ) + 1 ) ) != NULL, XLAL_ENOMEM );
490 sprintf( fname_gz, "%s.gz", fname );
491 if ( ( fname_path = XLAL_FILE_RESOLVE_PATH( fname_gz ) ) == NULL ) {
492 XLALFree( fname_gz );
493 XLAL_ERROR_NULL( XLAL_EINVAL, "Failed to find ephemeris-file '%s[.gz]'\n", fname );
494 } // if 'fname_gz' could not be resolved
495 XLALFree( fname_gz );
496 } // if 'fname' couldn't be resolved
497
498 // if we're here, it means we found it
499
500 // read in whole file (compressed or not) with XLALParseDataFile(), which ignores comment header lines
501 LALParsedDataFile *flines = NULL;
502 XLAL_CHECK_NULL( XLALParseDataFile( &flines, fname_path ) == XLAL_SUCCESS, XLAL_EFUNC );
503 XLALFree( fname_path );
504
505 UINT4 numLines = flines->lines->nTokens;
506
507 INT4 gpsYr; /* gpsYr + leap is the time on the GPS clock
508 * at first instant of new year, UTC; equivalently
509 * leap is # of leap secs added between Jan.6, 1980 and
510 * Jan. 2 of given year
511 */
512 REAL8 dt; /* ephemeris-file time-step in seconds */
513 UINT4 nEntries; /* number of ephemeris-file entries */
514
515 /* read first line */
516 if ( 3 != sscanf( flines->lines->tokens[0], "%d %le %u\n", &gpsYr, &dt, &nEntries ) ) {
518 XLAL_ERROR_NULL( XLAL_EDOM, "Couldn't parse first line of %s\n", fname );
519 }
520
521 /* check that number of lines is correct */
522 if ( nEntries != ( numLines - 1 ) / 4 && nEntries != ( numLines - 1 ) ) {
524 INT4 dataLines = nEntries != ( numLines - 1 ) ? ( numLines - 1 ) : ( numLines - 1 ) / 4;
525 XLAL_ERROR_NULL( XLAL_EDOM, "Inconsistent number of data-lines (%d) in file '%s' compared to header information (%d)\n", dataLines, fname, nEntries );
526 }
527
528 /* prepare output ephemeris vector */
529 EphemerisVector *ephemV;
530 if ( ( ephemV = XLALCreateEphemerisVector( nEntries ) ) == NULL ) {
531 XLAL_ERROR_NULL( XLAL_EFUNC, "Failed to XLALCreateEphemerisVector(%d)\n", nEntries );
532 }
533
534 ephemV->dt = dt;
535
536 /* first column in ephemeris-file is gps time--one long integer
537 * giving the number of secs that have ticked since start of GPS epoch
538 * + on 1980 Jan. 6 00:00:00 UTC
539 */
540
541 /* the old-style ephemeris files are created with each entry spanning 4 lines
542 * with the format:
543 * gps\tposX\tposY\n
544 * posZ\tvelX\tvelY\n
545 * velZ\taccX\taccY\n
546 * accZ\n
547 * However, newer ephemerides just span 1 line. So, deal with both cases.
548 ***************************************************************************/
549
550 /* read the remaining lines */
551 for ( UINT4 j = 0; j < nEntries; j++ ) {
552 UINT4 i_line;
553 int ret;
554
555 if ( nEntries == ( numLines - 1 ) / 4 ) {
556 i_line = 1 + 4 * j;
557
558 ret = sscanf( flines->lines->tokens[ i_line ], "%le %le %le\n", &ephemV->data[j].gps, &ephemV->data[j].pos[0], &ephemV->data[j].pos[1] );
559 XLAL_CHECK_NULL( ret == 3, XLAL_EDOM, "Couldn't parse line %d of %s: read %d items instead of 3\n", i_line, fname, ret );
560
561 i_line ++;
562 ret = sscanf( flines->lines->tokens[ i_line ], "%le %le %le\n", &ephemV->data[j].pos[2], &ephemV->data[j].vel[0], &ephemV->data[j].vel[1] );
563 XLAL_CHECK_NULL( ret == 3, XLAL_EDOM, "Couldn't parse line %d of %s: read %d items instead of 3\n", i_line, fname, ret );
564
565 i_line ++;
566 ret = sscanf( flines->lines->tokens[ i_line ], "%le %le %le\n", &ephemV->data[j].vel[2], &ephemV->data[j].acc[0], &ephemV->data[j].acc[1] );
567 XLAL_CHECK_NULL( ret == 3, XLAL_EDOM, "Couldn't parse line %d of %s: read %d items instead of 3\n", i_line, fname, ret );
568
569 i_line ++;
570 ret = sscanf( flines->lines->tokens[ i_line ], "%le\n", &ephemV->data[j].acc[2] );
571 XLAL_CHECK_NULL( ret == 1, XLAL_EDOM, "Couldn't parse line %d of %s: read %d items instead of 1\n", i_line, fname, ret );
572 } else {
573 i_line = j + 1;
574 ret = sscanf( flines->lines->tokens[ i_line ], "%le %le %le %le %le %le %le %le %le %le\n",
575 &ephemV->data[j].gps, &ephemV->data[j].pos[0], &ephemV->data[j].pos[1],
576 &ephemV->data[j].pos[2], &ephemV->data[j].vel[0], &ephemV->data[j].vel[1],
577 &ephemV->data[j].vel[2], &ephemV->data[j].acc[0], &ephemV->data[j].acc[1],
578 &ephemV->data[j].acc[2] );
579 XLAL_CHECK_NULL( ret == 10, XLAL_EDOM, "Couldn't parse line %d of %s: read %d items instead of 10\n", i_line, fname, ret );
580 }
581
582 /* check timestamps */
583 if ( j == 0 ) {
584 if ( gpsYr - ephemV->data[j].gps > 3600 * 24 * 365 ) {
587 XLAL_ERROR_NULL( XLAL_EDOM, "Wrong timestamp in line %d of %s: %d/%le\n", j + 2, fname, gpsYr, ephemV->data[j].gps );
588 }
589 } else {
590 if ( ephemV->data[j].gps != ephemV->data[j - 1].gps + ephemV->dt ) {
593 XLAL_ERROR_NULL( XLAL_EDOM, "Wrong timestamp in line %d of %s: %le/%le\n", j + 2, fname, ephemV->data[j].gps, ephemV->data[j - 1].gps + ephemV->dt );
594 }
595 }
596
597 } /* for j < nEntries */
598
600
601 /* return result */
602 return ephemV;
603
604} /* XLALReadEphemerisFile() */
605
606
607/**
608 * Function to check rough consistency of ephemeris-data with being an actual
609 * 'Earth' ephemeris: ie check position, velocity and acceleration are within
610 * reasonable ranges {avg +- range}. where 'avg' and 'range' are 3-D arrays
611 * with [0]=position, [1]=velocity and [2]=acceleration
612 */
613int
615{
616 /* check input consistency */
617 if ( !ephemV ) {
618 XLAL_ERROR( XLAL_EINVAL, "Invalid NULL input for 'ephemV' \n" );
619 }
620
621 UINT4 numEntries = ephemV->length;
622 REAL8 dt = ephemV->dt;
623
624 /* check position, velocity and acceleration */
625 UINT4 j;
626 REAL8 tjm1 = 0;
627 for ( j = 0; j < numEntries; j ++ ) {
628 REAL8 length;
629 length = LENGTH3D( ephemV->data[j].pos );
630 if ( fabs( avg[0] - length ) > range[0] )
631 XLAL_ERROR( XLAL_EDOM, "Position out of range in entry %d: vr=(%le, %le, %le), sqrt{|vr|} = %le [%g +- %g]\n",
632 j, ephemV->data[j].pos[0], ephemV->data[j].pos[1], ephemV->data[j].pos[2], length, avg[0], range[0] );
633
634 length = LENGTH3D( ephemV->data[j].vel );
635 if ( fabs( avg[1] - length ) > range[1] ) /* 10% */
636 XLAL_ERROR( XLAL_EDOM, "Velocity out of range in entry %d: vv=(%le, %le, %le), sqrt{|vv|} = %le, [%g +- %g]\n",
637 j, ephemV->data[j].vel[0], ephemV->data[j].vel[1], ephemV->data[j].vel[2], length, avg[1], range[1] );
638
639 length = LENGTH3D( ephemV->data[j].acc );
640 if ( fabs( avg[2] - length ) > range[2] ) /* 15% */
641 XLAL_ERROR( XLAL_EDOM, "Acceleration out of range in entry %d: va=(%le, %le, %le), sqrt{|va|} = %le, [%g +- %g]\n",
642 j, ephemV->data[j].acc[0], ephemV->data[j].acc[1], ephemV->data[j].acc[2], length, avg[2], range[2] );
643
644 /* check timestep */
645 if ( j > 0 ) {
646 if ( ephemV->data[j].gps - tjm1 != dt ) {
647 XLAL_ERROR( XLAL_EDOM, "Invalid timestep in entry %d: t_i - t_{i-1} = %g != %g\n", j, ephemV->data[j].gps - tjm1, dt );
648 }
649 }
650 tjm1 = ephemV->data[j].gps; /* keep track of previous timestamp */
651
652 } /* for j < nEntries */
653
654
655 /* all seems ok */
656 return XLAL_SUCCESS;
657
658} /* XLALCheckEphemerisRanges() */
659
660/// @}
int j
double e
int XLALParseDataFile(LALParsedDataFile **cfgdata, const CHAR *fname)
void XLALDestroyParsedDataFile(LALParsedDataFile *cfgdata)
#define XLAL_FILE_RESOLVE_PATH(fname)
TimeCorrectionData * XLALInitTimeCorrections(const CHAR *timeCorrectionFile)
An XLAL interface for reading a time correction file containing a table of values for converting betw...
EphemerisData * XLALInitBarycenter(const CHAR *earthEphemerisFile, const CHAR *sunEphemerisFile)
XLAL interface to reading ephemeris files 'earth' and 'sun', and return ephemeris-data in old backwar...
void XLALDestroyEphemerisVector(EphemerisVector *ephemV)
Destructor for EphemerisVector, NULL robust.
EphemerisVector * XLALReadEphemerisFile(const CHAR *fname)
XLAL function to read ephemeris-data from one file, returning a EphemerisVector.
EphemerisType
Enumerated type denoting the JPL solar system ephemeris to be used in calculating barycentre time cor...
Definition: LALBarycenter.h:86
int XLALRestrictEphemerisData(EphemerisData *edat, const LIGOTimeGPS *startGPS, const LIGOTimeGPS *endGPS)
Restrict the EphemerisData 'edat' to the smallest number of entries required to cover the GPS time ra...
int XLALCheckEphemerisRanges(const EphemerisVector *ephemEarth, REAL8 avg[3], REAL8 range[3])
Function to check rough consistency of ephemeris-data with being an actual 'Earth' ephemeris: ie chec...
void XLALDestroyTimeCorrectionData(TimeCorrectionData *tcd)
Destructor for TimeCorrectionData struct, NULL robust.
EphemerisVector * XLALCreateEphemerisVector(UINT4 length)
simple creator function for EphemerisVector type
void XLALDestroyEphemerisData(EphemerisData *edat)
Destructor for EphemerisData struct, NULL robust.
@ EPHEM_DE405
Definition: LALBarycenter.h:89
@ EPHEM_DE414
Definition: LALBarycenter.h:90
@ EPHEM_DE421
Definition: LALBarycenter.h:91
@ EPHEM_DE200
Definition: LALBarycenter.h:88
@ EPHEM_DE430
Definition: LALBarycenter.h:92
double REAL8
char CHAR
uint32_t UINT4
int32_t INT4
void * XLALMalloc(size_t n)
void * XLALCalloc(size_t m, size_t n)
void XLALFree(void *p)
char char * XLALStringDuplicate(const char *s)
#define XLAL_ERROR_NULL(...)
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
#define XLAL_CHECK_NULL(assertion,...)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
XLAL_EINVAL
int XLALGPSCmp(const LIGOTimeGPS *t0, const LIGOTimeGPS *t1)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
end
This structure contains all information about the center-of-mass positions of the Earth and Sun,...
Generic ephemeris-vector type, holding one timeseries of pos, vel, acceleration.
REAL8 dt
spacing in seconds between consecutive instants in ephemeris table.
UINT4 length
number of ephemeris-data entries
PosVelAcc * data
array containing pos,vel,acc as extracted from ephem file.
TokenList * lines
Structure holding a REAL8 time, and a position, velocity and acceleration vector.
REAL8 acc[3]
acceleration-vector
REAL8 gps
REAL8 timestamp.
REAL8 vel[3]
velocity-vector
REAL8 pos[3]
position-vector
This structure will contain a vector of time corrections used during conversion from TT to TDB/TCB/Te...
CHAR * timeEphemeris
File containing the time ephemeris.
REAL8 * timeCorrs
Array of time delays for converting TT to TDB/TCB from the Time table (seconds).
CHAR ** tokens
UINT4 nTokens