Loading [MathJax]/jax/output/HTML-CSS/config.js
LALPulsar 7.1.1.1-b246709
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
heterodyne_pulsar.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Matt Pitkin
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20/**
21 * \file
22 * \ingroup lalpulsar_bin_HeterodyneSearch
23 * \author M. D. Pitkin
24 * \brief
25 * code to perform a coarse/fine heterodyne on LIGO or GEO data given a set of pulsar
26 * parameters. The heterodyne is a 2 stage process with the code run for a coarse
27 * heterodyne (not taking into account the SSB and BSB time delays, but using the other frequency
28 * params) and then rerun for the fine heterodyne (taking into account SSB and BSB time delays). The
29 * code can also be used to update heterodyned data using new parameters (old and new parameter files
30 * are required) i.e. it will take the difference of the original heterodyne phase and the new phase
31 * and reheterodyne with this phase difference.
32 */
33
34/* Matt Pitkin - 07/02/06 ------------- heterodyne_pulsar.c */
35
36/* code to perform a coarse/fine heterodyne on LIGO or GEO data given a set of pulsar
37parameters. The heterodyne is a 2 stage process with the code run for a coarse
38heterodyne (not taking into account the SSB and BSB time delays, but using the other frequency
39params) and then rerun for the fine heterodyne (taking into account SSB and BSB time delays). The
40code can also be used to update heterodyned data using new parameters (old and new parameter files
41are required) i.e. it will take the difference of the original heterodyne phase and the new phase
42and reheterodyne with this phase difference. */
43
44#include "heterodyne_pulsar.h"
45
46/* define a macro to round a number without having to use the C round function */
47#define ROUND(a) (floor(a+0.5))
48
49/* allocate 1Mb (2^20) of memory at a time */
50#define MAXALLOC 1048576
51
52/* track memory usage under linux */
53#define TRACKMEMUSE 0
54
55/* routine to track memory usage in different categories */
56#if TRACKMEMUSE
57void printmemuse()
58{
59 pid_t mypid = getpid();
60 char commandline[256];
61 fflush( NULL );
62 snprintf( commandline, sizeof( commandline ), "cat /proc/%d/status | /bin/grep Vm | /usr/bin/fmt -140 -u", ( int )mypid );
63 system( commandline );
64 fflush( NULL );
65}
66#endif
67
68// internal function taken from lal/lib/support/LogPrintf.c
69static const char *LogTimeToString( double t );
70
71/* verbose global variable */
73
74int main( int argc, char *argv[] )
75{
76 InputParams inputParams;
77 HeterodyneParams hetParams;
78
79 Filters iirFilters;
80
81 LALFILE *fpin = NULL;
82 FILE *fpout = NULL;
83 LALCache *cache = NULL;
84 INT4 count = 0;
85
86 CHAR outputfile[256] = "";
87 CHAR channel[128] = "";
88 const CHAR *psrname;
89
90 INT4Vector *starts = NULL, *stops = NULL; /* science segment start and stop times */
91 INT4 numSegs = 0;
92 INT4 nodata = 1;
93
94 FilterResponse *filtresp = NULL; /* variable for the filter response function */
95
96 /* set error handler */
98
99#if TRACKMEMUSE
100 fprintf( stderr, "Memory use at start of the code:\n" );
101 printmemuse();
102#endif
103
104 /* get input options */
105 get_input_args( &inputParams, argc, argv );
106
107 if ( inputParams.verbose ) {
108 verbose = 1;
109 }
110
111 hetParams.heterodyneflag = inputParams.heterodyneflag; /* set type of heterodyne */
112
113 /* read in pulsar data */
114 hetParams.het = XLALReadTEMPOParFile( inputParams.paramfile );
115 hetParams.hetUpdate = NULL;
116 hetParams.outputPhase = inputParams.outputPhase;
117
118 /* set pulsar name - take from par file if available, or if not get from command line args */
119 if ( PulsarCheckParam( hetParams.het, "PSRJ" ) ) {
120 psrname = PulsarGetStringParam( hetParams.het, "PSRJ" );
121 } else if ( PulsarCheckParam( hetParams.het, "PSRB" ) ) {
122 psrname = PulsarGetStringParam( hetParams.het, "PSRB" );
123 } else if ( PulsarCheckParam( hetParams.het, "NAME" ) ) {
124 psrname = PulsarGetStringParam( hetParams.het, "NAME" );
125 } else if ( PulsarCheckParam( hetParams.het, "PSR" ) ) {
126 psrname = PulsarGetStringParam( hetParams.het, "PSR" );
127 } else {
128 fprintf( stderr, "No pulsar name specified!\n" );
129 exit( 0 );
130 }
131
132 /* if there is an epoch given manually (i.e. not from the pulsar parameter
133 file) then set it here and overwrite any other value - this is used, for
134 example, with the pulsar hardware injections in which this should be set
135 at 751680013.0 */
136 if ( inputParams.manualEpoch != 0. ) {
137 PulsarSetParam( hetParams.het, "PEPOCH", &inputParams.manualEpoch );
138 PulsarSetParam( hetParams.het, "POSEPOCH", &inputParams.manualEpoch );
139 }
140
141 if ( verbose ) {
142 fprintf( stderr, "I've read in the pulsar parameters for %s.\n", psrname );
143 REAL8 rav, decv, pepochv;
144 if ( PulsarCheckParam( hetParams.het, "RAJ" ) ) {
145 rav = PulsarGetREAL8Param( hetParams.het, "RAJ" );
146 } else {
147 rav = PulsarGetREAL8ParamOrZero( hetParams.het, "RA" );
148 }
149
150 if ( PulsarCheckParam( hetParams.het, "DECJ" ) ) {
151 decv = PulsarGetREAL8Param( hetParams.het, "DECJ" );
152 } else {
153 decv = PulsarGetREAL8ParamOrZero( hetParams.het, "DEC" );
154 }
155
156 fprintf( stderr, "alpha = %lf rads, delta = %lf rads.\n", rav, decv );
157
158 if ( PulsarCheckParam( hetParams.het, "F" ) ) {
159 const REAL8Vector *freqsv = PulsarGetREAL8VectorParam( hetParams.het, "F" );
160 UINT4 i = 0;
161
162 pepochv = PulsarGetREAL8ParamOrZero( hetParams.het, "PEPOCH" );
163 for ( i = 0; i < freqsv->length; i++ ) {
164 fprintf( stderr, "f%u = %.1e Hz/s^%u, ", i, freqsv->data[i], i );
165 }
166 fprintf( stderr, "epoch = %.1lf.\n", pepochv );
167 }
168
169 fprintf( stderr, "I'm looking for gravitational waves at %.2lf times the pulsars spin frequency.\n", inputParams.freqfactor );
170 }
171
172 /*if performing fine heterdoyne using same params as coarse */
173 if ( inputParams.heterodyneflag == 1 || inputParams.heterodyneflag == 3 ) {
174 hetParams.hetUpdate = hetParams.het;
175 }
176
177 hetParams.samplerate = inputParams.samplerate;
178
179 /* set detector */
180 hetParams.detector = *XLALGetSiteInfo( inputParams.ifo );
181
182 if ( verbose ) {
183 fprintf( stderr, "I've set the detector location for %s.\n", inputParams.ifo );
184 }
185
186 if ( inputParams.heterodyneflag == 2 || inputParams.heterodyneflag == 4 ) { /* if updating parameters read in updated par file */
187 hetParams.hetUpdate = XLALReadTEMPOParFile( inputParams.paramfileupdate );
188
189 /* if there is an epoch given manually (i.e. not from the pulsar parameter
190 file) then set it here and overwrite any other value */
191 if ( inputParams.manualEpoch != 0. ) {
192 PulsarSetParam( hetParams.hetUpdate, "PEPOCH", &inputParams.manualEpoch );
193 PulsarSetParam( hetParams.hetUpdate, "POSEPOCH", &inputParams.manualEpoch );
194 }
195
196 if ( verbose ) {
197 fprintf( stderr, "I've read the updated parameters for %s.\n", psrname );
198
199 REAL8 rav, decv, pepochv;
200 if ( PulsarCheckParam( hetParams.hetUpdate, "RAJ" ) ) {
201 rav = PulsarGetREAL8Param( hetParams.hetUpdate, "RAJ" );
202 } else {
203 rav = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "RA" );
204 }
205
206 if ( PulsarCheckParam( hetParams.hetUpdate, "DECJ" ) ) {
207 decv = PulsarGetREAL8Param( hetParams.hetUpdate, "DECJ" );
208 } else {
209 decv = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "DEC" );
210 }
211
212 fprintf( stderr, "alpha = %lf rads, delta = %lf rads.\n", rav, decv );
213
214 if ( PulsarCheckParam( hetParams.hetUpdate, "F" ) ) {
215 const REAL8Vector *freqsv = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "F" );
216 UINT4 i = 0;
217
218 pepochv = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "PEPOCH" );
219 for ( i = 0; i < freqsv->length; i++ ) {
220 fprintf( stderr, "f%u = %.1e Hz/s^%u, ", i, freqsv->data[i], i );
221 }
222 fprintf( stderr, "epoch = %.1lf.\n", pepochv );
223 }
224 }
225 }
226
227 if ( inputParams.heterodyneflag > 0 ) {
228 snprintf( hetParams.earthfile, sizeof( hetParams.earthfile ), "%s",
229 inputParams.earthfile );
230 snprintf( hetParams.sunfile, sizeof( hetParams.sunfile ), "%s",
231 inputParams.sunfile );
232
233 if ( inputParams.timeCorrFile != NULL ) {
234 hetParams.timeCorrFile = XLALStringDuplicate( inputParams.timeCorrFile );
235
236 if ( PulsarCheckParam( hetParams.hetUpdate, "UNITS" ) ) {
237 if ( !strcmp( PulsarGetStringParam( hetParams.hetUpdate, "UNITS" ), "TDB" ) ) {
238 hetParams.ttype = TIMECORRECTION_TDB; /* use TDB units i.e. TEMPO standard */
239 } else {
240 hetParams.ttype = TIMECORRECTION_TCB; /* default to TCB i.e. TEMPO2 standard */
241 }
242 } else { /* don't recognise units type, so default to the original code */
243 hetParams.ttype = TIMECORRECTION_ORIGINAL;
244 }
245 } else {
246 hetParams.timeCorrFile = NULL;
247 hetParams.ttype = TIMECORRECTION_ORIGINAL;
248 }
249 }
250
251 /* get science segment lists - allocate initial memory for starts and stops */
252 if ( ( starts = XLALCreateINT4Vector( 1 ) ) == NULL ||
253 ( stops = XLALCreateINT4Vector( 1 ) ) == NULL ) {
254 XLALPrintError( "Error, allocating segment list memory.\n" );
255 }
256 numSegs = get_segment_list( starts, stops, inputParams.segfile,
257 inputParams.heterodyneflag );
258 if ( ( starts = XLALResizeINT4Vector( starts, numSegs ) ) == NULL ||
259 ( stops = XLALResizeINT4Vector( stops, numSegs ) ) == NULL ) {
260 XLALPrintError( "Error, re-allocating segment list memory.\n" );
261 }
262
263 if ( verbose ) {
264 fprintf( stderr, "I've read in the segment list.\n" );
265 }
266
267 if ( inputParams.heterodyneflag == 0 || inputParams.heterodyneflag == 3 ) {
268 /* input comes from frame files so read in frame filenames */
269 if ( ( cache = XLALCacheImport( inputParams.datafile ) ) == NULL ) {
270 fprintf( stderr, "Error... There's been a problem reading in the frame \
271data!\n" );
272 return 1;
273 }
274
275 if ( verbose ) {
276 fprintf( stderr, "I've read in the frame list.\n" );
277 }
278 }
279
280 if ( inputParams.heterodyneflag == 1 || inputParams.heterodyneflag == 2 ||
281 inputParams.heterodyneflag == 4 ) {
282 if ( inputParams.filterknee == 0. ) {
283 fprintf( stderr, "REMINDER: You aren't giving a filter knee frequency from\
284 the coarse heterodyne stage! You could be reheterodyning data that has\
285 already had the filter response removed, but are you sure this is what you're\
286 doing?\n" );
287 }
288
289 /* calculate the frequency and phase response of the filter used in the
290 coarse heterodyne */
291 filtresp = create_filter_response( inputParams.filterknee );
292
293 /* reset the filter knee to zero so the filtering is not performed on the
294 fine heterodyned data*/
295 inputParams.filterknee = 0.;
296 }
297
298 /************************BIT THAT DOES EVERYTHING****************************/
299
300 /* set filters - values held for the whole data set so we don't get lots of
301 glitches from the filter ringing */
302 if ( inputParams.filterknee > 0.0 ) {
303 set_filters( &iirFilters, inputParams.filterknee, inputParams.samplerate );
304 if ( verbose ) {
305 fprintf( stderr, "I've set up the filters.\n" );
306 }
307 }
308
309 /* set output file */
310 snprintf( outputfile, sizeof( outputfile ), "%s", inputParams.outputfile );
311
312 // check if output should be gzipped due to ".gz" suffix on file name */
313 if ( XLALStringCaseSubstring( outputfile, ".gz" ) != NULL ) {
314 if ( inputParams.binaryoutput ) {
315 XLALPrintError( "Error... do not use a \".gz\" file extension for a binary output file\n" );
316 }
317
318 inputParams.gzipoutput = 1;
319 // remove ".gz" suffix
320 CHAR *strloc = XLALStringCaseSubstring( outputfile, ".gz" );
321 strloc[0] = '\0';
322 }
323
324 /* add header to the files: header information will be a string consisting of several lines starting with %%s.
325 * - the first line will contain the time and date of the file creation
326 * - the next set of lines will contain the version and git hash of the lalsuite versions
327 * - the penulimate line will contain the command line inputs used to create the file
328 * - the final will contain headers for the three columns in the file: GPS time, Real, Imag */
329 if ( ( fpout = fopen( outputfile, "w" ) ) == NULL ) {
330 fprintf( stderr, "Error... can't open output file %s!\n", outputfile );
331 return 0;
332 }
333
334 CHAR *headerinfo = XLALStringDuplicate( "%% File created on " );
335 headerinfo = XLALStringAppend( headerinfo, LogTimeToString( XLALGetTimeOfDay() ) );
336 headerinfo = XLALStringAppend( headerinfo, "\n" );
337 headerinfo = XLALStringAppend( headerinfo, XLALVCSInfoString( lalPulsarVCSInfoList, 0, "%% " ) );
338 headerinfo = XLALStringAppend( headerinfo, "%% " );
339 for ( INT4 j = 0; j < argc; j++ ) {
340 headerinfo = XLALStringAppend( headerinfo, argv[j] );
341 headerinfo = XLALStringAppend( headerinfo, " " );
342 }
343 CHAR dataline[] = "\n%% GPS time\tReal\tImag\n";
344 if ( strlen( headerinfo ) + strlen( dataline ) > HEADERSIZE ) {
345 fprintf( stderr, "Error... HEADERSIZE needs to be increased to accommodate information\n" );
346 return 0;
347 } else {
348 /* fill in rest of string with whitespace */
349 for ( INT4 j = strlen( headerinfo ); j < HEADERSIZE; j++ ) {
350 headerinfo = XLALStringAppend( headerinfo, " " );
351 }
352 memcpy( &headerinfo[HEADERSIZE - strlen( dataline )], &dataline[0], sizeof( CHAR )*strlen( dataline ) );
353
354 /* output the header to the file */
355 size_t rc = fwrite( &headerinfo[0], sizeof( CHAR ), HEADERSIZE, fpout );
356 if ( ferror( fpout ) || !rc ) {
357 fprintf( stderr, "Error... problem writing out header data!\n" );
358 exit( 1 );
359 }
360 }
361 XLALFree( headerinfo );
362 fclose( fpout );
363
364 snprintf( channel, sizeof( channel ), "%s", inputParams.channel );
365
366#if TRACKMEMUSE
367 fprintf( stderr, "Memory use before entering main loop:\n" );
368 printmemuse();
369#endif
370
371 /* loop through file and read in data */
372 /* if the file is a list of frame files read science segment at a time and
373 perform the heterodyne on that set of data - this will only contain a real
374 component - plus remember read in double precision for GEO and LIGO h(t)
375 and, single precision for uncalibrated LIGO data. If the file is already
376 heterodyned it will be complex and we can read the whole file in in one go
377 as it should be significantly downsampled */
378 do {
379 COMPLEX16TimeSeries *data = NULL; /* data for heterodyning */
380 COMPLEX16TimeSeries *resampData = NULL; /* resampled data */
381 REAL8Vector *times = NULL; /*times of data read from coarse heterodyne file*/
382 INT4 i;
383
384 if ( inputParams.heterodyneflag == 0 || inputParams.heterodyneflag == 3 ) {
385 /* i.e. reading from frame files */
388 REAL8TimeSeries *datareal = NULL;
389 LALCache *smalllist = NULL; /* list of frame files for a science segment */
390 LIGOTimeGPS epochdummy;
391
392 epochdummy.gpsSeconds = 0;
393 epochdummy.gpsNanoSeconds = 0;
394
395 /* if the seg list has segment before the start time of the available
396 data frame then increment the segment and continue */
397 if ( stops->data[count] <= cache->list[0].t0 ) {
398 count++;
399 continue;
400 }
401 /* if there are segments after the last available data from then break */
402 if ( cache->list[cache->length - 1].t0 + cache->list[cache->length - 1].dt <=
403 starts->data[count] ) {
404 break;
405 }
406
407 if ( ( duration = stops->data[count] - starts->data[count] ) > inputParams.datachunklength ) {
408 duration = inputParams.datachunklength;
409 } /* if duration of science segment is large
410 just get part of it */
411
412 fprintf( stderr, "Getting data between %d and %d.\n", starts->data[count],
413 starts->data[count] + duration );
414
415 hetParams.timestamp = ( REAL8 )starts->data[count];
416 hetParams.length = inputParams.samplerate * duration;
417 gpstime = ( REAL8 )starts->data[count];
418
419 /* if there was no frame file for that segment move on */
420 if ( ( smalllist = set_frame_files( &starts->data[count], &stops->data[count],
421 cache, &count, inputParams.datachunklength ) ) == NULL ) {
422 /* if there was no frame file for that segment move on */
423 fprintf( stderr, "Error... no frame files listed between %d and %d.\n",
424 ( INT4 )gpstime, ( INT4 )gpstime + duration );
425
426 if ( count < numSegs ) {
427 count++;/*if not finished reading in all data try next set of frames*/
428
429 continue;
430 } else {
431 break;
432 }
433 }
434
435 /* make vector (make sure imaginary parts are set to zero) */
436 if ( ( data = XLALCreateCOMPLEX16TimeSeries( "", &epochdummy,
437 PulsarGetREAL8VectorParamIndividual( hetParams.het, "F0" ), 1. / inputParams.samplerate, &lalSecondUnit,
438 ( INT4 )inputParams.samplerate * duration ) ) == NULL ) {
439 XLALPrintError( "Error allocating data memory.\n" );
440 }
441
442 /* read in frame data */
443 if ( ( datareal = get_frame_data( smalllist, channel, gpstime,
444 inputParams.samplerate * duration, duration, inputParams.samplerate,
445 inputParams.scaleFac, inputParams.highPass ) ) == NULL ) {
446 fprintf( stderr, "Error... could not open frame files between %d and \
447%d.\n", ( INT4 )gpstime, ( INT4 )gpstime + duration );
448
449 if ( count < numSegs ) {
450 count++;/*if not finished reading in all data try next set of frames*/
451
453
454 XLALDestroyCache( smalllist );
455
456 continue;
457 } else {
459 break; /* if at the end of data anyway then break */
460 }
461 }
462
463 /* if any data has successfully been read-in set flag to 0 */
464 nodata = 0;
465
466 /* put data into COMPLEX16 vector and set imaginary parts to zero */
467 for ( i = 0; i < inputParams.samplerate * duration; i++ ) {
468 data->data->data[i] = ( REAL8 )datareal->data->data[i];
469 }
470
471 XLALDestroyREAL8TimeSeries( datareal );
472
473 XLALDestroyCache( smalllist );
474
475 count++;
476 } else if ( inputParams.heterodyneflag == 1 ||
477 inputParams.heterodyneflag == 2 || inputParams.heterodyneflag == 4 ) {
478 /* i.e. reading from a heterodyned file */
479 REAL8 temptime = 0.; /* temporary time storage variable */
480 LIGOTimeGPS epochdummy;
481
482 epochdummy.gpsSeconds = 0;
483 epochdummy.gpsNanoSeconds = 0;
484
485 if ( ( data = XLALCreateCOMPLEX16TimeSeries( "", &epochdummy,
486 PulsarGetREAL8VectorParamIndividual( hetParams.het, "F0" ), 1. / inputParams.samplerate, &lalSecondUnit, 1 ) )
487 == NULL || ( times = XLALCreateREAL8Vector( 1 ) ) == NULL ) {
488 XLALPrintError( "Error allocating memory for data.\n" );
489 }
490 i = 0;
491
492 fprintf( stderr, "Reading heterodyned data from %s.\n", inputParams.datafile );
493
494 /* open input file */
495 if ( ( fpin = XLALFileOpen( inputParams.datafile, "r" ) ) == NULL ) {
496 fprintf( stderr, "Error... Can't open input data file!\n" );
497 return 1;
498 }
499
500 /* read in header info (if not working on legacy files without the header) */
501 CHAR headerdata[HEADERSIZE];
502 if ( !inputParams.legacyinput ) {
503 size_t rch = XLALFileRead( ( void * )&headerdata[0], sizeof( CHAR ), HEADERSIZE, fpin );
504 if ( !rch ) {
505 fprintf( stderr, "Error... problem reading in header data!\n" );
506 exit( 1 );
507 }
508 }
509
510 /* read in file - depends on if file is binary or not */
511 if ( inputParams.binaryinput ) {
512 INT4 memcount = 1;
513
514 do {
515 size_t rc;
516 REAL8 reVal, imVal;
517 rc = XLALFileRead( ( void * )&times->data[i], sizeof( REAL8 ), 1, fpin );
518 rc = XLALFileRead( ( void * )&reVal, sizeof( REAL8 ), 1, fpin );
519 rc = XLALFileRead( ( void * )&imVal, sizeof( REAL8 ), 1, fpin );
520
521 if ( XLALFileEOF( fpin ) || rc == 0 ) {
522 break;
523 }
524
525 /* check that data is finite (and not unrealistically large) and not NaN */
526 if ( !isfinite( reVal ) || !isfinite( imVal ) || fabs( reVal ) > 1. || fabs( imVal ) > 1. ) {
527 continue;
528 }
529
530 if ( inputParams.scaleFac > 1.0 ) {
531 reVal *= inputParams.scaleFac;
532 imVal *= inputParams.scaleFac;
533 }
534
535 data->data->data[i] = reVal + I * imVal;
536
537 /* make sure data doesn't overlap previous data */
538 if ( times->data[i] > temptime ) {
539 temptime = times->data[i];
540 i++;
541 } else {
542 continue;
543 }
544
545 /* dynamically allocate memory 2^20 lines at a time */
546 if ( ( i == 1 ) || ( i % MAXALLOC == 0 ) ) {
547 if ( ( times = XLALResizeREAL8Vector( times, MAXALLOC * memcount ) ) == NULL
549 MAXALLOC * memcount ) ) == NULL ) {
550 XLALPrintError( "Error resizing data memory.\n" );
551 }
552 memcount++;
553 }
554 } while ( !XLALFileEOF( fpin ) );
555 } else {
556 INT4 memcount = 1;
557 REAL8 reVal, imVal;
558
559 do {
560 CHAR linebuf[256];
561 if ( XLALFileGets( &linebuf[0], 256, fpin ) == NULL ) {
562 // skip this line
563 continue;
564 }
565
566 if ( sscanf( linebuf, "%lf%lf%lf", &times->data[i], &reVal, &imVal ) != 3 ) {
567 // skip this line
568 continue;
569 }
570
571 /* check that data is finite (and not unrealistically large) and not NaN */
572 if ( !isfinite( reVal ) || !isfinite( imVal ) || fabs( reVal ) > 1. || fabs( imVal ) > 1. ) {
573 continue;
574 }
575
576 if ( inputParams.scaleFac > 1.0 ) {
577 reVal *= inputParams.scaleFac;
578 imVal *= inputParams.scaleFac;
579 }
580
581 data->data->data[i] = reVal + I * imVal;
582
583 /* make sure data doesn't overlap previous data */
584 if ( times->data[i] > temptime ) {
585 temptime = times->data[i];
586 i++;
587 } else {
588 continue;
589 }
590
591 /* dynamically allocate memory 2^20 lines at a time */
592 if ( ( i == 1 ) || ( i % MAXALLOC == 0 ) ) {
593 if ( ( times = XLALResizeREAL8Vector( times, MAXALLOC * memcount ) ) == NULL
595 MAXALLOC * memcount ) ) == NULL ) {
596 XLALPrintError( "Error resizing data memory.\n" );
597 }
598 memcount++;
599 }
600 } while ( !XLALFileEOF( fpin ) );
601 }
602
603 XLALFileClose( fpin );
604
605 hetParams.timestamp = times->data[0]; /* set initial time stamp */
606
607 /* resize vector to actual size */
608 if ( ( data = XLALResizeCOMPLEX16TimeSeries( data, 0, i ) ) == NULL ||
609 ( times = XLALResizeREAL8Vector( times, i ) ) == NULL ) {
610 XLALPrintError( "Error resizing data memory.\n" );
611 }
612 hetParams.length = i;
613
614 if ( verbose ) {
615 fprintf( stderr, "I've read in the fine heterodyne data.\n" );
616 }
617 } else {
618 fprintf( stderr, "Error... Heterodyne flag = %d, should be 0, 1, 2, 3 or 4.\n", inputParams.heterodyneflag );
619 return 0;
620 }
621
622 XLALGPSSetREAL8( &data->epoch, hetParams.timestamp );
623
624 /* heterodyne data */
625 heterodyne_data( data, times, hetParams, inputParams.freqfactor, filtresp );
626 if ( verbose ) {
627 fprintf( stderr, "I've heterodyned the data.\n" );
628 }
629
630 /* filter data */
631 if ( inputParams.filterknee > 0. ) { /* filter if knee frequency is not zero */
632 filter_data( data, &iirFilters );
633
634 if ( verbose ) {
635 fprintf( stderr, "I've low pass filtered the data at %.2lf Hz\n", inputParams.filterknee );
636 }
637 }
638
639 if ( inputParams.heterodyneflag == 0 || inputParams.heterodyneflag == 3 )
640 if ( ( times = XLALCreateREAL8Vector( data->data->length ) ) == NULL ) {
641 XLALPrintError( "Error creating vector of data times.\n" );
642 }
643
644 /* resample data and data times */
645 resampData = resample_data( data, times, starts, stops,
646 inputParams.samplerate, inputParams.resamplerate,
647 inputParams.heterodyneflag );
648 if ( verbose ) {
649 fprintf( stderr, "I've resampled the data from %.2lf to %.4lf Hz\n", inputParams.samplerate, inputParams.resamplerate );
650 }
651
653
654 /*perform outlier removal twice incase very large outliers skew the stddev*/
655 if ( inputParams.stddevthresh != 0. ) {
656 INT4 numOutliers = 0;
657 numOutliers = remove_outliers( resampData, times,
658 inputParams.stddevthresh );
659 if ( verbose ) {
660 fprintf( stderr, "I've removed %lf%% of data above the threshold %.1lf sigma for 1st time.\n",
661 100.*( double )numOutliers / ( double )resampData->data->length,
662 inputParams.stddevthresh );
663 }
664 }
665
666 /* calibrate */
667 if ( inputParams.calibrate ) {
668 calibrate( resampData, times, inputParams.calibfiles,
669 inputParams.freqfactor * PulsarGetREAL8VectorParamIndividual( hetParams.het, "F0" ), inputParams.channel );
670 if ( verbose ) {
671 fprintf( stderr, "I've calibrated the data at %.1lf Hz\n", inputParams.freqfactor * PulsarGetREAL8VectorParamIndividual( hetParams.het, "F0" ) );
672 }
673 }
674
675 /* remove outliers above our threshold */
676 if ( inputParams.stddevthresh != 0. ) {
677 INT4 numOutliers = 0;
678 numOutliers = remove_outliers( resampData, times,
679 inputParams.stddevthresh );
680 if ( verbose ) {
681 fprintf( stderr, "I've removed %lf%% of data above the threshold %.1lf sigma for 2nd time.\n",
682 100.*( double )numOutliers / ( double )resampData->data->length,
683 inputParams.stddevthresh );
684 }
685 }
686
687 /* output data */
688 if ( inputParams.binaryoutput ) {
689 if ( ( fpout = fopen( outputfile, "ab" ) ) == NULL ) {
690 fprintf( stderr, "Error... can't open output file %s!\n", outputfile );
691 return 0;
692 }
693 } else {
694 if ( ( fpout = fopen( outputfile, "a" ) ) == NULL ) {
695 fprintf( stderr, "Error... can't open output file %s!\n", outputfile );
696 return 0;
697 }
698 }
699
700 /* buffer the output, so that file system is not thrashed when outputing */
701 /* buffer will be 1Mb */
702 if ( setvbuf( fpout, NULL, _IOFBF, 0x100000 ) ) {
703 fprintf( stderr, "Warning: Unable to set output file buffer!" );
704 }
705
706 for ( i = 0; i < ( INT4 )resampData->data->length; i++ ) {
707 /* if data has been scaled then undo scaling for output */
708
709 if ( inputParams.binaryoutput ) {
710 size_t rc = 0;
711 REAL8 tempreal, tempimag;
712
713 tempreal = creal( resampData->data->data[i] );
714 tempimag = cimag( resampData->data->data[i] );
715
716 /* binary output will be same as ASCII text - time real imag */
717 if ( inputParams.scaleFac > 1.0 ) {
718 tempreal /= inputParams.scaleFac;
719 tempimag /= inputParams.scaleFac;
720 }
721
722 rc = fwrite( &times->data[i], sizeof( REAL8 ), 1, fpout );
723 rc = fwrite( &tempreal, sizeof( REAL8 ), 1, fpout );
724 rc = fwrite( &tempimag, sizeof( REAL8 ), 1, fpout );
725
726 if ( ferror( fpout ) || !rc ) {
727 fprintf( stderr, "Error... problem writing out data to binary file!\n" );
728 exit( 1 );
729 }
730 } else {
731 if ( inputParams.scaleFac > 1.0 ) {
732 fprintf( fpout, "%lf\t%le\t%le\n", times->data[i],
733 creal( resampData->data->data[i] ) / inputParams.scaleFac,
734 cimag( resampData->data->data[i] ) / inputParams.scaleFac );
735 } else {
736 fprintf( fpout, "%lf\t%le\t%le\n", times->data[i],
737 creal( resampData->data->data[i] ), cimag( resampData->data->data[i] ) );
738 }
739 }
740
741 }
742 if ( verbose ) {
743 fprintf( stderr, "I've output the data.\n" );
744 }
745
746 fclose( fpout );
747
748 XLALDestroyCOMPLEX16TimeSeries( resampData );
749
750 XLALDestroyREAL8Vector( times );
751 } while ( count < numSegs && ( inputParams.heterodyneflag == 0 || inputParams.heterodyneflag == 3 ) );
752
753 /* check if any data has been read - if not exit with an error */
754 if ( nodata && ( inputParams.heterodyneflag == 0 || inputParams.heterodyneflag == 3 ) ) {
755 fprintf( stderr, "Error... no data was read in.\n" );
756 exit( 1 );
757 }
758
759 /* check whether to gzip the output */
760 if ( !inputParams.binaryoutput && inputParams.gzipoutput ) {
761 fprintf( stderr, "Outputing %s to gzipped file\n", outputfile );
762 if ( XLALGzipTextFile( outputfile ) != XLAL_SUCCESS ) { // gzip it
763 XLALPrintError( "Error... problem gzipping the output file.\n" );
764 }
765 }
766
767#if TRACKMEMUSE
768 fprintf( stderr, "Memory usage after completion of main loop:\n" );
769 printmemuse();
770#endif
771
772 fprintf( stderr, "Heterodyning complete.\n" );
773
774 XLALDestroyINT4Vector( stops );
775 XLALDestroyINT4Vector( starts );
776
777 if ( inputParams.heterodyneflag == 0 || inputParams.heterodyneflag == 3 ) {
779 }
780
781 if ( inputParams.filterknee > 0. ) {
788
789 if ( verbose ) {
790 fprintf( stderr, "I've destroyed all filters.\n" );
791 }
792 }
793
794 if ( filtresp != NULL ) {
795 destroy_filter_response( filtresp );
796 }
797
798 PulsarFreeParams( hetParams.het );
799 if ( inputParams.heterodyneflag == 2 || inputParams.heterodyneflag == 4 ) {
800 PulsarFreeParams( hetParams.hetUpdate );
801 }
802
803#if TRACKMEMUSE
804 fprintf( stderr, "Memory use at the end of the code:\n" );
805 printmemuse();
806#endif
807
808 return 0;
809}
810
811/* function to parse the input arguments */
812void get_input_args( InputParams *inputParams, int argc, char *argv[] )
813{
814 struct LALoption long_options[] = {
815 { "help", no_argument, 0, 'h' },
816 { "ifo", required_argument, 0, 'i' },
817 { "pulsar", required_argument, 0, 'p' },
818 { "heterodyne-flag", required_argument, 0, 'z' },
819 { "param-file", required_argument, 0, 'f' },
820 { "param-file-update", required_argument, 0, 'g' },
821 { "filter-knee", required_argument, 0, 'k' },
822 { "sample-rate", required_argument, 0, 's' },
823 { "resample-rate", required_argument, 0, 'r' },
824 { "data-file", required_argument, 0, 'd' },
825 { "data-chunk-length", required_argument, 0, 'D' },
826 { "channel", required_argument, 0, 'c' },
827 { "output-file", required_argument, 0, 'o' },
828 { "ephem-earth-file", required_argument, 0, 'e' },
829 { "ephem-sun-file", required_argument, 0, 'S' },
830 { "ephem-time-file", required_argument, 0, 't' },
831 { "seg-file", required_argument, 0, 'l' },
832 { "calibrate", no_argument, NULL, 'A' },
833 { "response-file", required_argument, 0, 'R' },
834 { "coefficient-file", required_argument, 0, 'C' },
835 { "sensing-function", required_argument, 0, 'F' },
836 { "open-loop-gain", required_argument, 0, 'O' },
837 { "stddev-thresh", required_argument, 0, 'T' },
838 { "freq-factor", required_argument, 0, 'm' },
839 { "scale-factor", required_argument, 0, 'G' },
840 { "high-pass-freq", required_argument, 0, 'H' },
841 { "manual-epoch", required_argument, 0, 'M' },
842 { "binary-input", no_argument, NULL, 'B' },
843 { "binary-output", no_argument, NULL, 'b' },
844 { "gzip-output", no_argument, NULL, 'Z' },
845 { "legacy-input", no_argument, NULL, 'L' },
846 { "verbose", no_argument, NULL, 'v' },
847 { "output-phase", no_argument, NULL, 'P' },
848 { 0, 0, 0, 0 }
849 };
850
851 char args[] = "hi:p:z:f:g:k:s:r:d:D:c:o:e:S:t:l:R:C:F:O:T:m:G:H:M:ABbZLvP";
852 char *program = argv[0];
853
854 /* set defaults */
855 inputParams->pulsar = NULL;
856 inputParams->filterknee = 0.; /* default is not to filter */
857 inputParams->resamplerate = 0.; /* resample to 1 Hz */
858 inputParams->samplerate = 0.;
859 inputParams->calibrate = 0; /* default is not to calibrate */
860 inputParams->verbose = 0; /* default is not to do verbose */
861 inputParams->binaryinput = 0; /* default to NOT read in data from a binary file */
862 inputParams->legacyinput = 0; /* default is that input files are not legacy files without the header information */
863 inputParams->outputPhase = 0; /* default to not output the phase evolution */
864 inputParams->binaryoutput = 0; /* default is to output data as ASCII text */
865 inputParams->gzipoutput = 0; /* default is to not gzip the output */
866 inputParams->stddevthresh = 0.; /* default is not to threshold */
867 inputParams->calibfiles.calibcoefficientfile = NULL;
868 inputParams->calibfiles.sensingfunctionfile = NULL;
869 inputParams->calibfiles.openloopgainfile = NULL;
870 inputParams->calibfiles.responsefunctionfile = NULL;
871 inputParams->datachunklength = MAXDATALENGTH; /* default to MAXDATALENGTH */
872
873 inputParams->freqfactor = 2.0; /* default is to look for gws at twice the
874pulsar spin frequency */
875
876 inputParams->scaleFac = 1.0; /* default scaling for calibrated GEO data */
877 inputParams->highPass = 0.; /* default to not high-pass GEO data */
878
879 inputParams->manualEpoch = 0.; /* default to zero i.e. it takes the epoch from
880the pulsar parameter file */
881 /* channel defaults to DARM_ERR */
882 snprintf( inputParams->channel, sizeof( inputParams->channel ), "DARM_ERR" );
883
884 inputParams->timeCorrFile = NULL;
885
886 /* get input arguments */
887 while ( 1 ) {
888 int option_index = 0;
889 int c;
890
891 c = LALgetopt_long( argc, argv, args, long_options, &option_index );
892 if ( c == -1 ) { /* end of options */
893 break;
894 }
895
896 switch ( c ) {
897 case 0: /* if option set a flag, nothing else to do */
898 if ( long_options[option_index].flag ) {
899 break;
900 } else
901 fprintf( stderr, "Error parsing option %s with argument %s\n",
902 long_options[option_index].name, LALoptarg );
903 break;
904 case 'h': /* help message */
905 fprintf( stderr, USAGE, program );
906 exit( 0 );
907 case 'v': /* verbose output */
908 inputParams->verbose = 1;
909 break;
910 case 'i': /* interferometer */
911 snprintf( inputParams->ifo, sizeof( inputParams->ifo ), "%s", LALoptarg );
912 break;
913 case 'z': /* heterodyne flag - 0 for coarse, 1 for fine, 2 for update to
914 params, 3 for a one step fine heteroydne (like old code)*/
915 inputParams->heterodyneflag = atoi( LALoptarg );
916 break;
917 case 'p': /* pulsar name */
918 inputParams->pulsar = XLALStringDuplicate( LALoptarg );
919 break;
920 case 'A': /* calibration flag */
921 inputParams->calibrate = 1;
922 break;
923 case 'B': /* input file is binary format */
924 inputParams->binaryinput = 1;
925 break;
926 case 'b': /* output file is to be in binary format */
927 inputParams->binaryoutput = 1;
928 break;
929 case 'Z': /* gzip output ascii text file */
930 inputParams->gzipoutput = 1;
931 break;
932 case 'f': /* initial heterodyne parameter file */
933 snprintf( inputParams->paramfile, sizeof( inputParams->paramfile ), "%s",
934 LALoptarg );
935 break;
936 case 'g': /*secondary heterodyne parameter file - for updated parameters*/
937 snprintf( inputParams->paramfileupdate,
938 sizeof( inputParams->paramfileupdate ), "%s", LALoptarg );
939 break;
940 case 'k': { /* low-pass filter knee frequency */
941 /* find if the string contains a / and get its position */
942 CHAR *loc = NULL;
943 CHAR numerator[10] = "", *denominator = NULL;
944 INT4 n;
945
946 if ( ( loc = strchr( LALoptarg, '/' ) ) != NULL ) {
947 n = loc - LALoptarg; /* length of numerator i.e. bit before / */
948 XLALStringCopy( numerator, LALoptarg, n + 1 );
949
950 /*set the denominator i.e. the point after / */
951 denominator = XLALStringDuplicate( loc + 1 );
952
953 inputParams->filterknee = atof( numerator ) / atof( denominator );
954 } else {
955 inputParams->filterknee = atof( LALoptarg );
956 }
957 }
958 break;
959 case 's': { /* sample rate of input data */
960 /* find if the string contains a / and get its position */
961 CHAR *loc = NULL;
962 CHAR numerator[10] = "", *denominator = NULL;
963 INT4 n;
964
965 if ( ( loc = strchr( LALoptarg, '/' ) ) != NULL ) {
966 n = loc - LALoptarg; /* length of numerator i.e. bit before / */
967 XLALStringCopy( numerator, LALoptarg, n + 1 );
968
969 denominator = XLALStringDuplicate( loc + 1 );
970
971 inputParams->samplerate = atof( numerator ) / atof( denominator );
972 } else {
973 inputParams->samplerate = atof( LALoptarg );
974 }
975 }
976 break;
977 case 'r': { /* resample rate - allow fractions e.g. 1/60 Hz*/
978 /* find if the string contains a / and get its position */
979 CHAR *loc = NULL;
980 CHAR numerator[10] = "", *denominator = NULL;
981 INT4 n;
982
983 if ( ( loc = strchr( LALoptarg, '/' ) ) != NULL ) {
984 n = loc - LALoptarg; /* length of numerator i.e. bit before / */
985 XLALStringCopy( numerator, LALoptarg, n + 1 );
986
987 denominator = XLALStringDuplicate( loc + 1 );
988
989 inputParams->resamplerate = atof( numerator ) / atof( denominator );
990 } else {
991 inputParams->resamplerate = atof( LALoptarg );
992 }
993 }
994 break;
995 case 'd': /* file containing list of frame files, or file with previously
996 heterodyned data */
997 snprintf( inputParams->datafile, sizeof( inputParams->datafile ), "%s",
998 LALoptarg );
999 break;
1000 case 'D': /* set the maximum data chunk length for reading in */
1001 inputParams->datachunklength = atoi( LALoptarg );
1002 break;
1003 case 'c': /* frame channel */
1004 snprintf( inputParams->channel, sizeof( inputParams->channel ), "%s",
1005 LALoptarg );
1006 break;
1007 case 'o': /* output data directory */
1008 snprintf( inputParams->outputfile, sizeof( inputParams->outputfile ), "%s",
1009 LALoptarg );
1010 break;
1011 case 'e': /* earth ephemeris file */
1012 snprintf( inputParams->earthfile, sizeof( inputParams->earthfile ), "%s",
1013 LALoptarg );
1014 break;
1015 case 'S': /* sun ephemeris file */
1016 snprintf( inputParams->sunfile, sizeof( inputParams->sunfile ), "%s",
1017 LALoptarg );
1018 break;
1019 case 't': /* Einstein delay time correction file */
1020 inputParams->timeCorrFile = XLALStringDuplicate( LALoptarg );
1021 break;
1022 case 'l':
1023 snprintf( inputParams->segfile, sizeof( inputParams->segfile ), "%s",
1024 LALoptarg );
1025 break;
1026 case 'R':
1028 break;
1029 case 'C':
1031 break;
1032 case 'F':
1034 break;
1035 case 'O':
1036 inputParams->calibfiles.openloopgainfile = LALoptarg;
1037 break;
1038 case 'T':
1039 inputParams->stddevthresh = atof( LALoptarg );
1040 break;
1041 case 'm': /* this can be defined as a real number or fraction e.g. 2.0 or
1042 4/3 */
1043 {/* find if the string contains a / and get its position */
1044 CHAR *loc = NULL;
1045 CHAR numerator[10] = "", *denominator = NULL;
1046 INT4 n;
1047
1048 if ( ( loc = strchr( LALoptarg, '/' ) ) != NULL ) {
1049 n = loc - LALoptarg; /* length of numerator i.e. bit before / */
1050
1051 XLALStringCopy( numerator, LALoptarg, n + 1 );
1052
1053 denominator = XLALStringDuplicate( loc + 1 );
1054
1055 inputParams->freqfactor = atof( numerator ) / atof( denominator );
1056 } else {
1057 inputParams->freqfactor = atof( LALoptarg );
1058 }
1059 }
1060 break;
1061 case 'G':
1062 inputParams->scaleFac = atof( LALoptarg );
1063 break;
1064 case 'H':
1065 inputParams->highPass = atof( LALoptarg );
1066 break;
1067 case 'M':
1068 inputParams->manualEpoch = atof( LALoptarg );
1069 break;
1070 case 'L':
1071 inputParams->legacyinput = 1;
1072 break;
1073 case 'P':
1074 inputParams->outputPhase = 1;
1075 break;
1076 case '?':
1077 fprintf( stderr, "unknown error while parsing options\n" );
1078 break;
1079 default:
1080 fprintf( stderr, "unknown error while parsing options\n" );
1081 break;
1082 }
1083 }
1084
1085 /* set more defaults */
1086 /*if the sample rate or resample rate hasn't been defined give error */
1087 if ( inputParams->samplerate == 0. || inputParams->resamplerate == 0. ) {
1088 fprintf( stderr, "Error... sample rate and/or resample rate has not been \
1089defined.\n" );
1090 exit( 1 );
1091 } else if ( inputParams->samplerate < inputParams->resamplerate ) {
1092 /* if sr is less than rsr give error */
1093 fprintf( stderr, "Error... sample rate is less than the resample rate.\n" );
1094 exit( 1 );
1095 }
1096
1097 /* FIXME: This check (fmod) doesn't work if any optimisation flags are set
1098 when compiling!! */
1099 /* check that sample rate / resample rate is an integer */
1100 /*if(fmod(inputParams->samplerate/inputParams->resamplerate, 1.) > 0.){
1101 fprintf(stderr, "Error... invalid sample rates.\n");
1102 exit(0);
1103 }*/
1104
1105 if ( inputParams->datachunklength <= 0 ) {
1106 fprintf( stderr, "Error... data chunk length must be greater than zero.\n" );
1107 exit( 1 );
1108 }
1109
1110 if ( inputParams->freqfactor < 0. ) {
1111 fprintf( stderr, "Error... frequency factor must be greater than zero.\n" );
1112 exit( 1 );
1113 }
1114
1115 /* check that we're not trying to set a binary file input for a coarse
1116 heterodyne */
1117 if ( inputParams->binaryinput ) {
1118 if ( inputParams->heterodyneflag == 0 ) {
1119 fprintf( stderr, "Error... binary input should not be set for coarse \
1120heterodyne!\n" );
1121 exit( 1 );
1122 }
1123 }
1124}
1125
1126/* heterodyne data function */
1128 HeterodyneParams hetParams, REAL8 freqfactor, FilterResponse *filtresp )
1129{
1130 REAL8 phaseCoarse = 0., phaseUpdate = 0., deltaphase = 0.;
1131 REAL8 t = 0., t2 = 0., tdt = 0., T0 = 0., T0Update = 0.;
1132 REAL8 dtpos = 0.; /* time between position epoch and data timestamp */
1133 INT4 i = 0;
1134
1135 EphemerisData *edat = NULL;
1136 TimeCorrectionData *tdat = NULL;
1137 BarycenterInput baryinput, baryinput2;
1138 EarthState earth, earth2;
1139 EmissionTime emit, emit2;
1140
1141 BinaryPulsarInput binInput, binInput2;
1142 BinaryPulsarOutput binOutput, binOutput2;
1143
1144 COMPLEX16 dataTemp, dataTemp2;
1145
1146 REAL8 df = 0., fcoarse = 0., ffine = 0., resp = 0., srate = 0.;
1147 REAL8 filtphase = 0.;
1148 UINT4 position = 0, middle = 0;
1149
1150 REAL8 om = PulsarGetREAL8ParamOrZero( hetParams.het, "WAVE_OM" ), omu = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "WAVE_OM" );
1151
1152 FILE *fpphase = NULL;
1153
1154 /* set the position, frequency and whitening epochs if not already set */
1155 REAL8 pepoch = 0., pepochu = 0., posepoch = 0., posepochu = 0.;
1156 pepoch = PulsarGetREAL8ParamOrZero( hetParams.het, "PEPOCH" );
1157 posepoch = PulsarGetREAL8ParamOrZero( hetParams.het, "POSEPOCH" );
1158 if ( pepoch == 0. && posepoch != 0. ) {
1159 pepoch = posepoch;
1160 } else if ( posepoch == 0. && pepoch != 0. ) {
1161 posepoch = pepoch;
1162 }
1163
1164 REAL8 waveepoch = 0., waveepochu = 0.;
1165 waveepoch = PulsarGetREAL8ParamOrZero( hetParams.het, "WAVEEPOCH" );
1166 if ( PulsarCheckParam( hetParams.het, "WAVESIN" ) && waveepoch == 0. ) {
1167 waveepoch = pepoch;
1168 }
1169
1170 if ( hetParams.heterodyneflag == 1 || hetParams.heterodyneflag == 2 || hetParams.heterodyneflag == 4 ) {
1171 pepochu = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "PEPOCH" );
1172 posepochu = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "POSEPOCH" );
1173 if ( pepochu == 0. && posepochu != 0. ) {
1174 pepochu = posepochu;
1175 } else if ( posepochu == 0. && pepochu != 0. ) {
1176 posepochu = pepochu;
1177 }
1178
1179 waveepochu = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "WAVEEPOCH" );
1180 if ( PulsarCheckParam( hetParams.hetUpdate, "WAVESIN" ) && waveepochu == 0. ) {
1181 waveepochu = pepochu;
1182 }
1183
1184 T0Update = pepochu;
1185 }
1186
1187 T0 = pepoch;
1188
1189 /* set up ephemeris files */
1190 if ( hetParams.heterodyneflag > 0 ) {
1191 XLAL_CHECK_VOID( ( edat = XLALInitBarycenter( hetParams.earthfile, hetParams.sunfile ) ) != NULL, XLAL_EFUNC );
1192
1193 /* get files containing Einstein delay correction look-up table */
1194 if ( hetParams.ttype != TIMECORRECTION_ORIGINAL ) {
1196 hetParams.timeCorrFile ) ) != NULL, XLAL_EFUNC );
1197 }
1198
1199 /* set up location of detector */
1200 baryinput.site.location[0] = hetParams.detector.location[0] / LAL_C_SI;
1201 baryinput.site.location[1] = hetParams.detector.location[1] / LAL_C_SI;
1202 baryinput.site.location[2] = hetParams.detector.location[2] / LAL_C_SI;
1203
1204 /* set 1/distance using parallax value if given - in 1/secs */
1205 if ( hetParams.heterodyneflag != 2 && hetParams.heterodyneflag != 4 ) {
1206 /* not
1207 using updated params */
1208 REAL8 px = PulsarGetREAL8ParamOrZero( hetParams.het, "PX" );
1209 if ( px != 0. ) {
1210 baryinput.dInv = px * ( LAL_C_SI / LAL_AU_SI );
1211 } else {
1212 baryinput.dInv = 0.; /* no parallax */
1213 }
1214 } else { /* using updated params */
1215 REAL8 pxu = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "PX" );
1216 if ( pxu != 0. ) {
1217 baryinput.dInv = pxu * ( LAL_C_SI / LAL_AU_SI );
1218 } else {
1219 baryinput.dInv = 0.; /* no parallax */
1220 }
1221 }
1222 }
1223
1224 REAL8 ra, dec, rau, decu;
1225 if ( PulsarCheckParam( hetParams.het, "RAJ" ) ) {
1226 ra = PulsarGetREAL8Param( hetParams.het, "RAJ" );
1227 } else {
1228 ra = PulsarGetREAL8ParamOrZero( hetParams.het, "RA" );
1229 }
1230 if ( PulsarCheckParam( hetParams.hetUpdate, "RAJ" ) ) {
1231 rau = PulsarGetREAL8Param( hetParams.hetUpdate, "RAJ" );
1232 } else {
1233 rau = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "RA" );
1234 }
1235 if ( PulsarCheckParam( hetParams.het, "DECJ" ) ) {
1236 dec = PulsarGetREAL8Param( hetParams.het, "DECJ" );
1237 } else {
1238 dec = PulsarGetREAL8ParamOrZero( hetParams.het, "DEC" );
1239 }
1240 if ( PulsarCheckParam( hetParams.hetUpdate, "DECJ" ) ) {
1241 decu = PulsarGetREAL8Param( hetParams.hetUpdate, "DECJ" );
1242 } else {
1243 decu = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "DEC" );
1244 }
1245
1246 REAL8 pmra, pmdec, pmrau, pmdecu;
1247 pmra = PulsarGetREAL8ParamOrZero( hetParams.het, "PMRA" );
1248 pmrau = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "PMRA" );
1249 pmdec = PulsarGetREAL8ParamOrZero( hetParams.het, "PMDEC" );
1250 pmdecu = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "PMDEC" );
1251
1252 REAL8 cgw = PulsarGetREAL8ParamOrZero( hetParams.het, "CGW" );
1253 REAL8 cgwu = PulsarGetREAL8ParamOrZero( hetParams.hetUpdate, "CGW" );
1254
1255 const REAL8Vector *freqs = PulsarGetREAL8VectorParam( hetParams.het, "F" );
1256 const REAL8Vector *freqsu = NULL;
1257 if ( PulsarCheckParam( hetParams.hetUpdate, "F" ) ) {
1258 freqsu = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "F" );
1259 }
1260
1261 /* check for glitch parameters */
1262 REAL8 *glep = NULL, *glph = NULL, *glf0 = NULL, *glf1 = NULL, *glf2 = NULL, *glf0d = NULL, *gltd = NULL;
1263 UINT4 glnum = 0;
1264 if ( PulsarCheckParam( hetParams.hetUpdate, "GLEP" ) ) {
1265 const REAL8Vector *gleppars = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "GLEP" );
1266 glnum = gleppars->length;
1267
1268 /* get epochs */
1269 glep = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
1270 for ( i = 0; i < ( INT4 )gleppars->length; i++ ) {
1271 glep[i] = gleppars->data[i];
1272 }
1273
1274 /* get phase offsets */
1275 glph = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
1276 if ( PulsarCheckParam( hetParams.hetUpdate, "GLPH" ) ) {
1277 const REAL8Vector *glpars = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "GLPH" );
1278 for ( i = 0; i < ( INT4 )glpars->length; i++ ) {
1279 glph[i] = glpars->data[i];
1280 }
1281 }
1282
1283 /* get frequencies offsets */
1284 glf0 = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
1285 if ( PulsarCheckParam( hetParams.hetUpdate, "GLF0" ) ) {
1286 const REAL8Vector *glpars = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "GLF0" );
1287 for ( i = 0; i < ( INT4 )glpars->length; i++ ) {
1288 glf0[i] = glpars->data[i];
1289 }
1290 }
1291
1292 /* get frequency derivative offsets */
1293 glf1 = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
1294 if ( PulsarCheckParam( hetParams.hetUpdate, "GLF1" ) ) {
1295 const REAL8Vector *glpars = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "GLF1" );
1296 for ( i = 0; i < ( INT4 )glpars->length; i++ ) {
1297 glf1[i] = glpars->data[i];
1298 }
1299 }
1300
1301 /* get second frequency derivative offsets */
1302 glf2 = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
1303 if ( PulsarCheckParam( hetParams.hetUpdate, "GLF2" ) ) {
1304 const REAL8Vector *glpars = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "GLF2" );
1305 for ( i = 0; i < ( INT4 )glpars->length; i++ ) {
1306 glf2[i] = glpars->data[i];
1307 }
1308 }
1309
1310 /* get decaying frequency component offset derivative */
1311 glf0d = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
1312 if ( PulsarCheckParam( hetParams.hetUpdate, "GLF0D" ) ) {
1313 const REAL8Vector *glpars = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "GLF0D" );
1314 for ( i = 0; i < ( INT4 )glpars->length; i++ ) {
1315 glf0d[i] = glpars->data[i];
1316 }
1317 }
1318
1319 /* get decaying frequency component decay time constant */
1320 gltd = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
1321 if ( PulsarCheckParam( hetParams.hetUpdate, "GLTD" ) ) {
1322 const REAL8Vector *glpars = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "GLTD" );
1323 for ( i = 0; i < ( INT4 )glpars->length; i++ ) {
1324 gltd[i] = glpars->data[i];
1325 }
1326 }
1327 }
1328
1329 if ( hetParams.outputPhase ) {
1330 fpphase = fopen( "phase.txt", "w" );
1331 }
1332
1333 for ( i = 0; i < hetParams.length; i++ ) {
1334
1335 /******************************************************************************/
1336 REAL8 phaseWave = 0.; /* phase of any timing noise whitening parameters */
1337 REAL8 phaseGlitch = 0.; /* phase from any glitches */
1338
1339 /* produce initial heterodyne phase for coarse heterodyne with no time delays */
1340 if ( hetParams.heterodyneflag == 0 ) {
1341 tdt = hetParams.timestamp + ( REAL8 )i / hetParams.samplerate - T0;
1342 } else if ( hetParams.heterodyneflag == 1 || hetParams.heterodyneflag == 2 ) {
1343 tdt = times->data[i] - T0;
1344 }
1345 /* if doing one single heterodyne i.e. het flag = 3 then just calc phaseCoarse at all times */
1346 else if ( hetParams.heterodyneflag == 3 || hetParams.heterodyneflag == 4 ) {
1347 /* set up XLALBarycenter */
1348 dtpos = hetParams.timestamp - posepoch;
1349
1350 /* set up RA, DEC, and distance variables for XLALBarycenter*/
1351 baryinput.delta = dec + dtpos * pmdec;
1352 baryinput.alpha = ra + dtpos * pmra / cos( baryinput.delta );
1353
1354 if ( hetParams.heterodyneflag == 3 ) { /* get data time */
1355 t = hetParams.timestamp + ( REAL8 )i / hetParams.samplerate;
1356 } else {
1357 t = times->data[i];
1358 }
1359
1360 XLALGPSSetREAL8( &baryinput.tgps, t );
1361
1362 XLAL_CHECK_VOID( XLALBarycenterEarthNew( &earth, &baryinput.tgps, edat, tdat, hetParams.ttype ) == XLAL_SUCCESS, XLAL_EFUNC );
1363 XLAL_CHECK_VOID( XLALBarycenter( &emit, &baryinput, &earth ) == XLAL_SUCCESS, XLAL_EFUNC );
1364
1365 /* if binary pulsar add extra time delay */
1366 if ( PulsarCheckParam( hetParams.het, "BINARY" ) ) {
1367 /* input SSB time into binary timing function */
1368 binInput.tb = t + emit.deltaT;
1369 binInput.earth = earth;
1370
1371 /* calculate binary time delay */
1372 XLALBinaryPulsarDeltaTNew( &binOutput, &binInput, hetParams.het );
1373
1374 /* add binary time delay */
1375 tdt = ( t - T0 ) + emit.deltaT + binOutput.deltaT;
1376 } else {
1377 tdt = t - T0 + emit.deltaT;
1378 }
1379
1380 /* add the effect of a variable gravitational wave speed */
1381 if ( cgw > 0. && cgw < 1. ) {
1382 tdt /= cgw;
1383 }
1384
1385 /* check if any timing noise whitening is used */
1386 if ( PulsarCheckParam( hetParams.het, "WAVESIN" ) && PulsarCheckParam( hetParams.het, "WAVECOS" ) ) {
1387 /* dtWave only doesn't include binary corrections as they would
1388 * also be sinusoidal terms */
1389 REAL8 dtWave = ( XLALGPSGetREAL8( &emit.te ) - waveepoch ) / 86400.; /* in days */
1390 REAL8 tWave = 0.;
1391
1392 const REAL8Vector *wavesin = PulsarGetREAL8VectorParam( hetParams.het, "WAVESIN" );
1393 const REAL8Vector *wavecos = PulsarGetREAL8VectorParam( hetParams.het, "WAVECOS" );
1394
1395 for ( UINT4 k = 0; k < wavesin->length; k++ ) {
1396 tWave += wavesin->data[k] * sin( om * ( REAL8 )( k + 1. ) * dtWave ) + wavecos->data[k] * cos( om * ( REAL8 )( k + 1. ) * dtWave );
1397 }
1398 phaseWave = freqs->data[0] * freqfactor * tWave;
1399 }
1400
1401 /* add glitch phase - based on equations in formResiduals.C of TEMPO2 from Eqn 1 of Yu et al (2013) http://ukads.nottingham.ac.uk/abs/2013MNRAS.429..688Y */
1402 phaseGlitch = 0.;
1403 if ( glnum > 0 ) {
1404 for ( UINT4 k = 0; k < glnum; k++ ) {
1405 if ( tdt >= glep[k] - T0 ) {
1406 REAL8 dtg = 0, expd = 1.;
1407 dtg = tdt - ( glep[k] - T0 ); /* time since glitch */
1408 if ( gltd[k] != 0. ) {
1409 expd = exp( -dtg / gltd[k] ); /* decaying part of glitch */
1410 }
1411
1412 phaseGlitch += glph[k] + glf0[k] * dtg + 0.5 * glf1[k] * dtg * dtg + ( 1. / 6. ) * glf2[k] * dtg * dtg * dtg + glf0d[k] * gltd[k] * ( 1. - expd );
1413 }
1414 }
1415 phaseGlitch *= freqfactor;
1416 }
1417 }
1418
1419 /* multiply by 2 to get gw phase */
1420 phaseCoarse = 0.;
1421 REAL8 taylorcoeff = 1.;
1422 REAL8 tdttmp = tdt;
1423 for ( UINT4 k = 0; k < freqs->length; k++ ) {
1424 taylorcoeff /= ( REAL8 )( k + 1 );
1425 phaseCoarse += taylorcoeff * freqs->data[k] * tdttmp;
1426 tdttmp *= tdt;
1427 }
1428 phaseCoarse *= freqfactor;
1429 phaseCoarse += phaseWave + phaseGlitch;
1430
1431 /* don't bother including glitch effects when calculating these frequencies as the effects (for the later filter amplitude and phase corrections) should be small */
1432 taylorcoeff = 1.;
1433 fcoarse = freqs->data[0];
1434 tdttmp = tdt;
1435 for ( UINT4 k = 1; k < freqs->length; k++ ) {
1436 taylorcoeff /= ( REAL8 )k;
1437 fcoarse += taylorcoeff * freqs->data[k] * tdttmp;
1438 tdttmp *= tdt;
1439 }
1440 fcoarse *= freqfactor;
1441
1442 if ( freqsu != NULL ) {
1443 taylorcoeff = 1.;
1444 ffine = freqsu->data[0];
1445 tdttmp = tdt;
1446 for ( UINT4 k = 1; k < freqsu->length; k++ ) {
1447 taylorcoeff /= ( REAL8 )k;
1448 ffine += taylorcoeff * freqsu->data[k] * tdttmp;
1449 tdttmp *= tdt;
1450 }
1451 ffine *= freqfactor;
1452 }
1453
1454 /******************************************************************************/
1455 /* produce second phase for fine heterodyne */
1456 if ( hetParams.heterodyneflag == 1 || hetParams.heterodyneflag == 2 ||
1457 hetParams.heterodyneflag == 4 ) {
1458 REAL8 tWave1 = 0., tWave2 = 0.;
1459 phaseWave = 0.;
1460
1461 /* set up XLALBarycenter */
1462 dtpos = hetParams.timestamp - posepochu;
1463
1464 baryinput.delta = decu + dtpos * pmdecu;
1465 baryinput.alpha = rau + dtpos * pmrau / cos( baryinput.delta );
1466
1467 t = times->data[i]; /* get data time */
1468 t2 = times->data[i] + 1.; /* just add a second to get the gradient */
1469
1470 baryinput2 = baryinput;
1471
1472 XLALGPSSetREAL8( &baryinput.tgps, t );
1473 XLALGPSSetREAL8( &baryinput2.tgps, t2 );
1474
1475 XLAL_CHECK_VOID( XLALBarycenterEarthNew( &earth, &baryinput.tgps, edat,
1476 tdat, hetParams.ttype ) == XLAL_SUCCESS, XLAL_EFUNC );
1477 XLAL_CHECK_VOID( XLALBarycenter( &emit, &baryinput, &earth ) ==
1479
1480 XLAL_CHECK_VOID( XLALBarycenterEarthNew( &earth2, &baryinput2.tgps, edat,
1481 tdat, hetParams.ttype ) == XLAL_SUCCESS, XLAL_EFUNC );
1482 XLAL_CHECK_VOID( XLALBarycenter( &emit2, &baryinput2, &earth2 ) ==
1484
1485 /* if binary pulsar add extra time delay */
1486 if ( PulsarCheckParam( hetParams.hetUpdate, "BINARY" ) ) {
1487 /* input SSB time into binary timing function */
1488 binInput.tb = t + emit.deltaT;
1489 binInput2.tb = t2 + emit2.deltaT;
1490 binInput.earth = binInput2.earth = earth;
1491
1492 /* calculate binary time delay */
1493 XLALBinaryPulsarDeltaTNew( &binOutput, &binInput, hetParams.hetUpdate );
1494 XLALBinaryPulsarDeltaTNew( &binOutput2, &binInput2, hetParams.hetUpdate );
1495
1496 /* add binary time delay */
1497 tdt = ( t - T0Update ) + emit.deltaT + binOutput.deltaT;
1498 } else {
1499 tdt = ( t - T0Update ) + emit.deltaT;
1500 binOutput.deltaT = 0.;
1501 binOutput2.deltaT = 0.;
1502 }
1503
1504 /* check if any timing noise whitening is used */
1505 if ( PulsarCheckParam( hetParams.hetUpdate, "WAVESIN" ) && PulsarCheckParam( hetParams.hetUpdate, "WAVECOS" ) ) {
1506 REAL8 dtWave = ( XLALGPSGetREAL8( &emit.te ) - waveepochu ) / 86400.; /* in days */
1507
1508 const REAL8Vector *wavesin = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "WAVESIN" );
1509 const REAL8Vector *wavecos = PulsarGetREAL8VectorParam( hetParams.hetUpdate, "WAVECOS" );
1510
1511 for ( UINT4 k = 0; k < wavesin->length; k++ ) {
1512 tWave1 += wavesin->data[k] * sin( omu * ( REAL8 )( k + 1. ) * dtWave ) + wavecos->data[k] * cos( omu * ( REAL8 )( k + 1. ) * dtWave );
1513 tWave2 += wavesin->data[k] * sin( omu * ( REAL8 )( k + 1. ) * ( dtWave + ( 1. / 86400. ) ) ) + wavecos->data[k] * cos( omu * ( REAL8 )( k + 1. ) * ( dtWave + ( 1. / 86400. ) ) );
1514 }
1515 phaseWave = freqsu->data[0] * freqfactor * tWave1;
1516 }
1517
1518 if ( filtresp != NULL ) {
1519 /* calculate df = f*(dt(t2) - dt(t))/(t2 - t) here (t2 - t) is 1 sec */
1520 df = fcoarse * ( emit2.deltaT - emit.deltaT + binOutput2.deltaT - binOutput.deltaT + tWave2 - tWave1 );
1521 if ( cgwu > 0. && cgwu < 1. ) {
1522 df /= cgwu;
1523 }
1524 df += ( ffine - fcoarse );
1525
1526 /*sample rate*/
1527 srate = ( REAL8 )filtresp->freqResp->length * filtresp->deltaf;
1528 middle = ( UINT4 )srate * FILTERFFTTIME / 2;
1529
1530 /* find filter frequency response closest to df */
1531 position = middle + ( INT4 )floor( df / filtresp->deltaf );
1532 }
1533
1534 /* add the effect of a variable gravitational wave speed */
1535 if ( cgwu > 0. && cgwu < 1. ) {
1536 tdt /= cgwu;
1537 }
1538
1539 /* multiply by freqfactor to get gw phase */
1540 taylorcoeff = 1.;
1541 tdttmp = tdt;
1542 phaseUpdate = 0.;
1543 for ( UINT4 k = 0; k < freqsu->length; k++ ) {
1544 taylorcoeff /= ( REAL8 )( k + 1 );
1545 phaseUpdate += taylorcoeff * freqsu->data[k] * tdttmp;
1546 tdttmp *= tdt;
1547 }
1548 phaseUpdate *= freqfactor;
1549
1550 /* add glitch phase */
1551 phaseGlitch = 0.;
1552 if ( glnum > 0 ) {
1553 for ( UINT4 k = 0; k < glnum; k++ ) {
1554 if ( tdt >= glep[k] - T0Update ) {
1555 REAL8 dtg = 0, expd = 1.;
1556 dtg = tdt - ( glep[k] - T0Update ); /* time since glitch */
1557 if ( gltd[k] != 0. ) {
1558 expd = exp( -dtg / gltd[k] ); /* decaying part of glitch */
1559 }
1560
1561 phaseGlitch += glph[k] + glf0[k] * dtg + 0.5 * glf1[k] * dtg * dtg + ( 1. / 6. ) * glf2[k] * dtg * dtg * dtg + glf0d[k] * gltd[k] * ( 1. - expd );
1562 }
1563 }
1564 phaseGlitch *= freqfactor;
1565 }
1566
1567 phaseUpdate += phaseWave + phaseGlitch;
1568 }
1569
1570 /******************************************************************************/
1571 dataTemp = data->data->data[i];
1572
1573 /* perform heterodyne */
1574 if ( hetParams.heterodyneflag == 0 || hetParams.heterodyneflag == 3 ) {
1575 deltaphase = 2.*LAL_PI * fmod( phaseCoarse, 1. );
1576 dataTemp = creal( dataTemp ); /* make sure imaginary part is zero */
1577 }
1578 if ( hetParams.heterodyneflag == 1 || hetParams.heterodyneflag == 2 ||
1579 hetParams.heterodyneflag == 4 ) {
1580 deltaphase = 2.*LAL_PI * fmod( phaseUpdate - phaseCoarse, 1. );
1581
1582 /* multiply the data by the filters complex response function to remove its effect */
1583 /* do a linear interpolation between filter response function points */
1584 if ( filtresp != NULL ) {
1585 filtphase = filtresp->phaseResp->data[position] +
1586 ( ( filtresp->phaseResp->data[position + 1] -
1587 filtresp->phaseResp->data[position] ) / ( filtresp->deltaf ) ) *
1588 ( ( REAL8 )srate / 2. + df - ( REAL8 )position * filtresp->deltaf );
1589 filtphase = fmod( filtphase - filtresp->phaseResp->data[middle],
1590 2.*LAL_PI );
1591
1592 resp = filtresp->freqResp->data[position] +
1593 ( ( filtresp->freqResp->data[position + 1] -
1594 filtresp->freqResp->data[position] ) / ( filtresp->deltaf ) ) *
1595 ( ( REAL8 )srate / 2. + df - ( REAL8 )position * filtresp->deltaf );
1596
1597 dataTemp2 = dataTemp;
1598
1599 dataTemp = ( 1. / resp ) * ( creal( dataTemp2 ) * cos( filtphase ) - cimag( dataTemp2 ) * sin( filtphase ) ) +
1600 I * ( 1. / resp ) * ( creal( dataTemp2 ) * sin( filtphase ) + cimag( dataTemp2 ) * cos( filtphase ) );
1601 }
1602 }
1603
1604 if ( fpphase != NULL ) {
1605 fprintf( fpphase, "%.9lf\n", deltaphase );
1606 }
1607
1608 data->data->data[i] = ( creal( dataTemp ) * cos( -deltaphase ) - cimag( dataTemp ) * sin( -deltaphase ) ) +
1609 I * ( creal( dataTemp ) * sin( -deltaphase ) + cimag( dataTemp ) * cos( -deltaphase ) );
1610 }
1611
1612 if ( hetParams.heterodyneflag > 0 ) {
1614
1615 if ( hetParams.ttype != TIMECORRECTION_ORIGINAL ) {
1617 }
1618 }
1619
1620 if ( fpphase != NULL ) {
1621 fclose( fpphase );
1622 }
1623}
1624
1625/* function to extract the frame time and duration from the file name */
1627{
1628 INT4 j = 0;
1629
1630 /* check framefile is not NULL */
1631 if ( framefile == NULL ) {
1632 fprintf( stderr, "Error... Frame filename is not specified!\n" );
1633 exit( 1 );
1634 }
1635
1636 /* file names should end with GPS-length.gwf - *********-***.gwf, so we can
1637 locate the first '-' before the end of the file name */
1638 /* locate the start time and length of the data */
1639 for ( j = strlen( framefile ) - 1; j >= 0; j-- )
1640 if ( strstr( ( framefile + j ), "-" ) != NULL ) {
1641 break;
1642 }
1643
1644 /* get start times and durations (assumes the GPS time is 9 digits long) */
1645 *gpstime = atof( framefile + j - 9 );
1646 *duration = atoi( framefile + j + 1 );
1647}
1648
1649/* function to read in frame data given a framefile and data channel */
1651 REAL8 length, INT4 duration, REAL8 samplerate, REAL8 scalefac,
1652 REAL8 highpass )
1653{
1654 REAL8TimeSeries *dblseries = NULL;
1655
1656 LALFrStream *frfile = NULL;
1657
1659 INT4 i;
1660
1661 /* set the data epoch */
1662 XLALGPSSetREAL8( &epoch, ttime );
1663
1664 /* open frame file for reading */
1665 if ( ( frfile = XLALFrStreamCacheOpen( framecache ) ) == NULL ) {
1666 return NULL; /* couldn't open frame file */
1667 }
1668
1669 /* fill in vector - checking for frame data type */
1670 INT4 frtype = XLALFrStreamGetTimeSeriesType( channel, frfile );
1671 if ( frtype == LAL_S_TYPE_CODE ) { /* data is float */
1672 REAL4TimeSeries *tseries = NULL;
1673
1674 if ( ( tseries = XLALFrStreamReadREAL4TimeSeries( frfile, channel, &epoch, duration, 0 ) ) == NULL ) {
1675 XLALDestroyREAL4TimeSeries( tseries );
1676 XLALFrStreamClose( frfile );
1677 return NULL; /* couldn't read frame data */
1678 }
1679
1680 /* create REAL8 time series */
1681 if ( ( dblseries = XLALCreateREAL8TimeSeries( channel, &epoch, 0.,
1682 1. / samplerate, &lalSecondUnit, ( INT4 )length ) ) == NULL ) {
1683 XLALPrintError( "Error allocating data times series.\n" );
1684 }
1685
1686 for ( i = 0; i < ( INT4 )length; i++ ) {
1687 /* check for NaNs and scale data */
1688 if ( isnan( tseries->data->data[i] ) != 0 ) {
1689 XLALDestroyREAL8TimeSeries( dblseries );
1690 XLALDestroyREAL4TimeSeries( tseries );
1691 XLALFrStreamClose( frfile );
1692 return NULL; /* couldn't read frame data */
1693 }
1694
1695 dblseries->data->data[i] = scalefac * ( REAL8 )tseries->data->data[i];
1696 }
1697
1698 XLALDestroyREAL4TimeSeries( tseries );
1699 } else if ( frtype == LAL_D_TYPE_CODE ) { /* data is double */
1700 if ( ( dblseries = XLALFrStreamReadREAL8TimeSeries( frfile, channel, &epoch, duration, 0 ) ) == NULL ) {
1701 XLALFrStreamClose( frfile );
1702 return NULL; /* couldn't read frame data */
1703 }
1704
1705 /* check that data doesn't contain NaNs */
1706 for ( i = 0; i < ( INT4 )length; i++ ) {
1707 /* check for NaNs and scale data */
1708 if ( isnan( dblseries->data->data[i] ) != 0 ) {
1709 XLALDestroyREAL8TimeSeries( dblseries );
1710 XLALFrStreamClose( frfile );
1711 return NULL; /* couldn't read frame data */
1712 }
1713
1714 dblseries->data->data[i] = scalefac * dblseries->data->data[i];
1715 }
1716 } else { /* channel name is not recognised */
1717 fprintf( stderr, "Error... Channel name %s is not recognised as a proper channel.\n", channel );
1718 exit( 1 ); /* abort code */
1719 }
1720
1721 /* if a high-pass filter is specified (>0) then filter data */
1722 if ( highpass > 0. ) {
1723 PassBandParamStruc highpasspar;
1724
1725 /* uses 8th order Butterworth, with 10% attenuation */
1726 highpasspar.nMax = 8;
1727 highpasspar.f1 = -1;
1728 highpasspar.a1 = -1;
1729 highpasspar.f2 = highpass;
1730 highpasspar.a2 = 0.9; /* this means 10% attenuation at f2 */
1731
1732 XLALButterworthREAL8TimeSeries( dblseries, &highpasspar );
1733 }
1734
1735 XLALFrStreamClose( frfile );
1736
1737 return dblseries;
1738}
1739
1740/* function to set up three low-pass third order Butterworth IIR filters */
1741void set_filters( Filters *iirFilters, REAL8 filterKnee, REAL8 samplerate )
1742{
1743 COMPLEX16ZPGFilter *zpg = NULL;
1744 REAL4 wc;
1745
1746 /* set zero pole gain values */
1747 wc = tan( LAL_PI * filterKnee / samplerate );
1748 zpg = XLALCreateCOMPLEX16ZPGFilter( 0, 3 );
1749 zpg->poles->data[0] = ( wc * sqrt( 3. ) / 2. ) + I * ( wc * 0.5 );
1750 zpg->poles->data[1] = I * wc;
1751 zpg->poles->data[2] = -( wc * sqrt( 3. ) / 2. ) + I * ( wc * 0.5 );
1752 zpg->gain = I * wc * wc * wc;
1754
1755 /* create IIR filters */
1756 iirFilters->filter1Re = NULL;
1757 iirFilters->filter1Im = NULL;
1758 iirFilters->filter1Re = XLALCreateREAL8IIRFilter( zpg );
1759 iirFilters->filter1Im = XLALCreateREAL8IIRFilter( zpg );
1760
1761 iirFilters->filter2Re = NULL;
1762 iirFilters->filter2Im = NULL;
1763 iirFilters->filter2Re = XLALCreateREAL8IIRFilter( zpg );
1764 iirFilters->filter2Im = XLALCreateREAL8IIRFilter( zpg );
1765
1766 iirFilters->filter3Re = NULL;
1767 iirFilters->filter3Im = NULL;
1768 iirFilters->filter3Re = XLALCreateREAL8IIRFilter( zpg );
1769 iirFilters->filter3Im = XLALCreateREAL8IIRFilter( zpg );
1770
1771 /* destroy zpg filter */
1773}
1774
1775/* function to low-pass filter the data using three third order Butterworth IIR filters */
1777{
1778 COMPLEX16 tempData;
1779 INT4 i = 0;
1780
1781 for ( i = 0; i < ( INT4 )data->data->length; i++ ) {
1782 tempData = LALDIIRFilter( creal( data->data->data[i] ), iirFilters->filter1Re ) +
1783 I * LALDIIRFilter( cimag( data->data->data[i] ), iirFilters->filter1Im );
1784
1785 data->data->data[i] = LALDIIRFilter( creal( tempData ), iirFilters->filter2Re ) +
1786 I * LALDIIRFilter( cimag( tempData ), iirFilters->filter2Im );
1787
1788 tempData = LALDIIRFilter( creal( data->data->data[i] ), iirFilters->filter3Re ) +
1789 I * LALDIIRFilter( cimag( data->data->data[i] ), iirFilters->filter3Im );
1790
1791 data->data->data[i] = creal( tempData ) + I * cimag( tempData );
1792 }
1793
1794}
1795
1796/* function to average the data at one sample rate down to a new sample rate */
1798 REAL8Vector *times, INT4Vector *starts, INT4Vector *stops, REAL8 sampleRate,
1799 REAL8 resampleRate, INT4 hetflag )
1800{
1801 COMPLEX16TimeSeries *series = NULL;
1802 INT4 i = 0, j = 0, k = 0, length;
1803 COMPLEX16 tempData;
1804 INT4 size;
1805
1806 INT4 count = 0;
1808
1809 epoch.gpsSeconds = 0;
1810 epoch.gpsNanoSeconds = 0;
1811
1812 if ( sampleRate != resampleRate ) {
1813 length = ( INT4 )floor( ROUND( resampleRate * data->data->length ) / sampleRate );
1814 } else {
1815 length = data->data->length;
1816 }
1817
1818 size = ( INT4 )ROUND( sampleRate / resampleRate );
1819
1820 if ( ( series = XLALCreateCOMPLEX16TimeSeries( "", &epoch, 0., 1. / resampleRate,
1821 &lalSecondUnit, length ) ) == NULL ) {
1822 XLALPrintError( "Error creating time series for resampled data.\n" );
1823 }
1824
1825 if ( hetflag == 0 || hetflag == 3 ) { /* coarse heterodyne */
1826 for ( i = 0; i < ( INT4 )data->data->length - size + 1; i += size ) {
1827 tempData = 0.;
1828
1829 /* sum data */
1830 for ( j = 0; j < size; j++ ) {
1831 tempData += data->data->data[i + j];
1832 }
1833
1834 /* get average */
1835 series->data->data[count] = tempData / ( REAL8 )size;
1836
1837 /* take the middle point - if just resampling rather than averaging */
1838 /*series->data->data[count].re = data->data->data[i + size/2].re;
1839 series->data->data[count].im = data->data->data[i + size/2].im;*/
1840 if ( sampleRate != resampleRate ) {
1841 times->data[count] = ( REAL8 )data->epoch.gpsSeconds +
1842 ( REAL8 )data->epoch.gpsNanoSeconds / 1.e9 + ( 1. / resampleRate ) / 2. +
1843 ( ( REAL8 )count / resampleRate );
1844 } else {
1845 times->data[count] = ( REAL8 )data->epoch.gpsSeconds +
1846 ( REAL8 )data->epoch.gpsNanoSeconds / 1.e9 + ( ( REAL8 )count / resampleRate );
1847 }
1848
1849 count++;
1850 }
1851 } else if ( hetflag == 1 || hetflag == 2 || hetflag == 4 ) {
1852 /* need to calculate
1853 how many chunks of data at the new sample rate will fit into each science
1854 segment (starts and stops) */
1855 INT4 duration = 0; /* duration of a science segment */
1856 INT4 rremainder = 0; /* number of data points lost */
1857 INT4 prevdur = 0; /* duration of previous segment */
1858 INT4 frombeg = 0, fromend = 0;
1859
1860 count = 0;
1861 j = 0;
1862
1863 for ( i = 0; i < ( INT4 )starts->length; i++ ) {
1864 /* find first bit of data within a segment */
1865 if ( starts->data[i] < times->data[j] && stops->data[i] <= times->data[j] ) {
1866 /* if the segmemt is before the jth data point then continue */
1867 continue;
1868 }
1869 if ( starts->data[i] < times->data[j] && stops->data[i] > times->data[j] ) {
1870 /* if the segment overlaps the jth data point then use as much as
1871 possible */
1872 starts->data[i] = times->data[j] - ( ( 1. / sampleRate ) / 2. );
1873 }
1874 if ( starts->data[i] < times->data[times->length - 1] && stops->data[i] >
1875 times->data[times->length - 1] ) {
1876 /* if starts is before the end of the data but stops is after the end of
1877 the data then shorten the segment */
1878 stops->data[i] = times->data[times->length - 1] + ( ( 1. / sampleRate ) / 2. );
1879 }
1880 if ( starts->data[i] >= times->data[times->length - 1] ) {
1881 /* segment is outside of data time, so exit */
1882 fprintf( stderr, "Segment %d to %d is outside the times of the data!\n", starts->data[i], stops->data[i] );
1883 fprintf( stderr, "End resampling\n" );
1884 break;
1885 }
1886
1887 while ( times->data[j] < starts->data[i] ) {
1888 j++;
1889 }
1890
1891 starts->data[i] = times->data[j] - ( ( 1. / sampleRate ) / 2. );
1892
1893 duration = stops->data[i] - starts->data[i];
1894
1895 /* check duration is not negative */
1896 if ( duration <= 0 ) {
1897 continue;
1898 }
1899
1900 /* check that data is contiguous within a segment - if not split in two */
1901 for ( k = 0; k < ( INT4 )( duration * sampleRate ) - 1; k++ ) {
1902 /* check for break in the data */
1903 if ( ( times->data[j + k + 1] - times->data[j + k] ) > 1. / sampleRate ) {
1904 /* get duration of segment up until time of split */
1905 duration = times->data[j + k] - starts->data[i] + ( ( 1. / sampleRate ) / 2. );
1906
1907 /* restart from this point as if it's a new segment */
1908 starts->data[i] = times->data[j + k + 1] - ( ( 1. / sampleRate ) / 2. );
1909
1910 /* check that the new point is still in the same segment or not - if
1911 we are then redo new segment, if not then move on to next segment*/
1912 if ( starts->data[i] < stops->data[i] && duration > 0 ) {
1913 i--; /* reset i so it redoes the new segment */
1914 }
1915
1916 break;
1917 }
1918 }
1919
1920 if ( duration < size ) {
1921 j += ( INT4 )( duration * sampleRate );
1922 continue; /* if segment is smaller than the number of samples needed then skip to next */
1923 }
1924
1925 rremainder = ( INT4 )( duration * sampleRate ) % size;
1926 if ( sampleRate != resampleRate ) {
1927 frombeg = floor( rremainder / 2 );
1928 fromend = ceil( rremainder / 2 );
1929 } else {
1930 frombeg = 0;
1931 fromend = -1;
1932 }
1933
1934 prevdur = j;
1935
1936 for ( j = prevdur + frombeg; j < prevdur + ( INT4 )ROUND( duration * sampleRate ) - fromend - 1 ; j += size ) {
1937 tempData = 0.;
1938
1939 for ( k = 0; k < size; k++ ) {
1940 tempData += data->data->data[j + k];
1941 }
1942 series->data->data[count] = tempData / ( REAL8 )size;
1943
1944 if ( sampleRate != resampleRate ) {
1945 times->data[count] = times->data[j + size / 2] - ( 1. / sampleRate ) / 2.;
1946 } else {
1947 times->data[count] = times->data[j];
1948 }
1949
1950 count++;
1951 }
1952 }
1953 }
1954
1955 if ( ( INT4 )times->length > count )
1956 if ( ( times = XLALResizeREAL8Vector( times, count ) ) == NULL ) {
1957 XLALPrintError( "Error resizing resampled times.\n" );
1958 }
1959
1960 if ( ( INT4 )series->data->length > count )
1961 if ( ( series = XLALResizeCOMPLEX16TimeSeries( series, 0, count ) ) == NULL ) {
1962 XLALPrintError( "Error resizing resampled data.\n" );
1963 }
1964
1965 /* create time stamps */
1966 series->deltaT = 1. / resampleRate;
1967 series->epoch = data->epoch;
1968
1969 return series;
1970}
1971
1972/* read in science segment list file - returns the number of segments */
1973INT4 get_segment_list( INT4Vector *starts, INT4Vector *stops, CHAR *seglistfile,
1974 INT4 heterodyneflag )
1975{
1976 FILE *fp = NULL;
1977 INT4 i = 0;
1978 long offset;
1979 CHAR jnkstr[256]; /* junk string to contain comment lines */
1980 INT4 dur; /* variable to contain the segment number and duration */
1981 INT4 linecount = 0; /* number of lines in the segment file */
1982 INT4 ch = 0;
1983
1984 if ( ( fp = fopen( seglistfile, "r" ) ) == NULL ) {
1985 fprintf( stderr, "Error... can't open science segment list file.\n" );
1986 exit( 1 );
1987 }
1988
1989 /* count number of lines in the file */
1990 while ( ( ch = fgetc( fp ) ) != EOF ) {
1991 if ( ch == '\n' ) { /* check for return at end of line */
1992 linecount++;
1993 }
1994 }
1995
1996 /* if segment list is empty exit with a warning */
1997 if ( linecount == 0 ) {
1998 fprintf( stderr, "Warning... segment list file was empty, so no heterodyne will be performed\n" );
1999 exit( 0 );
2000 }
2001
2002 /* allocate memory for vectors */
2003 if ( ( starts = XLALResizeINT4Vector( starts, linecount ) ) == NULL ||
2004 ( stops = XLALResizeINT4Vector( stops, linecount ) ) == NULL ) {
2005 XLALPrintError( "Error resizing segment lists.\n" );
2006 }
2007
2008 /* rewind file pointer */
2009 rewind( fp );
2010
2011 /* segment list files have comment lines starting with a # so want to ignore
2012 those lines */
2013 while ( !feof( fp ) ) {
2014 offset = ftell( fp ); /* get current position of file stream */
2015
2016 if ( fscanf( fp, "%s", jnkstr ) == EOF ) { /* scan in value and check if == to # */
2017 break;
2018 } /* break if there is an extra line at the end of file containing
2019 nothing */
2020
2021 if ( strstr( jnkstr, "#" ) ) {
2022 /* if == # then skip to the end of the line */
2023 if ( fscanf( fp, "%*[^\n]" ) == EOF ) {
2024 break;
2025 }
2026 continue;
2027 } else {
2028 fseek( fp, offset, SEEK_SET ); /* if line doesn't start with a # then it is
2029 data */
2030 if ( fscanf( fp, "%d%d", &starts->data[i], &stops->data[i] ) == EOF ) {
2031 break;
2032 }
2033 /* format is: starts stops */
2034 dur = stops->data[i] - starts->data[i];
2035
2036 /* if performing a fine heterodyne remove the first 60 secs at the start
2037 of a segment to remove the filter response - if the segment is less
2038 than 60 secs then ignore it */
2039 if ( heterodyneflag == 1 || heterodyneflag == 2 ) {
2040 if ( dur > 60 ) {
2041 starts->data[i] += 60;
2042 dur -= 60;
2043 } else {
2044 continue;
2045 }
2046 }
2047
2048 i++;
2049 }
2050 }
2051
2052 fclose( fp );
2053
2054 return i;
2055}
2056
2057/* get frame data for partcular science segment */
2059 INT4 *position, INT4 maxchunklength )
2060{
2061 INT4 durlock; /* duration of locked segment */
2062 INT4 tempstart, tempstop;
2063 LALCache *smalllist = NULL;
2064
2065 durlock = *stops - *starts;
2066 tempstart = *starts;
2067 tempstop = *stops;
2068
2069 /* duplicate frame cache */
2070 if ( ( smalllist = XLALCacheDuplicate( cache ) ) == NULL ) {
2071 fprintf( stderr, "Error... could not duplicate frame cache file\n" );
2072 exit( 1 );
2073 }
2074
2075 /*if lock stretch is long can't read whole thing in at once so only do a bit*/
2076 if ( durlock > maxchunklength ) {
2077 tempstop = tempstart + maxchunklength;
2078 }
2079
2080 if ( XLALCacheSieve( smalllist, tempstart, tempstop, NULL, NULL, NULL ) != 0 ) {
2081 fprintf( stderr, "Error... could not import frame cache file\n" );
2082 exit( 1 );
2083 }
2084
2085 if ( durlock > maxchunklength ) { /* set starts to its value plus maxchunklength */
2086 ( *position )--; /* move position counter back one */
2087 *starts = tempstop;
2088 }
2089
2090 /* if no data was found at all set small list to NULL */
2091 if ( smalllist->length == 0 ) {
2092 XLALDestroyCache( smalllist );
2093 return NULL;
2094 }
2095
2096 return smalllist;
2097}
2098
2099/* function to read in the calibration files and calibrate the data at that (gw)
2100frequency */
2103{
2104 FILE *fpcoeff = NULL;
2105 REAL8 Rfunc, Rphase;
2106 REAL8 C, Cphase; /* sensing function */
2107 REAL8 G, Gphase; /* open loop gain */
2108 INT4 i = 0, j = 0, k = 0, ktemp = 0, counter = 0;
2109
2110 COMPLEX16 tempData;
2111
2112 long offset;
2113 CHAR jnkstr[256]; /* junk string to contain comment lines */
2114 int rc;
2115
2116 if ( calfiles.calibcoefficientfile == NULL ) {
2117 fprintf( stderr, "No calibration coefficient file.\n\
2118Assume calibration coefficients are 1 and use the response function.\n" );
2119 /* get response function values */
2120 get_calibration_values( &Rfunc, &Rphase, calfiles.responsefunctionfile,
2121 frequency );
2122
2123 /* calibrate using response function */
2124 for ( i = 0; i < ( INT4 )series->data->length; i++ ) {
2125 tempData = series->data->data[i];
2126 series->data->data[i] = Rfunc * ( creal( tempData ) * cos( Rphase ) - cimag( tempData ) * sin( Rphase ) ) +
2127 I * Rfunc * ( creal( tempData ) * sin( Rphase ) + cimag( tempData ) * cos( Rphase ) );
2128 }
2129 } else {
2130 /* open the open loop gain and sensing function files to use for
2131 calibration */
2132 REAL8 *times = NULL;
2133 REAL8 *alpha = NULL, *ggamma = NULL; /* gamma = alpha*beta */
2134 COMPLEX16 Resp;
2135
2136 if ( ( fpcoeff = fopen( calfiles.calibcoefficientfile, "r" ) ) == NULL ) {
2137 fprintf( stderr, "Error... can't open calibration coefficient file %s.\n\
2138Assume calibration coefficients are 1 and use the response function.\n",
2139 calfiles.calibcoefficientfile );
2140 exit( 1 );
2141 }
2142
2143 /* open sensing function file for reading */
2144 get_calibration_values( &C, &Cphase, calfiles.sensingfunctionfile,
2145 frequency );
2146
2147 /* get open loop gain values */
2148 get_calibration_values( &G, &Gphase, calfiles.openloopgainfile, frequency );
2149
2150 if ( ( alpha = XLALCalloc( 100, sizeof( REAL8 ) ) ) == NULL ||
2151 ( ggamma = XLALCalloc( 100, sizeof( REAL8 ) ) ) == NULL ||
2152 ( times = XLALCalloc( 100, sizeof( REAL8 ) ) ) == NULL ) {
2153 XLALPrintError( "Error allocating calibration data memory.\n" );
2154 }
2155
2156 /* read in calibration coefficients */
2157 while ( !feof( fpcoeff ) ) {
2158 offset = ftell( fpcoeff ); /* get current position of file stream */
2159
2160 if ( fscanf( fpcoeff, "%s", jnkstr ) == EOF ) {
2161 /* scan in value and check if ==
2162 to % */
2163 break;
2164 }
2165 if ( strstr( jnkstr, "%" ) ) {
2166 rc = fscanf( fpcoeff, "%*[^\n]" ); /* if == % then skip to the end of the
2167 line */
2168 if ( rc == EOF ) {
2169 continue;
2170 }
2171
2172 continue;
2173 } else {
2174 fseek( fpcoeff, offset, SEEK_SET ); /* if line doesn't start with a % then
2175 it is data */
2176
2177 /* dynamically allocate memory (in increments of 100) */
2178 if ( i != 0 && i % 100 == 0 ) {
2179 if ( ( times = XLALRealloc( times, sizeof( REAL8 ) * ( i + 100 ) ) ) == NULL ) {
2180 fprintf( stderr, "Error... times memory allocation failed\n" );
2181 exit( 1 );
2182 }
2183 if ( ( alpha = XLALRealloc( alpha, sizeof( REAL8 ) * ( i + 100 ) ) ) == NULL ) {
2184 fprintf( stderr, "Error... alpha memory allocation failed\n" );
2185 exit( 1 );
2186 }
2187 if ( ( ggamma = XLALRealloc( ggamma, sizeof( REAL8 ) * ( i + 100 ) ) ) == NULL ) {
2188 fprintf( stderr, "Error... gamma memory allocation failed\n" );
2189 exit( 1 );
2190 }
2191 }
2192
2193 if ( fscanf( fpcoeff, "%lf%lf%lf", &times[i], &alpha[i], &ggamma[i] ) != 3 ) {
2194 fprintf( stderr, "Error... problem reading in values from calibration coefficient file!\n" );
2195 exit( 1 );
2196 }
2197 i++;
2198 }
2199 }
2200
2201 fclose( fpcoeff );
2202
2203 /* check times aren't outside range of calib coefficients */
2204 if ( times[0] > datatimes->data[series->data->length - 1] || times[i - 1] <
2205 datatimes->data[0] ) {
2206 fprintf( stderr, "Error... calibration coefficients outside range of data.\n" );
2207 exit( 1 );
2208 }
2209
2210 /* calibrate */
2211 for ( j = 0; j < ( INT4 )series->data->length; j++ ) {
2212 for ( k = ktemp; k < i; k++ ) {
2213 /* get alpha and gamma values closest to the data, assuming a value a
2214 minute */
2215 if ( fabs( times[k] - datatimes->data[j] ) <= 30. ) {
2216 /* if the coefficients were outside a range then they are bad so don't
2217 use */
2218 if ( ( alpha[k] < ALPHAMIN || alpha[k] > ALPHAMAX ) && j <
2219 ( INT4 )series->data->length - 1 ) {
2220 ktemp = k;
2221 break;
2222 } else if ( ( alpha[k] < ALPHAMIN || alpha[k] > ALPHAMAX ) &&
2223 j == ( INT4 )series->data->length - 1 ) {
2224 break;
2225 }
2226
2227 /* response function for DARM_ERR is
2228 R(f) = (1 + \gamma*G)/\gamma*C */
2229 if ( strcmp( channel, "LSC-DARM_ERR" ) == 0 ) {
2230 Resp = ( ( cos( Cphase ) + ggamma[k] * G * cos( Gphase - Cphase ) ) / ( ggamma[k] * C ) ) +
2231 I * ( ( -sin( Cphase ) + ggamma[k] * G * sin( Gphase - Cphase ) ) / ( ggamma[k] * C ) );
2232 }
2233 /* response function for AS_Q is
2234 R(f) = (1 + \gamma*G)/\alpha*C */
2235 else if ( strcmp( channel, "LSC-AS_Q" ) == 0 ) {
2236 Resp = ( ( cos( Cphase ) + ggamma[k] * G * cos( Gphase - Cphase ) ) / ( alpha[k] * C ) ) +
2237 I * ( ( -sin( Cphase ) + ggamma[k] * G * sin( Gphase - Cphase ) ) / ( alpha[k] * C ) );
2238 } else {
2239 fprintf( stderr, "Error... data channel is not set. Give either AS_Q\
2240 or DARM_ERR!\n" );
2241 exit( 1 );
2242 }
2243
2244 tempData = series->data->data[j];
2245 series->data->data[counter] = tempData * Resp;
2246 datatimes->data[counter] = datatimes->data[j];
2247
2248 counter++;
2249 ktemp = k;
2250 break;
2251 }
2252 }
2253 }
2254
2255 /* free memory */
2256 XLALFree( times );
2257 XLALFree( alpha );
2258 XLALFree( ggamma );
2259
2260 /*resize vectors incase any points have been vetoed by the alpha valuecuts*/
2261 if ( ( series->data = XLALResizeCOMPLEX16Vector( series->data, counter ) )
2262 == NULL ||
2263 ( datatimes = XLALResizeREAL8Vector( datatimes, counter ) ) == NULL ) {
2264 XLALPrintError( "Error resizing calibrated data.\n" );
2265 }
2266 }
2267}
2268
2269void get_calibration_values( REAL8 *magnitude, REAL8 *phase, CHAR *calibfilename,
2271{
2272 FILE *fp = NULL;
2273 long offset;
2274 CHAR jnkstr[256]; /* junk string to contain comment lines */
2275 REAL8 freq = 0.;
2276 int rc;
2277
2278 /* open calibration file for reading */
2279 if ( calibfilename == NULL ) {
2280 fprintf( stderr, "Error... calibration filename has a null pointer\n" );
2281 exit( 1 );
2282 } else if ( ( fp = fopen( calibfilename, "r" ) ) == NULL ) {
2283 fprintf( stderr, "Error... can't open calibration file %s.\n",
2284 calibfilename );
2285 exit( 1 );
2286 }
2287
2288 /*calibration files can have lines starting with % at the top so ignore them*/
2289 do {
2290 offset = ftell( fp ); /* get current position of file stream */
2291
2292 rc = fscanf( fp, "%s", jnkstr ); /* scan in value and check if == to % */
2293 if ( strstr( jnkstr, "%" ) ) {
2294 rc = fscanf( fp, "%*[^\n]" ); /* if == % then skip to the end of the line */
2295
2296 if ( rc == EOF ) {
2297 continue;
2298 }
2299 continue;
2300 } else {
2301 fseek( fp, offset, SEEK_SET ); /* if line doesn't start with a % then it is
2302 data */
2303 if ( fscanf( fp, "%lf%lf%lf", &freq, magnitude, phase ) != 3 ) {
2304 fprintf( stderr, "Error... problem reading data from calibration \
2305file!\n" );
2306 exit( 1 );
2307 }
2308 }
2309 } while ( !feof( fp ) && freq < frequency ); /* stop when we've read in response for
2310 our frequency*/
2311 fclose( fp );
2312}
2313
2314/* function to remove outliers above a certain standard deviation threshold - it
2315 returns the number of outliers removed */
2317 REAL8 stddevthresh )
2318{
2319 COMPLEX16 mean;
2320 COMPLEX16 stddev;
2321 INT4 i = 0, j = 0, startlen = ( INT4 )data->data->length;
2322
2323 /* calculate mean - could in reality just assume to be zero */
2324 mean = 0.;
2325 /*for(i=0;i<data->data->length;i++){
2326 mean.re += data->data->data[i].re;
2327 mean.im += data->data->data[i].im;
2328 }
2329
2330 mean.re /= (REAL8)data->data->length;
2331 mean.im /= (REAL8)data->data->length; */
2332
2333 /* for now assume mean = zero as really large outliers could upset this */
2334
2335 /* calculate standard deviation */
2336 stddev = 0.;
2337
2338 for ( i = 0; i < ( INT4 )data->data->length; i++ ) {
2339 stddev += ( creal( data->data->data[i] ) - creal( mean ) ) * ( creal( data->data->data[i] ) - creal( mean ) ) +
2340 I * ( ( cimag( data->data->data[i] ) - cimag( mean ) ) * ( cimag( data->data->data[i] ) - cimag( mean ) ) );
2341 }
2342
2343 stddev = sqrt( creal( stddev ) / ( REAL8 )( data->data->length ) ) +
2344 I * sqrt( cimag( stddev ) / ( REAL8 )( data->data->length ) );
2345
2346 /* exclude those points who's absolute value is greater than our
2347 stddevthreshold */
2348 for ( i = 0; i < ( INT4 )data->data->length; i++ ) {
2349 if ( fabs( creal( data->data->data[i] ) ) < creal( stddev ) * stddevthresh &&
2350 fabs( cimag( data->data->data[i] ) ) < cimag( stddev ) * stddevthresh ) {
2351 data->data->data[j] = data->data->data[i];
2352 times->data[j] = times->data[i];
2353 j++;
2354 }
2355 }
2356
2357 XLAL_CHECK( j > 0, XLAL_EFUNC, "Error... thresholding has rejected all the data!" );
2358
2359 /* resize data and times */
2360 if ( ( data = XLALResizeCOMPLEX16TimeSeries( data, 0, j ) ) == NULL ||
2361 ( times = XLALResizeREAL8Vector( times, j ) ) == NULL ) {
2362 XLALPrintError( "Error resizing thresholded data.\n" );
2363 }
2364
2365 return startlen - j;
2366}
2367
2369{
2370 int i = 0;
2371 int srate, ttime;
2372
2373 FilterResponse *filtresp = NULL;
2374 Filters testFilters;
2375
2376 COMPLEX16Vector *data = NULL;
2377 COMPLEX16Vector *fftdata = NULL;
2378
2379 COMPLEX16FFTPlan *fftplan = NULL;
2380
2381 REAL8 phase = 0., tempphase = 0.;
2382 INT4 count = 0;
2383
2384 /* check filter knee is > 0 otherwise return NULL */
2385 if ( filterKnee <= 0. ) {
2386 return NULL;
2387 }
2388
2389 srate = 16;
2390 /* srate = 16384; */ /* sample at 16384 Hz */
2391 ttime = FILTERFFTTIME; /* have 200 second long data stretch - might need
2392 longer to increase resolution */
2393
2394 /**** CREATE SET OF IIR FILTERS ****/
2395 set_filters( &testFilters, filterKnee, srate );
2396
2397 /* allocate memory for filtresp */
2398 if ( ( filtresp = XLALMalloc( sizeof( FilterResponse ) ) ) == NULL ) {
2399 XLALPrintError( "Error allocating memory for filter response.\n" );
2400 }
2401
2402 /* create some data */
2403 if ( ( data = XLALCreateCOMPLEX16Vector( ttime * srate ) ) == NULL ) {
2404 XLALPrintError( "Error allocating data for filter response.\n" );
2405 }
2406
2407 /* create impulse and perform filtering */
2408 for ( i = 0; i < srate * ttime; i++ ) {
2409 REAL8 dataTmpRe = 0., dataTmpIm = 0.;
2410
2411 if ( i == 0 ) {
2412 dataTmpRe = 1.;
2413 dataTmpIm = 1.;
2414 }
2415
2416 dataTmpRe = LALDIIRFilter( dataTmpRe, testFilters.filter1Re );
2417 dataTmpRe = LALDIIRFilter( dataTmpRe, testFilters.filter2Re );
2418 dataTmpRe = LALDIIRFilter( dataTmpRe, testFilters.filter3Re );
2419
2420 dataTmpIm = LALDIIRFilter( dataTmpIm, testFilters.filter1Im );
2421 dataTmpIm = LALDIIRFilter( dataTmpIm, testFilters.filter2Im );
2422 dataTmpIm = LALDIIRFilter( dataTmpIm, testFilters.filter3Im );
2423
2424 data->data[i] = dataTmpRe + I * dataTmpIm;
2425 }
2426
2427 /* destroy filters */
2428 XLALDestroyREAL8IIRFilter( testFilters.filter1Re );
2429 XLALDestroyREAL8IIRFilter( testFilters.filter1Im );
2430 XLALDestroyREAL8IIRFilter( testFilters.filter2Re );
2431 XLALDestroyREAL8IIRFilter( testFilters.filter2Im );
2432 XLALDestroyREAL8IIRFilter( testFilters.filter3Re );
2433 XLALDestroyREAL8IIRFilter( testFilters.filter3Im );
2434
2435 /* FFT the data */
2436 if ( ( fftplan = XLALCreateForwardCOMPLEX16FFTPlan( srate * ttime, 1 ) ) == NULL ||
2437 ( fftdata = XLALCreateCOMPLEX16Vector( srate * ttime ) ) == NULL ) {
2438 XLALPrintError( "Error creating FFT plan and data.\n" );
2439 }
2440
2441 XLALCOMPLEX16VectorFFT( fftdata, data, fftplan );
2442
2443 /* flip vector so that it's in ascending frequency */
2444 for ( i = 0; i < srate * ttime / 2; i++ ) {
2445 COMPLEX16 tempdata;
2446
2447 tempdata = fftdata->data[i];
2448
2449 fftdata->data[i] = fftdata->data[i + srate * ttime / 2];
2450 fftdata->data[i + srate * ttime / 2] = tempdata;
2451 }
2452
2453 filtresp->srate = ( REAL8 )srate;
2454
2455 if ( ( filtresp->freqResp = XLALCreateREAL8Vector( srate * ttime ) ) == NULL ||
2456 ( filtresp->phaseResp = XLALCreateREAL8Vector( srate * ttime ) ) == NULL ) {
2457 XLALPrintError( "Error allocating filter response vectors.\n" );
2458 }
2459
2460 /* output the frequency and phase response */
2461 for ( i = 0; i < srate * ttime; i++ ) {
2462 filtresp->freqResp->data[i] = sqrt( creal( fftdata->data[i] ) * creal( fftdata->data[i] ) +
2463 cimag( fftdata->data[i] ) * cimag( fftdata->data[i] ) ) / sqrt( 2. );
2464
2465 phase = atan2( creal( fftdata->data[i] ), cimag( fftdata->data[i] ) );
2466
2467 if ( i == 0 ) {
2468 filtresp->phaseResp->data[i] = phase;
2469 continue;
2470 } else if ( phase - tempphase < 0. ) {
2471 count++;
2472 }
2473
2474 filtresp->phaseResp->data[i] = phase + 2.*LAL_PI * ( REAL8 )count;
2475
2476 tempphase = phase;
2477 }
2478
2479 /* set frequency step */
2480 filtresp->deltaf = ( REAL8 )srate / ( REAL8 )filtresp->freqResp->length;
2481
2483 XLALDestroyCOMPLEX16Vector( fftdata );
2484 XLALDestroyCOMPLEX16FFTPlan( fftplan );
2485
2486 return filtresp;
2487}
2488
2490{
2491 XLALDestroyREAL8Vector( filtresp->freqResp );
2492 XLALDestroyREAL8Vector( filtresp->phaseResp );
2493 XLALFree( filtresp );
2494}
2495
2496/* edited version of internal function from lal/lib/support/LogPrintf.c: return time-string for given unix-time */
2497const char *LogTimeToString( double t )
2498{
2499 static char buf[100];
2500 time_t x = ( time_t )t;
2501 struct tm tm;
2502 localtime_r( &x, &tm );
2503
2504 strftime( buf, sizeof( buf ), "%Y-%m-%d %H:%M:%S", &tm );
2505
2506 return buf;
2507} /* LogTimeToString() */
int XLALButterworthREAL8TimeSeries(REAL8TimeSeries *series, PassBandParamStruc *params)
void XLALBinaryPulsarDeltaTNew(BinaryPulsarOutput *output, BinaryPulsarInput *input, PulsarParameters *params)
function to calculate the binary system delay using new parameter structure
const char * program
#define LALDIIRFilter(x, f)
int j
int k
const LALVCSInfoList lalPulsarVCSInfoList
NULL-terminated list of VCS and build information for LALPulsar and its dependencies
#define c
int LALgetopt_long(int argc, char *const *argv, const char *options, const struct LALoption *long_options, int *opt_index)
char * LALoptarg
#define no_argument
#define required_argument
void PulsarSetParam(PulsarParameters *pars, const CHAR *name, const void *value)
Set the value of a parameter in the PulsarParameters structure.
const REAL8Vector * PulsarGetREAL8VectorParam(const PulsarParameters *pars, const CHAR *name)
Return a REAL8Vector parameter.
REAL8 PulsarGetREAL8ParamOrZero(const PulsarParameters *pars, const CHAR *name)
Return a REAL8 parameter if it exists, otherwise return zero.
int PulsarCheckParam(const PulsarParameters *pars, const CHAR *name)
Check for the existence of the parameter name in the PulsarParameters structure.
PulsarParameters * XLALReadTEMPOParFile(const CHAR *pulsarAndPath)
Read in the parameters from a TEMPO(2) parameter file into a PulsarParameters structure.
REAL8 PulsarGetREAL8Param(const PulsarParameters *pars, const CHAR *name)
Return a REAL8 parameter.
const CHAR * PulsarGetStringParam(const PulsarParameters *pars, const CHAR *name)
Return a string parameter.
void PulsarFreeParams(PulsarParameters *pars)
Function to free memory from pulsar parameters.
REAL8 PulsarGetREAL8VectorParamIndividual(const PulsarParameters *pars, const CHAR *name)
Return an individual REAL8 value from a REAL8Vector parameter.
const char * name
Definition: SearchTiming.c:93
#define fscanf
#define fprintf
int XLALWToZCOMPLEX16ZPGFilter(COMPLEX16ZPGFilter *filter)
COMPLEX16FFTPlan * XLALCreateForwardCOMPLEX16FFTPlan(UINT4 size, int measurelvl)
void XLALDestroyCOMPLEX16FFTPlan(COMPLEX16FFTPlan *plan)
int XLALCOMPLEX16VectorFFT(COMPLEX16Vector *_LAL_RESTRICT_ output, const COMPLEX16Vector *_LAL_RESTRICT_ input, const COMPLEX16FFTPlan *plan)
REAL8IIRFilter * XLALCreateREAL8IIRFilter(COMPLEX16ZPGFilter *input)
COMPLEX16ZPGFilter * XLALCreateCOMPLEX16ZPGFilter(INT4 numZeros, INT4 numPoles)
void XLALDestroyREAL8IIRFilter(REAL8IIRFilter *filter)
void XLALDestroyCOMPLEX16ZPGFilter(COMPLEX16ZPGFilter *filter)
int XLALFileClose(LALFILE *file)
int XLALFileEOF(LALFILE *file)
LALFILE * XLALFileOpen(const char *path, const char *mode)
size_t XLALFileRead(void *ptr, size_t size, size_t nobj, LALFILE *file)
int XLALGzipTextFile(const char *path)
char * XLALFileGets(char *s, int size, LALFILE *file)
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 XLALDestroyTimeCorrectionData(TimeCorrectionData *tcd)
Destructor for TimeCorrectionData struct, NULL robust.
int XLALBarycenter(EmissionTime *emit, const BarycenterInput *baryinput, const EarthState *earth)
Transforms from detector arrival time in GPS (as specified in the LIGOTimeGPS structure) to pulse em...
void XLALDestroyEphemerisData(EphemerisData *edat)
Destructor for EphemerisData struct, NULL robust.
int XLALBarycenterEarthNew(EarthState *earth, const LIGOTimeGPS *tGPS, const EphemerisData *edat, const TimeCorrectionData *tdat, TimeCorrectionType ttype)
Computes the position and orientation of the Earth, at some arrival time, but unlike XLALBarycenterEa...
@ TIMECORRECTION_ORIGINAL
Definition: LALBarycenter.h:78
@ TIMECORRECTION_TCB
Definition: LALBarycenter.h:75
@ TIMECORRECTION_TDB
Definition: LALBarycenter.h:74
void XLALDestroyCache(LALCache *cache)
LALCache * XLALCacheImport(const char *fname)
LALCache * XLALCacheDuplicate(const LALCache *cache)
int XLALCacheSieve(LALCache *cache, INT4 t0, INT4 t1, const char *srcregex, const char *dscregex, const char *urlregex)
#define LAL_PI
double complex COMPLEX16
double REAL8
char CHAR
uint32_t UINT4
int32_t INT4
float REAL4
LAL_S_TYPE_CODE
LAL_D_TYPE_CODE
int XLALFrStreamClose(LALFrStream *stream)
LALFrStream * XLALFrStreamCacheOpen(LALCache *cache)
LALTYPECODE XLALFrStreamGetTimeSeriesType(const char *chname, LALFrStream *stream)
REAL8TimeSeries * XLALFrStreamReadREAL8TimeSeries(LALFrStream *stream, const char *chname, const LIGOTimeGPS *start, REAL8 duration, size_t lengthlimit)
REAL4TimeSeries * XLALFrStreamReadREAL4TimeSeries(LALFrStream *stream, const char *chname, const LIGOTimeGPS *start, REAL8 duration, size_t lengthlimit)
void * XLALMalloc(size_t n)
void * XLALCalloc(size_t m, size_t n)
void * XLALRealloc(void *p, size_t n)
void XLALFree(void *p)
char char * XLALStringDuplicate(const char *s)
size_t XLALStringCopy(char *dst, const char *src, size_t size)
int char * XLALStringAppend(char *s, const char *append)
char * XLALStringCaseSubstring(const char *haystack, const char *needle)
char * XLALVCSInfoString(const LALVCSInfoList vcs_list, const int verbose, const char *prefix)
REAL8 XLALGetTimeOfDay(void)
const LALDetector * XLALGetSiteInfo(const CHAR *name)
Find the site geometry-information 'LALDetector' for given a detector name (or prefix).
Definition: SFTnaming.c:218
void XLALDestroyCOMPLEX16TimeSeries(COMPLEX16TimeSeries *series)
COMPLEX16TimeSeries * XLALCreateCOMPLEX16TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
void XLALDestroyREAL4TimeSeries(REAL4TimeSeries *series)
REAL8TimeSeries * XLALCreateREAL8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
COMPLEX16TimeSeries * XLALResizeCOMPLEX16TimeSeries(COMPLEX16TimeSeries *series, int first, size_t length)
const LALUnit lalSecondUnit
REAL8Vector * XLALResizeREAL8Vector(REAL8Vector *vector, UINT4 length)
INT4Vector * XLALResizeINT4Vector(INT4Vector *vector, UINT4 length)
INT4Vector * XLALCreateINT4Vector(UINT4 length)
void XLALDestroyINT4Vector(INT4Vector *vector)
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
COMPLEX16Vector * XLALCreateCOMPLEX16Vector(UINT4 length)
COMPLEX16Vector * XLALResizeCOMPLEX16Vector(COMPLEX16Vector *vector, UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
void XLALDestroyCOMPLEX16Vector(COMPLEX16Vector *vector)
void XLALAbortErrorHandler(const char *func, const char *file, int line, int errnum)
XLALErrorHandlerType * XLALSetErrorHandler(XLALErrorHandlerType *newHandler)
#define XLAL_CHECK(assertion,...)
#define XLAL_CHECK_VOID(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_SUCCESS
XLAL_EFUNC
LIGOTimeGPS * XLALGPSSetREAL8(LIGOTimeGPS *epoch, REAL8 t)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
int main(int argc, char *argv[])
COMPLEX16TimeSeries * resample_data(COMPLEX16TimeSeries *data, REAL8Vector *times, INT4Vector *starts, INT4Vector *stops, REAL8 sampleRate, REAL8 resampleRate, INT4 hetflag)
void destroy_filter_response(FilterResponse *filtresp)
void set_filters(Filters *iirFilters, REAL8 filterKnee, REAL8 samplerate)
void heterodyne_data(COMPLEX16TimeSeries *data, REAL8Vector *times, HeterodyneParams hetParams, REAL8 freqfactor, FilterResponse *filtresp)
static const char * LogTimeToString(double t)
INT4 remove_outliers(COMPLEX16TimeSeries *data, REAL8Vector *times, REAL8 stddevthresh)
void calibrate(COMPLEX16TimeSeries *series, REAL8Vector *datatimes, CalibrationFiles calfiles, REAL8 frequency, CHAR *channel)
#define MAXALLOC
void get_calibration_values(REAL8 *magnitude, REAL8 *phase, CHAR *calibfilename, REAL8 frequency)
LALCache * set_frame_files(INT4 *starts, INT4 *stops, LALCache *cache, INT4 *position, INT4 maxchunklength)
FilterResponse * create_filter_response(REAL8 filterKnee)
INT4 get_segment_list(INT4Vector *starts, INT4Vector *stops, CHAR *seglistfile, INT4 heterodyneflag)
INT4 verbose
void get_input_args(InputParams *inputParams, int argc, char *argv[])
void get_frame_times(CHAR *framefile, REAL8 *gpstime, INT4 *duration)
REAL8TimeSeries * get_frame_data(LALCache *framecache, CHAR *channel, REAL8 ttime, REAL8 length, INT4 duration, REAL8 samplerate, REAL8 scalefac, REAL8 highpass)
#define ROUND(a)
void filter_data(COMPLEX16TimeSeries *data, Filters *iirFilters)
#define ALPHAMIN
#define FILTERFFTTIME
#define localtime_r(timep, result)
#define ALPHAMAX
#define HEADERSIZE
#define MAXDATALENGTH
long long count
Definition: hwinject.c:371
float data[BLOCKSIZE]
Definition: hwinject.c:360
int gpstime
Definition: hwinject.c:365
size
n
def phase(point, coeffs, params, ignoreintcheck=False)
int T0
double alpha
Basic input structure to LALBarycenter.c.
REAL8 alpha
Source right ascension in ICRS J2000 coords (radians).
REAL8 dInv
1/(distance to source), in 1/sec.
LIGOTimeGPS tgps
input GPS arrival time.
REAL8 delta
Source declination in ICRS J2000 coords (radians)
LALDetector site
detector site info.
structure containing the input parameters for the binary delay function
REAL8 tb
Time of arrival (TOA) at the SSB.
EarthState earth
The current Earth state (for e.g.
structure containing the output parameters for the binary delay function
REAL8 deltaT
deltaT to add to TDB in order to account for binary
COMPLEX16Sequence * data
COMPLEX16 * data
COMPLEX16Vector * poles
Basic output structure of LALBarycenterEarth.c.
Basic output structure produced by LALBarycenter.c.
REAL8 deltaT
(TDB) - (GPS)
LIGOTimeGPS te
pulse emission time (TDB); also sometimes called `‘arrival time (TDB) of same wavefront at SSB’'
This structure contains all information about the center-of-mass positions of the Earth and Sun,...
REAL8Vector * freqResp
REAL8Vector * phaseResp
REAL8IIRFilter * filter2Im
REAL8IIRFilter * filter3Im
REAL8IIRFilter * filter3Re
REAL8IIRFilter * filter1Re
REAL8IIRFilter * filter1Im
REAL8IIRFilter * filter2Re
PulsarParameters * hetUpdate
PulsarParameters * het
TimeCorrectionType ttype
INT4 * data
UINT4 length
CHAR paramfile[256]
CHAR paramfileupdate[256]
CHAR outputfile[256]
CHAR datafile[256]
CalibrationFiles calibfiles
CHAR segfile[256]
CHAR earthfile[256]
CHAR sunfile[256]
UINT4 length
REAL8 location[3]
int * flag
INT4 gpsNanoSeconds
REAL4Sequence * data
REAL4 * data
REAL8Sequence * data
REAL8 * data
This structure will contain a vector of time corrections used during conversion from TT to TDB/TCB/Te...
enum @1 epoch
double df
double srate