LALPulsar  6.1.0.1-c9a8ef6
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  */
44 typedef 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 
56 int 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  */
86 XLALInitTimeCorrections( 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 ) ) {
119  XLALDestroyParsedDataFile( flines );
121  XLAL_ERROR_NULL( XLAL_EDOM, "Couldn't parse first line of %s\n", timeCorrectionFile );
122  }
123 
124  if ( numLines - 1 != tdat->nentriesT ) {
125  XLALDestroyParsedDataFile( flines );
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 ) {
132  XLALDestroyParsedDataFile( flines );
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 );
142  XLALDestroyParsedDataFile( flines );
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 
148  XLALDestroyParsedDataFile( flines );
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  */
164 void
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  */
206 XLALInitBarycenter( 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 ) {
266  XLALDestroyEphemerisVector( ephemV );
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 ) {
295  XLALDestroyEphemerisVector( ephemV );
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  */
321 void
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  */
357 int XLALRestrictEphemerisData( EphemerisData *edat, const LIGOTimeGPS *startGPS, const LIGOTimeGPS *endGPS )
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  */
439 void
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 */
460 char *
461 XLALPulsarFileResolvePath( 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 ) ) {
517  XLALDestroyParsedDataFile( flines );
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 ) ) {
523  XLALDestroyParsedDataFile( flines );
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 ) {
585  XLALDestroyEphemerisVector( ephemV );
586  XLALDestroyParsedDataFile( flines );
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 ) {
591  XLALDestroyEphemerisVector( ephemV );
592  XLALDestroyParsedDataFile( flines );
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 
599  XLALDestroyParsedDataFile( flines );
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  */
613 int
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)
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
TimeCorrectionData * XLALInitTimeCorrections(const CHAR *timeCorrectionFile)
An XLAL interface for reading a time correction file containing a table of values for converting betw...
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.
EphemerisData * XLALInitBarycenter(const CHAR *earthEphemerisFile, const CHAR *sunEphemerisFile)
XLAL interface to reading ephemeris files 'earth' and 'sun', and return ephemeris-data in old backwar...
@ 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 * XLALCalloc(size_t m, size_t n)
void * XLALMalloc(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