LALApps 10.1.0.1-eeff03c
xtefitstoframe.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010 Chris Messenger
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 * \author C.Messenger
22 * \file
23 * \ingroup lalapps_frametools
24 * \brief
25 * This code is designed to convert an (R)XTE FITS data file into a frame file.
26 *
27 * It reads in either individually time-tagged photons or pre-binned photon counts.
28 * If the input file has been pre-processed such that it also contains barycentric
29 * time information then the user can specify that the output timeseries be
30 * barycentered. The final timeseries is output in frame file format.
31 *
32 */
33
34/***********************************************************************************************/
35/* includes */
36
37#include "config.h"
38
39/* disable -Wstrict-prototypes flag for this header file as this */
40/* a build failure for cfitsio-3.440+ */
41#pragma GCC diagnostic ignored "-Wstrict-prototypes"
42#include <fitsio.h>
43#pragma GCC diagnostic pop
44
45#include <math.h>
46#include <gsl/gsl_interp.h> /* needed for the gsl interpolation */
47#include <gsl/gsl_spline.h> /* needed for the gsl interpolation */
48#include <gsl/gsl_rng.h>
49#include <lal/LALString.h>
50#include <lal/TimeSeries.h>
51#include <lal/LALDatatypes.h>
52#include <lal/Units.h>
53#include <lal/UserInput.h>
54#include <lal/LogPrintf.h>
55#include <lal/LALFrameIO.h>
56#include <lal/LALFrStream.h>
57#include <lalappsfrutils.h>
58#include <LALAppsVCSInfo.h>
59
60/***********************************************************************************************/
61/* some global constants */
62#define MAX_DT 0.000976562 /* the maximum sample time we will use (equiv max freq 512 Hz) */
63#define MIN_DT 0.000244140625 /* the minimum sample time we will use (equiv max freq 2048 Hz) */
64#define GPSMINUSTAI 441417609 /* IMPORTANT, DO NOT TOUCH = difference between GPS and TAI in seconds on January 1, 1994, at 00:00:28 */
65#define TIMESTAMPDELTAT 1 /* the spacing used when reducing the number of event time stamps (seconds) */
66#define MAXTIMESTAMPDELTAT 256 /* the maximum allowed spacing timestamp spacing for barycentering (seconds) */
67#define APIDLENGTH 5 /* the length of APID HEX strings */
68#define STRINGLENGTH 256 /* the length of general string */
69#define LONGSTRINGLENGTH 1024 /* the length of general string */
70#define NAPID 6 /* the number of valid APIDs we can currently read */
71#define NUSELESSDATAMODE 5 /* the number of useless data modes we know of */
72#define MINFRAMELENGTH 10 /* the minimum duration of output frame file in seconds */
73#define ARRAY 0 /* data type codes */
74#define EVENT 1 /* data type codes */
75#define NPCU 5 /* the number of PCUs on XTE */
76#define MAXZEROCOUNT 1000 /* the maximum number of consecutive zeros alowed in the data */
77
78/***********************************************************************************************/
79/* error codes */
80#define XTEFITSTOFRAMEC_ENULL 1
81#define XTEFITSTOFRAMEC_ESYS 2
82#define XTEFITSTOFRAMEC_EINPUT 3
83#define XTEFITSTOFRAMEC_EMEM 4
84#define XTEFITSTOFRAMEC_ENONULL 5
85#define XTEFITSTOFRAMEC_EXLAL 6
86#define XTEFITSTOFRAMEC_MSGENULL "Arguments contained an unexpected null pointer"
87#define XTEFITSTOFRAMEC_MSGESYS "System call failed (probably file IO)"
88#define XTEFITSTOFRAMEC_MSGEINPUT "Invalid input"
89#define XTEFITSTOFRAMEC_MSGEMEM "Out of memory. Bad."
90#define XTEFITSTOFRAMEC_MSGENONULL "Output pointer is non-NULL"
91#define XTEFITSTOFRAMEC_MSGEXLAL "XLALFunction-call failed"
92
93/***********************************************************************************************/
94/* structure for storing the content read from a FITS file */
95
96/**
97 * A structure for storing vectors of detector and barycentric frame timestamps
98 * A pre-barycentered FITS file contains an original set of detector frame
99 * timestamps (not always uniformly spaced) and a corresponding set of barycentric
100 * timestamps.
101 *
102 */
103typedef struct {
104 REAL8 *dettime; /**< the detector timestamps */
105 REAL8 *barytime; /**< the barycentered timestamps */
106 INT8 length; /**< the number of timestamps */
107 REAL8 dtrow; /**< the time steps for the timestamps */
109
110/**
111 * The good time interval data read from a FITS file
112 */
113typedef struct {
114 REAL8 *start; /**< the start times of good data */
115 REAL8 *end; /**< the end times of good data */
116 INT8 length; /**< the number of gti segments */
117} GTIData;
118
119/**
120 * A structure to store TDDES2 DDL data.
121 * This is a string found in the FITS header that contains information
122 * regarding the energy range used and the timing parameters for a specific
123 * column in the FITS file.
124 *
125 */
126typedef struct {
127 INT4 ndetconfig; /**< the number of detector configurations */
128 INT4 **detectors; /**< flags indicating which detectors were being used */
129 INT4 *minenergy; /**< minimum energy channel (0-255) (one for each channel) */
130 INT4 *maxenergy; /**< maximum energy channel (0-255) (one for each channel) */
131 INT4 nenergy; /**< the number of energy channels */
132 REAL8 deltat; /**< the sampling time */
133 REAL8 offset; /**< the time offset */
134 INT4 nsamples; /**< the number of samples */
135 INT4 nchannels; /**< the number of channels (nenergy * ndetconfig) */
137
138/**
139 * A structure containing all of the relavent information extracted from the header of
140 * an (R)XTE FITS PCA file.
141 *
142 */
143typedef struct {
144 char file[STRINGLENGTH]; /**< the full path of the fits file */
145 char filename[STRINGLENGTH]; /**< the name of the fits file */
146 int type; /**< is the data array (0) or event (1) */
147 char objectname[STRINGLENGTH]; /**< the name of the source object */
148 char obsid[STRINGLENGTH]; /**< the observation ID */
149 char mode[STRINGLENGTH]; /**< stores the data mode */
150 char apid[APIDLENGTH]; /**< stores the APID hex string */
151 int LLD; /**< flag for whether it's LLD2 data */
152 long int nbytesperrow; /**< the number of bytes per row for event data */
153 double gpsoffset; /**< the number to be added to TAI times to get to GPS */
154 double ra; /**< the source right ascension */
155 double dec; /**< the source declination */
156 int nXeCntcol; /**< the number of columns with Cnt or Event data */
157 int *XeCntcolidx; /**< the XeCnt column index */
158 char **colname; /**< stores the Cnt and Event column names */
159 long int ncols; /**< the total number of columns in the data table */
160 long int nrows; /**< the number of rows ( = number of timestamps) */
161 INT4 *rowlength; /**< the row length for each column */
162 XTETDDESParams **tddes; /**< the TDDES params for each column */
163 double timedel; /**< the timedel keyword for this time series */
164 char *headerdump; /**< the entire header dumped in ascii */
165} FITSHeader;
166
167/**
168 * A structure containing event information from a single channel found in an
169 * (R)XTE FITS file.
170 */
171typedef struct {
172 CHAR *data; /**< vector of data */
173 CHAR *undefined; /**< data quality flag */
174 INT8 length; /**< length of the vector */
175 INT8 nevents; /**< the actual number of events */
176 INT8 rowlength; /**< the number of data per timestamp */
177 REAL8 deltat; /**< the sampling time */
178 INT4 energy[2]; /**< the energy channel range (0-255) */
179 CHAR detconfig[6]; /**< contains detector config string */
181
182/**
183 * A structure containing a vector of event data information. Specifically, many
184 * energy channels from a single FITS data column.
185 */
186typedef struct {
187 INT4 nchannels; /**< the number of channels */
188 XTECHARVector *channeldata; /**< pointers to individual event data vectors */
190
191/**
192 * A structure containing array data information from a single channel found in an
193 * (R)XTE FITS file.
194 */
195typedef struct {
196 UINT4 *data; /**< vector of data */
197 CHAR *undefined; /**< data quality flag */
198 INT8 length; /**< length of the vector */
199 INT8 rowlength; /**< the number of data per timestamp */
200 REAL8 deltat; /**< the sampling time */
201 INT4 energy[2]; /**< the energy channel range (0-255) */
202 CHAR detconfig[NPCU+1]; /**< contains detector config string */
204
205/**
206 * A structure containing a vector of array data information. Specifically, many
207 * energy channels from a single FITS data column.
208 */
209typedef struct {
210 INT4 nchannels; /**< the number of channels */
211 XTEUINT4Vector *channeldata; /**< a pointer to array data vectors */
213
214/**
215 * A structure containing all of the relavent information extracted from a single
216 * (R)XTE FITS PCA file
217 */
218typedef struct {
219 FITSHeader *header; /**< FITS file header information */
220 XTEUINT4Array **array; /**< array of vectors containing array data */
221 XTECHARArray **event; /**< array of vectors containing event data */
222 GTIData *gti; /**< good time interval information */
223 BarycentricData *stamps; /**< barycentric timestamps information */
224} FITSData;
225
226/**
227 * A structure for storing a timeseries of unsigned integers for XTE data.
228 *
229 * This structure contains a distilled version of the information found
230 * in the FITS data file. It stores a continuous timeseries as well as
231 * a data quality vector.
232 *
233 */
234typedef struct {
235 CHAR colname[STRINGLENGTH]; /**< name of the column from which the data was read */
236 UINT4 *data; /**< the data (timeseries of binned photon counts) */
237 CHAR *undefined; /**< a data quality flag (0=good, 1=bad) */
238 INT8 length; /**< length of the timeseries */
239 REAL8 deltat; /**< the time step size in seconds */
240 REAL8 tstart; /**< the GPS start time */
241 REAL8 T; /**< the time span in seconds */
242 INT4 energy[2]; /**< the energy channel range (0-255) */
243 CHAR detconfig[NPCU+1]; /**< contains detector config string */
245
246/**
247 * A structure for storing an array of integer timeseries for XTE data.
248 * It is designed to be able to store a number of timeseries with identical start, duration and
249 * sampling times.
250 */
251typedef struct {
252 CHAR objectname[STRINGLENGTH]; /**< the source name */
253 CHAR obsid[STRINGLENGTH]; /**< the XTE observation ID <proposal>-<target>-<viewing>-<seq no><type> */
254 CHAR apid[APIDLENGTH]; /**< the APID */
255 CHAR mode[STRINGLENGTH]; /**< the operation mode as a string */
256 INT4 bary; /**< barycentered flag */
257 INT4 lld; /**< lld flag */
258 XTEUINT4TimeSeries **ts; /**< pointer to single timeseries vectors */
259 INT4 length; /**< number of timeseries */
260 CHAR *headerdump; /**< an ascii dump of the original FITS header */
261 CHAR *comment; /**< a comment field (used to store original clargs) */
263
264/**
265 * A structure that stores user input variables
266 */
267typedef struct {
268 CHAR *inputfile; /**< directory containing input FITS files */
269 CHAR *outputdir; /**< name of output directory */
270 REAL8 deltat; /**< the desired sampling time */
271 BOOLEAN bary; /**< flag for performing barycentering */
273
274/***********************************************************************************************/
275/* global variables */
276extern int vrbflg; /**< defined in lal/lib/std/LALError.c */
277
278/* keywords in FITS file header */
279char string_OBJECT[] = "OBJECT";
280char string_RA_PNT[] = "RA_PNT";
281char string_DEC_PNT[] = "DEC_PNT";
282char string_OBS_ID[] = "OBS_ID";
283char string_TFIELDS[] = "TFIELDS";
284char string_NAXIS1[] = "NAXIS1";
285char string_TIMEZERO[] = "TIMEZERO";
286char string_DELTAT[] = "DELTAT";
287char string_DATAMODE[] = "DATAMODE";
288char string_2LLD[] = "2LLD";
289char string_HDUCLAS1[] = "HDUCLAS1";
290char string_TDDES2[] = "TDDES2";
291char string_TIMEDEL[] = "TIMEDEL";
292char string_TTYPE1[] = "TTYPE1";
293
294const char *APID[6] = {"FS37","FS3b","FS3f","FS4f","XENO","FS46"}; /* fill in the HEX APID names */
295
296const char xtechannelname[16] = "X1";
297
298/* a list of useless data modes (specifically for the Sco X-1 analysis) */
299const char *USELESSDATAMODE[5] = {"D_1US_0_249_1024_64S_F","D_1US_0_249_128_1S_F","D_1US_0_249_128_1S_2LLD_F","CB","GoodXenon"};
300
301/***********************************************************************************************/
302/* define functions */
303int main(int argc,char *argv[]);
304int ReadUserVars(int argc,char *argv[],UserInput_t *uvar, CHAR *clargs);
305
306/* FITS reading functions */
307int XLALReadFITSFile(FITSData **data,char *filename);
308int XLALReadFITSHeader(FITSHeader *fitsfileheader,fitsfile *fptr);
309int XLALReadFITSGTI(GTIData **fitsfilegti, fitsfile *fptr);
310int XLALReadFITSArrayData(XTEUINT4Array **array,fitsfile *fptr,FITSHeader *header,int col);
311int XLALReadFITSEventData(XTECHARArray **event,fitsfile *fptr,FITSHeader *header,int col);
312int XLALReadFITSTimeStamps(BarycentricData **fitsfilebary,fitsfile *fptr);
313int XLALConvertTDDES(XTETDDESParams **params,char *tddes);
314int removechar(CHAR *p,CHAR ch);
315
316/* FITS conversion functions */
328
329/* memory handling functions */
333int XLALCreateGTIData(GTIData **gti,INT8 N);
334int XLALFreeGTIData(GTIData *gti);
340
341/***********************************************************************************************/
342
343/**
344 * The main function of xtefitstoframe.c
345 *
346 * Here we read in a single XTE FITS file containing PCA data, generate a timeseries,
347 * barycenter the data if requested, and output as a frame file.
348 *
349 */
350int main( int argc, char *argv[] ) {
351
352 static const char *fn = __func__; /* store function name for log output */
353 UserInput_t XLAL_INIT_DECL(uvar); /* user input variables */
354 FITSData *fitsdata = NULL; /* a FITS data structure */
355 XTEUINT4TimeSeriesArray *ts = NULL; /* a timeseries array structure */
356 CHAR clargs[LONGSTRINGLENGTH]; /* store the command line args */
357
358 vrbflg = 1; /* verbose error-messages */
359
360 /* turn off default GSL error handler */
361 gsl_set_error_handler_off();
362
363 /* register and read all user-variables */
364 XLAL_CHECK_MAIN ( ReadUserVars( argc,argv, &uvar, clargs) == XLAL_SUCCESS, XLAL_EFUNC );
365 LogPrintf(LOG_DEBUG,"%s : read in uservars\n",fn);
366
367 /**********************************************************************************/
368 /* READ THE DATA */
369 /**********************************************************************************/
370
371 /* read in data from the input FITS file */
372 if (XLALReadFITSFile(&fitsdata,uvar.inputfile)) {
373 LogPrintf(LOG_CRITICAL,"%s : XLALReadFitsFile() failed with error = %d\n",fn,xlalErrno);
374 return 1;
375 }
376 LogPrintf(LOG_DEBUG,"%s : Read in fits data from file %s\n",fn,fitsdata->header->filename);
377
378 /* if barycentering was requested check if barycentric data was found */
379 if ((uvar.bary == 1) && (fitsdata->stamps->barytime == NULL)) {
380 LogPrintf(LOG_CRITICAL,"%s : User requested barycentering but no barycentered timestamps found in file %s.\n",fn,uvar.inputfile);
381 return 1;
382 }
383
384 /**********************************************************************************/
385 /* CONVERT THE DATA */
386 /**********************************************************************************/
387
388 /* convert fits data to timeseries data */
389 if (fitsdata->header->type == ARRAY) {
390
391 if (XLALArrayDataToXTEUINT4TimeSeriesArray(&ts,fitsdata,uvar.deltat)) {
392 LogPrintf(LOG_CRITICAL,"%s : XLALEventDataToXTEUINT4TimeSeries() failed with error = %d\n",fn,xlalErrno);
393 return 1;
394 }
395
396 }
397 else if (fitsdata->header->type == EVENT) {
398
399 if (XLALEventDataToXTEUINT4TimeSeriesArray(&ts,fitsdata,uvar.deltat)) {
400 LogPrintf(LOG_CRITICAL,"%s : XLALEventDataToXTEUINT4TimeSeries() failed with error = %d\n",fn,xlalErrno);
401 return 1;
402 }
403 }
404 else {
405 LogPrintf(LOG_CRITICAL,"%s : data type not ARRAY or EVENT. Exiting.\n",fn);
406 return 1;
407 }
408 LogPrintf(LOG_DEBUG,"%s : converted FITS data structure to a timeseries\n",fn);
409
410 /* apply GTI table */
412 LogPrintf(LOG_CRITICAL,"%s : XLALApplyGTITable() failed with error = %d\n",fn,xlalErrno);
413 return 1;
414 }
415 LogPrintf(LOG_DEBUG,"%s : applied GTI information to data from file %s\n",fn,fitsdata->header->filename);
416
417 if (uvar.bary) {
418
419 /* if barycentering then extract timestamps */
420 if (XLALReduceBarycentricData(&(fitsdata->stamps))) {
421 LogPrintf(LOG_CRITICAL,"%s : XLALReduceBarycentricData() failed with error = %d\n",fn,xlalErrno);
422 return 1;
423 }
424 LogPrintf(LOG_DEBUG,"%s : extracted barycentered timestamps from file %s\n",fn,fitsdata->header->filename);
425
426 /* perform barycentering */
428 LogPrintf(LOG_CRITICAL,"%s : XLALBarycenterXTEUINT4TimeSeries() failed with error = %d\n",fn,xlalErrno);
429 return 1;
430 }
431 LogPrintf(LOG_DEBUG,"%s : extracted barycentered timestamps from file %s\n",fn,fitsdata->header->filename);
432
433 }
434
435 /**********************************************************************************/
436 /* OUTPUT THE DATA */
437 /**********************************************************************************/
438
439 /* first add command line args to the comment field in the timeseries array */
440 if ((ts->comment = (CHAR *)XLALCalloc(LONGSTRINGLENGTH+1,sizeof(CHAR))) == NULL) {
441 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for comment field.\n",fn);
443 }
444 snprintf(ts->comment,LONGSTRINGLENGTH+1,"\n%s",clargs);
445
446 /* output data */
447 if (XLALXTEUINT4TimeSeriesArrayToFrames(ts,uvar.outputdir)) {
448 LogPrintf(LOG_CRITICAL,"%s : XLALXTEUINT4TimeSeriesToFrames() failed with error = %d\n",fn,xlalErrno);
449 return 1;
450 }
451 LogPrintf(LOG_DEBUG,"%s : output data to frame file(s)\n",fn);
452
453 /**********************************************************************************/
454 /* CLEAN UP */
455 /**********************************************************************************/
456
457 /* free memory */
458 if (XLALFreeFITSData(fitsdata)) {
459 LogPrintf(LOG_CRITICAL,"%s : XLALFreeFITSData() failed with error = %d\n",fn,xlalErrno);
460 return 1;
461 }
462 LogPrintf(LOG_DEBUG,"%s : freed FITSFileData\n",fn);
463
465 LogPrintf(LOG_CRITICAL,"%s : XLALFreeXTEUINT4TimeSeries() failed with error = %d\n",fn,xlalErrno);
466 return 1;
467 }
468 LogPrintf(LOG_DEBUG,"%s : freed timeseries data\n",fn);
469
470 /* Free config-Variables and userInput stuff */
472
473 /* did we forget anything ? */
475 LogPrintf(LOG_DEBUG,"%s : successfully checked memory leaks.\n",fn);
476
477 LogPrintf(LOG_DEBUG,"%s : successfully completed.\n",fn);
478 return 0;
479
480}
481
482/**
483 * Read in input user arguments
484 */
485int
486ReadUserVars( int argc,char *argv[], UserInput_t *uvar, CHAR *clargs)
487{
488 /* initialise user variables */
489 uvar->inputfile = NULL;
490 uvar->outputdir = NULL;
491 uvar->bary = 0;
492 uvar->deltat = MIN_DT;
493
494 /* ---------- register all user-variables ---------- */
495 XLALRegisterUvarMember( inputfile, STRING, 'i', REQUIRED, "The input FITS file name");
496 XLALRegisterUvarMember( outputdir, STRING, 'o', REQUIRED, "The output frame file directory name");
497 XLALRegisterUvarMember( deltat, REAL8, 't', OPTIONAL, "The output sampling time (in seconds)");
498 XLALRegisterUvarMember( bary, BOOLEAN, 'b', OPTIONAL, "Output barycentered data");
499
500 /* do ALL cmdline and cfgfile handling */
501 BOOLEAN should_exit = 0;
503 if ( should_exit ) { exit(1); }
504
505 /* put clargs into string */
506 strcpy(clargs,"");
507 for ( int i=0;i<argc;i++) {
508 strcat(clargs,argv[i]);
509 strcat(clargs," ");
510 }
511
512 return XLAL_SUCCESS;
513}
514
515
516
517/**
518 * This function reads in data from a FITS file and returns a FITSdata data structure.
519 */
520int XLALReadFITSFile(FITSData **fitsfiledata, /**< [out] FITS file null data structure */
521 CHAR *filepath /**< [in] full path to input FITS file */
522 )
523{
524
525 const CHAR *fn = __func__; /* store function name for log output */
526 fitsfile *fptr; /* pointer to the FITS file, defined in fitsio.h */
527 INT4 status = 0; /* fitsio status flag initialised */
528 INT4 i; /* counter */
529 FITSHeader *header = NULL; /* temporary pointer */
530
531 /* check input arguments */
532 if ((*fitsfiledata) != NULL) {
533 LogPrintf(LOG_CRITICAL,"%s: Invalid input, output FITSdata structure != NULL.\n",fn);
535 }
536 LogPrintf(LOG_DEBUG,"%s : checked input arguments\n",fn);
537
538 /* allocate memory for output FITS data structure and header */
539 if ( ( (*fitsfiledata) = (FITSData *)LALCalloc(1,sizeof(FITSData))) == NULL ) {
540 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for FITSdata structure.\n",fn);
542 }
543 if ( ( (*fitsfiledata)->header = (FITSHeader *)LALCalloc(1,sizeof(FITSHeader))) == NULL ) {
544 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for FITSdata structure.\n",fn);
546 }
547 LogPrintf(LOG_DEBUG,"%s : allocated memory for the FITS file and it's header.\n",fn);
548
549 /* initialise data pointers */
550 (*fitsfiledata)->array = NULL;
551 (*fitsfiledata)->event = NULL;
552 (*fitsfiledata)->gti = NULL;
553 (*fitsfiledata)->stamps = NULL;
554 header = (*fitsfiledata)->header;
555
556 /* open the fits file */
557 if (fits_open_file(&fptr,filepath,READONLY,&status)) {
558 fits_report_error(stderr,status);
559 LogPrintf(LOG_CRITICAL,"%s : failed to open FITS file %s for reading.\n",fn,filepath);
561 }
562 LogPrintf(LOG_DEBUG,"%s : opened the input FITS file\n",fn);
563
564 /* add full file path to the header information */
565#if __GNUC__ >= 8
566#pragma GCC diagnostic push
567#pragma GCC diagnostic ignored "-Wstringop-truncation"
568#endif
569 strncpy(header->file,filepath,STRINGLENGTH);
570#if __GNUC__ >= 8
571#pragma GCC diagnostic pop
572#endif
573
574 /* read the header information from the first extension */
575 if (XLALReadFITSHeader(header,fptr)) {
576 LogPrintf(LOG_CRITICAL,"%s : XLALReadFitsHeader() failed to read header information from FITS file %s with error = %d.\n",fn,filepath,xlalErrno);
578 }
579 LogPrintf(LOG_DEBUG,"%s : read the FITS file header\n",fn);
580
581 /* read GTI information from the second extension */
582 if (XLALReadFITSGTI(&((*fitsfiledata)->gti),fptr)) {
583 LogPrintf(LOG_CRITICAL,"%s : XLALReadFITSGTI() failed to read GTI information from FITS file %s with error = %d.\n",fn,filepath,xlalErrno);
585 }
586 LogPrintf(LOG_DEBUG,"%s : read the FITS file GTI table\n",fn);
587
588 /* read the timestamps information */
589 if (XLALReadFITSTimeStamps(&((*fitsfiledata)->stamps),fptr)) {
590 LogPrintf(LOG_CRITICAL,"%s : XLALReadFITSTimeStamps() failed to read time stamps information from FITS file %s with error = %d.\n",fn,filepath,xlalErrno);
592 }
593 LogPrintf(LOG_DEBUG,"%s : read the FITS file timestamps\n",fn);
594
595 /* read in the data - (Array mode) */
596 if (header->type == ARRAY) {
597
598 /* allocate memory for array data pointers (one for each column) */
599 if (((*fitsfiledata)->array = (XTEUINT4Array **)LALCalloc(header->nXeCntcol,sizeof(XTEUINT4Array *))) == NULL) {
600 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for array data pointers.\n",fn);
602 }
603 LogPrintf(LOG_DEBUG,"%s : allocated memory for the array data\n",fn);
604
605 /* loop over XeCnt columns and read in each column */
606 for (i=0;i<header->nXeCntcol;i++) {
607
608 LogPrintf(LOG_DEBUG,"%s : reading array data from column %d\n",fn,header->XeCntcolidx[i]);
609
610 /* read in all channels from this column */
611 if (XLALReadFITSArrayData(&((*fitsfiledata)->array[i]),fptr,header,i)) {
612 LogPrintf(LOG_CRITICAL,"%s : XLALReadFITSBinnedData() failed to read binned data from FITS file %s with error = %d.\n",fn,filepath,xlalErrno);
614 }
615 LogPrintf(LOG_DEBUG,"%s : read array data from column %d\n",fn,header->XeCntcolidx[i]);
616
617 }
618
619 }
620
621 /* read in the data - Event */
622 else {
623
624 /* allocate memory for event data pointers */
625 if (((*fitsfiledata)->event = (XTECHARArray **)LALCalloc(header->nXeCntcol,sizeof(XTECHARArray *))) == NULL) {
626 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for event data pointers.\n",fn);
628 }
629 LogPrintf(LOG_DEBUG,"%s : allocated memory for the event data\n",fn);
630
631 /* loop over XeCnt columns and read in each column */
632 for (i=0;i<header->nXeCntcol;i++) {
633
634 LogPrintf(LOG_DEBUG,"%s : reading event data from column %d\n",fn,header->XeCntcolidx[i]);
635
636 /* read in all channels from this column */
637 if (XLALReadFITSEventData(&((*fitsfiledata)->event[i]),fptr,header,i)) {
638 LogPrintf(LOG_CRITICAL,"%s : XLALReadFITSEventData() failed to read event data from FITS file %s with error = %d.\n",fn,filepath,xlalErrno);
640 }
641
642 }
643
644 }
645
646 /* close the file */
647 if (fits_close_file(fptr,&status)) {
648 fits_report_error(stderr,status);
649 LogPrintf(LOG_CRITICAL,"%s : failed to close FITS file %s.\n",fn,filepath);
651 }
652
653 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
654 return XLAL_SUCCESS;
655
656}
657
658/**
659 * Read in GTI (good time interval) table from FITS file.
660 * The second extension HDU2 (3 from the beginning) lists the standard good time intervals,
661 * i.e. the start and stop times of all the potentially useable data in the file.
662 *
663 */
664int XLALReadFITSGTI(GTIData **gti, /**< [out] Good time interval data structure */
665 fitsfile *fptr /**< [in] fitsfile file pointer */
666 )
667{
668
669 const CHAR *fn = __func__; /* store function name for log output */
670 INT4 i; /* counter */
671 INT4 hdutype; /* returned value of the header type */
672 REAL8 doublenull = 0.0; /* dummy variable ? */
673 INT4 anynull; /* dummy ? */
674 INT4 status = 0; /* fitsio status flag initialised */
675 long int ngtirows; /* the number of rows in the GTI table */
676 REAL8 tzero; /* the clock correction */
677 REAL8 gpsoffset; /* the correction needed to convert time values to GPS */
678 char comment[80]; /* a temporary comment string */
679
680 /* check input arguments */
681 if ((*gti) != NULL) {
682 LogPrintf(LOG_CRITICAL,"%s: Invalid input, output GTIData structure != NULL.\n",fn);
684 }
685 if (fptr == NULL) {
686 LogPrintf(LOG_CRITICAL,"%s: Invalid input, input FITS file pointer = NULL.\n",fn);
688 }
689
690 /* move to the gti header - the third extension */
691 if (fits_movabs_hdu(fptr,3,&hdutype,&status)) {
692 fits_report_error(stderr,status);
693 LogPrintf(LOG_CRITICAL,"%s : fits_movabs_hdu() failed to move to extension header 3.\n",fn);
695 }
696
697 /* get TIMEZERO for this file - this can be read from any of the extension headers */
698 /* Timestamps plus the value of TIMEZERO provide the time in TAI as seconds since January 1, 1994, at 00:00:28 (TAI). */
699 if (fits_read_key(fptr,TDOUBLE,string_TIMEZERO,&tzero,comment,&status)) {
700 fits_report_error(stderr,status);
701 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_TIMEZERO);
703 }
704 LogPrintf(LOG_DEBUG,"%s : read tzero as %6.12f\n",fn,tzero);
705
706 /* convert tzero to GPS - this is simply the TAI time plus the GPS-TAI constant */
707 gpsoffset = tzero + (double)GPSMINUSTAI;
708 LogPrintf(LOG_DEBUG,"%s : computed GPS offset as %6.12f\n",fn,gpsoffset);
709
710 /* get number of columns in the gti table - there should be 2 */
711 {
712 int ngticols = 0;
713 if (fits_get_num_cols(fptr,&ngticols,&status)) {
714 fits_report_error(stderr,status);
715 LogPrintf(LOG_CRITICAL,"%s : fits_get_num_cols() failed to return the number of columns.\n",fn);
717 }
718 if (ngticols!=2) {
719 LogPrintf(LOG_CRITICAL,"%s : The number of GTI columns != 2.\n",fn);
721 }
722 }
723
724 /* get the number of rows in the gti table - this is the number of good segments in the file */
725 if (fits_get_num_rows(fptr,&ngtirows,&status)) {
726 fits_report_error(stderr,status);
727 LogPrintf(LOG_CRITICAL,"%s : fits_get_num_rows() failed to return the number of rows.\n",fn);
729 }
730 if (ngtirows<1) {
731 LogPrintf(LOG_CRITICAL,"%s : found %ld rows in GTI table, should be >0.\n",fn,ngtirows);
733 }
734 LogPrintf(LOG_DEBUG,"%s : found %ld rows in GTI table.\n",fn,ngtirows);
735
736 /* allocate memory for GTI table */
737 if (XLALCreateGTIData(gti,ngtirows)) {
738 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for GTI start time data with error = %d.\n",fn,xlalErrno);
740 }
741
742 /* read the gti start and end values */
743 {
744 if (fits_read_col(fptr,TDOUBLE,1,1,1,(*gti)->length,&doublenull,(*gti)->start,&anynull,&status)) {
745 fits_report_error(stderr,status);
746 LogPrintf(LOG_CRITICAL,"%s : fits_read_col() failed to read GTI table start times.\n",fn);
748 }
749 if (fits_read_col(fptr,TDOUBLE,2,1,1,(*gti)->length,&doublenull,(*gti)->end,&anynull,&status)) {
750 fits_report_error(stderr,status);
751 LogPrintf(LOG_CRITICAL,"%s : fits_read_col() failed to read GTI table end times.\n",fn);
753 }
754 }
755
756 /* IMPORTANT : convert all times to GPS using the offset value */
757 for (i=0;i<(*gti)->length;i++) {
758 (*gti)->start[i] += gpsoffset;
759 (*gti)->end[i] += gpsoffset;
760 LogPrintf(LOG_DEBUG,"%s : found GTI range %6.12f -> %6.12f.\n",fn,(*gti)->start[i],(*gti)->end[i]);
761 }
762
763 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
764 return XLAL_SUCCESS;
765
766}
767
768/**
769 * Reads in the FITS file first extension header information.
770 * The first extension Header HDU1 (2 from the beginning) contains keywords which
771 * provide a complete and detailed description of the contents of the first
772 * extension. For convenience, it also contains some of the same information as
773 * the primary header.
774 *
775 */
776int XLALReadFITSHeader(FITSHeader *header, /**< [out] The FITS file header structure */
777 fitsfile *fptr /**< [in] fitsfile file pointer */
778 )
779{
780
781 const char *fn = __func__; /* store function name for log output */
782 int hdutype; /* the return value when moving to headers */
783 char comment[80]; /* a temporary comment string */
784 char type[256]; /* stores the type (array or event) */
785 int status = 0; /* fitsio status flag initialised */
786 int i; /* counter */
787
788 /* check input arguments */
789 if (header == NULL) {
790 LogPrintf(LOG_CRITICAL,"%s: Invalid input, output FITSHeader structure == NULL.\n",fn);
792 }
793 if (fptr == NULL) {
794 LogPrintf(LOG_CRITICAL,"%s: Invalid input, input FITS file pointer = NULL.\n",fn);
796 }
797
798 /* first we extract the filename from the full file path */
799 {
800 char *c;
801 if ((c = strrchr(header->file,'/'))) c++;
802 else c = header->file;
803 strcpy(header->filename,c);
804 }
805 LogPrintf(LOG_DEBUG,"%s : extracted filename as %s\n",fn,header->filename);
806
807 /* now we extract the APID hex string from the filename */
808 if(APIDLENGTH<=snprintf(header->apid,APIDLENGTH,"%s",header->filename))
809 printf("Warning: truncated filename %s\n",header->filename);
810 LogPrintf(LOG_DEBUG,"%s : extracted APID as %s\n",fn,header->apid);
811
812 /* check that APID is one we can currently deal with */
813 /* if not then we exit immediately with error code 0 */
814 {
815 INT4 j = 0;
816 for (i=0;i<NAPID;i++) if (!strncmp(header->apid,APID[i],APIDLENGTH-1)) j++;
817 if (j==0) {
818 LogPrintf(LOG_NORMAL,"%s : Sorry, currently unable to read data with APID = %s. Exiting.\n",fn,header->apid);
819 exit(0);
820 }
821 }
822
823 /* move to the first extension header */
824 if (fits_movabs_hdu(fptr,2,&hdutype,&status)) {
825 fits_report_error(stderr,status);
826 LogPrintf(LOG_CRITICAL,"%s : fits_movabs_hdu() failed to move to the first extension header.\n",fn);
828 }
829
830 /* get mode string defining the detector configuration e.g. B_250us_2A_0_17_Q */
831 if (fits_read_key(fptr,TSTRING,string_DATAMODE,&(header->mode),comment,&status)) {
832 fits_report_error(stderr,status);
833 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_DATAMODE);
835 }
836 LogPrintf(LOG_DEBUG,"%s : read data mode as %s\n",fn,header->mode);
837
838 /* check that the data mode is one we can currently deal with */
839 /* if not then we exit immediately with error code 0 */
840 {
841 INT4 j = 0;
843 if (j>0) {
844 LogPrintf(LOG_NORMAL,"%s : Sorry, currently unable to read data data mode = %s. Exiting.\n",fn,header->mode);
845 exit(0);
846 }
847 }
848
849 /* check object name and store in output structure */
850 {
851 CHAR tempobject[STRINGLENGTH];
852 if (fits_read_key(fptr,TSTRING,string_OBJECT,&tempobject,comment,&status)) {
853 fits_report_error(stderr,status);
854 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_OBJECT);
856 }
857 /* need to get rid of all non-allowed characters e.g. "-" and "_" */
858 removechar(tempobject,'_');
859 removechar(tempobject,'-');
860 strncpy(header->objectname,tempobject,STRINGLENGTH);
861 }
862 LogPrintf(LOG_DEBUG,"%s : checked object name is %s.\n",fn,header->objectname);
863
864 /* read in sky position */
865 if (fits_read_key(fptr,TDOUBLE,string_RA_PNT,&(header->ra),comment,&status)) {
866 fits_report_error(stderr,status);
867 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_RA_PNT);
869 }
870 if (fits_read_key(fptr,TDOUBLE,string_DEC_PNT,&(header->dec),comment,&status)) {
871 fits_report_error(stderr,status);
872 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_DEC_PNT);
874 }
875 LogPrintf(LOG_DEBUG,"%s : read ra = %6.12f dec = %6.12f.\n",fn,header->ra,header->dec);
876
877 /* extract obsid - goodxenon data will not have an obsid field*/
878 if (strstr(header->filename,"XENON") == NULL) {
879
880 CHAR tempobsid[STRINGLENGTH];
881 if (fits_read_key(fptr,TSTRING,string_OBS_ID,&tempobsid,comment,&status)) {
882 fits_report_error(stderr,status);
883 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_OBS_ID);
885 }
886 /* need to get rid of all non-allowed characters e.g. "-" and "_" */
887 removechar(tempobsid,'_');
888 removechar(tempobsid,'-');
889 strncpy(header->obsid,tempobsid,STRINGLENGTH);
890 }
891 else {
892 /* if XENON data then we just write XENON in the odsid because there is no true OBSID info avaialable */
893 snprintf(header->obsid,STRINGLENGTH,"XENON");
894 }
895 LogPrintf(LOG_DEBUG,"%s : read obsid as %s\n",fn,header->obsid);
896
897 /* get the number of rows in the data table */
898 if (fits_get_num_rows(fptr,&(header->nrows),&status)) {
899 fits_report_error(stderr,status);
900 LogPrintf(LOG_CRITICAL,"%s : fits_get_num_rows() failed to read in number of rows.\n",fn);
902 }
903 LogPrintf(LOG_DEBUG,"%s : found %ld rows in first extension.\n",fn,header->nrows);
904
905 /* get number of columns in the data table */
906 if (fits_read_key(fptr,TINT,string_TFIELDS,&(header->ncols),comment,&status)) {
907 fits_report_error(stderr,status);
908 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_TFIELDS);
910 }
911 LogPrintf(LOG_DEBUG,"%s : found %ld columns in first extension.\n",fn,header->ncols);
912
913 /* get the type SA or SE */
914 /* this tells us whether it is binned (science-array) or event (science-event) data */
915 /* if not either mode then we exit immediately with no error */
916 if (fits_read_key(fptr,TSTRING,string_HDUCLAS1,&type,comment,&status)) {
917 fits_report_error(stderr,status);
918 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_HDUCLAS1);
920 }
921 if (strcmp(type,"ARRAY")==0) header->type = 0;
922 else if ( (strcmp(type,"EVENTS") == 0 ) || (strcmp(type,"EVENT") == 0 ) ) header->type = 1;
923 else {
924 LogPrintf(LOG_NORMAL,"%s : data type \"%s\" not recognised. Exiting. \n",fn,type);
925 exit(0);
926 }
927 LogPrintf(LOG_DEBUG,"%s : data type is %s\n",fn,type);
928
929 /* allocate memory for column data */
930 if ((header->XeCntcolidx = (INT4 *)LALCalloc(header->ncols,sizeof(INT4))) == NULL) {
931 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for column data.\n",fn);
933 }
934 if ((header->colname = (CHAR **)LALCalloc(header->ncols,sizeof(CHAR *))) == NULL) {
935 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for column names.\n",fn);
937 }
938 for (i=0;i<header->ncols;i++) {
939 if ((header->colname[i] = (CHAR *)LALCalloc(STRINGLENGTH,sizeof(CHAR))) == NULL) {
940 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for column names.\n",fn);
942 }
943 }
944 LogPrintf(LOG_DEBUG,"%s : allocated memory for column data\n",fn);
945
946 /* record all column numbers and names that have XeCnt data */
947 {
948 char colnamestring[STRINGLENGTH];
949 char keyword[STRINGLENGTH];
950 INT4 idx = 0;
951 for (i=0;i<header->ncols;i++) {
952 snprintf(keyword,STRINGLENGTH,"TTYPE%d",i+1);
953 if (fits_read_key(fptr,TSTRING,keyword,&colnamestring,comment,&status)) {
954 fits_report_error(stderr,status);
955 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,keyword);
957 }
958 if ( ((strstr(colnamestring,"Cnt")!=NULL) && (strstr(colnamestring,"MeanCnt")==NULL)
959 && (strstr(colnamestring,"RemainingCnt")==NULL) && (strstr(colnamestring,"VLECnt")==NULL)
960 && (strstr(colnamestring,"VpCnt")==NULL)) || ((strncmp(colnamestring,"Event",5)==0))) {
961 header->XeCntcolidx[idx] = i+1;
962 snprintf(header->colname[idx],STRINGLENGTH,"%s",colnamestring);
963 idx ++;
964 LogPrintf(LOG_DEBUG,"%s : found col %d contains Cnt or Event data.\n",fn,i+1);
965 }
966 }
967 header->nXeCntcol = idx;
968 if (!header->nXeCntcol) {
969 LogPrintf(LOG_NORMAL,"%s : failed to find XeCnt or Event columns in file.\n",fn);
970 exit(0);
971 }
972 }
973
974 /* resize memory for column data */
975 if ((header->XeCntcolidx = (INT4 *)LALRealloc(header->XeCntcolidx,header->nXeCntcol*sizeof(INT4))) == NULL) {
976 LogPrintf(LOG_CRITICAL,"%s : failed to re-allocate memory for column data.\n",fn);
978 }
979 for (i=header->nXeCntcol;i<header->ncols;i++) XLALFree(header->colname[i]);
980 if ((header->colname = (CHAR **)LALRealloc(header->colname,header->nXeCntcol*sizeof(CHAR *))) == NULL) {
981 LogPrintf(LOG_CRITICAL,"%s : failed to re-allocate memory for column names.\n",fn);
983 }
984 LogPrintf(LOG_DEBUG,"%s : re-allocated memory for column data\n",fn);
985
986 /* get number of bytes per row in the data table */
987 if (fits_read_key(fptr,TLONG,string_NAXIS1,&(header->nbytesperrow),comment,&status)) {
988 fits_report_error(stderr,status);
989 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_NAXIS1);
991 }
992 LogPrintf(LOG_DEBUG,"%s : read the number of bytes per row as %ld\n",fn,header->nbytesperrow);
993
994 /* if the data mode is equal to 2LLD then we record this in the LLD (Lower Level Discriminator) flag */
995 if (strstr(header->mode,string_2LLD)!=NULL) header->LLD = 1;
996 else header->LLD = 0;
997 LogPrintf(LOG_DEBUG,"%s : set LLD flag = %d\n",fn,header->LLD);
998
999 /* get sampling time - this is the actual sampling time interval in seconds */
1000 if (fits_read_key(fptr,TDOUBLE,string_TIMEDEL,&(header->timedel),comment,&status)) {
1001 fits_report_error(stderr,status);
1002 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_TIMEDEL);
1004 }
1005 LogPrintf(LOG_DEBUG,"%s : read TIMEDEL keyword as %6.12e\n",fn,header->timedel);
1006
1007 /* allocate memory for the tddes params and rowlength for each column */
1008 if ((header->tddes = (XTETDDESParams **)LALCalloc(header->nXeCntcol,sizeof(XTETDDESParams *))) == NULL) {
1009 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for tddes data.\n",fn);
1011 }
1012 if ((header->rowlength = (INT4 *)LALCalloc(header->nXeCntcol,sizeof(INT4))) == NULL) {
1013 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for rowlength data.\n",fn);
1015 }
1016 LogPrintf(LOG_DEBUG,"%s : allocated memory for %d TDDES structures\n",fn,header->nXeCntcol);
1017
1018 /* get the TDDES<col> keyword - describes the data in each column */
1019 /* this tells us the sampling time and the energy channels used */
1020 /* A typical string of DDL (Data Description Language) is a concatenation of tokens */
1021 /* (denoted by single letters) with assigned values (enclosed in square brackets). */
1022 /* for each relevant column */
1023 for (i=0;i<header->nXeCntcol;i++) {
1024
1025 INT4 j;
1026 char *tddes_string;
1027 CHAR keyword[STRINGLENGTH];
1028 INT4 col = header->XeCntcolidx[i];
1029 int naxis;
1030 long int naxes[2];
1031 INT4 maxdim = 2;
1032
1033 snprintf(keyword,STRINGLENGTH,"TDDES%d",col);
1034 if (fits_read_key_longstr(fptr,keyword,&tddes_string,comment,&status)) {
1035 fits_report_error(stderr,status);
1036 LogPrintf(LOG_CRITICAL,"%s : fits_read_key_longstr() failed to read in long string keyword %s.\n",fn,keyword);
1038 }
1039 LogPrintf(LOG_DEBUG,"%s : read column %d TDDES string as %s\n",fn,col,tddes_string);
1040
1041 /* extract energy and sampling time info from the TDDES2 DDL string */
1042 if (XLALConvertTDDES(&(header->tddes[i]),tddes_string)) {
1043 LogPrintf(LOG_CRITICAL,"%s : XLALConvertTDDES() failed to convert TDDES string %s with error = %d.\n",fn,tddes_string,xlalErrno);
1045 }
1046 LogPrintf(LOG_DEBUG,"%s : found %d channels\n",fn,header->tddes[i]->nchannels);
1047 LogPrintf(LOG_DEBUG,"%s : found %d nsamples\n",fn,header->tddes[i]->nsamples);
1048 for(j=0;j<header->tddes[i]->nenergy;j++) LogPrintf(LOG_DEBUG,"%s : energy ranges extracted as %d - %d\n",fn,header->tddes[i]->minenergy[j],header->tddes[i]->maxenergy[j]);
1049 for(j=0;j<header->tddes[i]->ndetconfig;j++) LogPrintf(LOG_DEBUG,"%s : detector config extracted as [%d %d %d %d %d]\n",fn,
1050 header->tddes[i]->detectors[j][0],header->tddes[i]->detectors[j][1],
1051 header->tddes[i]->detectors[j][2],header->tddes[i]->detectors[j][3],header->tddes[i]->detectors[j][4]);
1052
1053 /* if we have been unable to extract timing information from the DDL */
1054 /* string then we use the TIMEDEL keyword value as the sampling time */
1055 if (!header->tddes[i]->deltat) header->tddes[i]->deltat = header->timedel;
1056
1057 /* free string mem */
1058 free(tddes_string);
1059
1060 /* get dimensions of the data table for this column */
1061 if (fits_read_tdim(fptr,col,maxdim,&naxis,naxes,&status)) {
1062 fits_report_error(stderr,status);
1063 LogPrintf(LOG_CRITICAL,"%s : fits_read_tdim() failed to read in the number and size of dimensions in col %d.\n",fn,col);
1065 }
1066 if (naxis > 2) {
1067 LogPrintf(LOG_CRITICAL,"%s : the size of dimensions in col %d = %d. Can only deal with 1 or 2 dimensional tables.\n",fn,col,naxis);
1068 exit(0);
1069 }
1070 if (naxis == 1) naxes[1] = 1;
1071 header->rowlength[i] = (INT4)naxes[0];
1072 LogPrintf(LOG_DEBUG,"%s : read dim as %d nchannels as %ld and channelsize as %ld for col %d\n",fn,naxis,naxes[1],naxes[0],col);
1073 LogPrintf(LOG_DEBUG,"%s : total row length = %ld\n",fn,naxes[1]*header->rowlength[i]);
1074
1075 /* check that this is consistent with the number of channels we found */
1076 if (naxes[1] != header->tddes[i]->nchannels) {
1077 LogPrintf(LOG_CRITICAL,"%s : The number of energy channels read from TDDES %d != %ld the number given by the TDIM keyword for col %d.\n",fn,header->tddes[i]->nchannels,naxes[1],col);
1079 }
1080
1081 }
1082
1083 /* dump entire header into a long string */
1084 /* we do extra stuff to add newline characters at the end of each 80 character long stretch */
1085 /* it makes it look nicer when you do a frame dump */
1086 {
1087 INT4 nkeys;
1088 CHAR *dummy = NULL;
1089 if (fits_hdr2str(fptr,0,NULL,0,&dummy,&nkeys,&status)) {
1090 fits_report_error(stderr,status);
1091 LogPrintf(LOG_CRITICAL,"%s : fits_hdr2str() failed to read header.\n",fn);
1093 }
1094
1095 /* allocate memory for new char vector */
1096 if ((header->headerdump = (CHAR *)XLALCalloc(1+nkeys*81,sizeof(CHAR))) == NULL) {
1097 LogPrintf(LOG_CRITICAL,"%s : failed to re-allocate memory for column names.\n",fn);
1099 }
1100
1101 /* add newline characters after every 80 CHARS */
1102 for (i=0;i<nkeys;i++) {
1103
1104 INT4 idx = i*80;
1105 CHAR tempstr[81];
1106 CHAR kwpair[80];
1107 snprintf(kwpair,80,"%s",dummy+idx);
1108 snprintf(tempstr,81,"\n%s",kwpair);
1109 strncat(header->headerdump,tempstr,81);
1110
1111 }
1112 free(dummy);
1113 }
1114
1115 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
1116 return XLAL_SUCCESS;
1117
1118}
1119/**
1120 * Removes a character from a string
1121 */
1122int removechar(CHAR *p, /**< [in/out] string to edit */
1123 CHAR ch /**< [in] character to remove */
1124 )
1125{
1126 const char *fn = __func__; /* store function name for log output */
1127 CHAR *temp = p;
1128
1129 while (*temp) {
1130
1131 if ((*temp) == (CHAR)ch) {
1132
1133 while (*temp) {
1134 (*temp) = *(temp+1);
1135 if (*temp) temp++;
1136 }
1137 temp = p;
1138
1139 }
1140 temp++;
1141
1142 }
1143
1144 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
1145 return XLAL_SUCCESS;
1146
1147}
1148
1149/**
1150 * Reads in FITS file first extension header timestamps information.
1151 * It also reads in barycentric timestamps if they are present.
1152 *
1153 */
1154int XLALReadFITSTimeStamps(BarycentricData **stamps, /**< [out] the detector and barycenter timestamps */
1155 fitsfile *fptr /**< [in] a FITS file pointer */
1156 )
1157{
1158
1159 const char *fn = __func__; /* store function name for log output */
1160 long int j;
1161 char comment[80];
1162 double doublenull = 0.0;
1163 int anynull;
1164 int hdutype;
1165 int status = 0; /* fitsio status flag initialised */
1166 REAL8 tzero;
1167 REAL8 gpsoffset;
1168 INT4 ncols;
1169 INT4 detidx = 0;
1170 INT4 baryidx = 0;
1171 long int numrows = 0;
1172
1173 /* check input arguments */
1174 if ((*stamps) != NULL) {
1175 LogPrintf(LOG_CRITICAL,"%s: Invalid input, output BarycentricData structure != NULL.\n",fn);
1177 }
1178 if (fptr == NULL) {
1179 LogPrintf(LOG_CRITICAL,"%s: Invalid input, input FITS file pointer = NULL.\n",fn);
1181 }
1182
1183 /* allocate memory for timestamps structure */
1184 if (((*stamps) = (BarycentricData *)LALCalloc(1,sizeof(BarycentricData))) == NULL) {
1185 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for timestamps structure.\n",fn);
1187 }
1188
1189 /* move to the first extension header */
1190 if (fits_movabs_hdu(fptr,2,&hdutype,&status)) {
1191 fits_report_error(stderr,status);
1192 LogPrintf(LOG_CRITICAL,"%s : fits_movabs_hdu() failed to move to the first extension header.\n",fn);
1194 }
1195
1196 /* get DELTAT for this file */
1197 /* DELTAT gives the the time between each row in the file - these are of order second in length */
1198 if (fits_read_key(fptr,TDOUBLE,string_DELTAT,&((*stamps)->dtrow),comment,&status)) {
1199 fits_report_error(stderr,status);
1200 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_DELTAT);
1202 }
1203 LogPrintf(LOG_DEBUG,"%s : read DELTAT keyword as %6.12f\n",fn,(*stamps)->dtrow);
1204
1205 /* get TIMEZERO for this file */
1206 /* Timestamps plus the value of TIMEZERO provide the time in TAI as seconds since January 1, 1994, at 00:00:28 (TAI). */
1207 if (fits_read_key(fptr,TDOUBLE,string_TIMEZERO,&tzero,comment,&status)) {
1208 fits_report_error(stderr,status);
1209 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_TIMEZERO);
1211 }
1212 LogPrintf(LOG_DEBUG,"%s : read tzero as %6.12f\n",fn,tzero);
1213
1214 /* convert tzero to GPS - this is simply the TAI time plus the GPS-TAI constant */
1215 gpsoffset = tzero + (double)GPSMINUSTAI;
1216 LogPrintf(LOG_DEBUG,"%s : converted tzero to gps -> %6.12f\n",fn,gpsoffset);
1217
1218 /* get the number of rows in the data table */
1219 if (fits_get_num_rows(fptr,&numrows,&status)) {
1220 fits_report_error(stderr,status);
1221 LogPrintf(LOG_CRITICAL,"%s : fits_get_num_rows() failed to read in number of rows.\n",fn);
1223 }
1224 (*stamps)->length = numrows;
1225 LogPrintf(LOG_DEBUG,"%s : found %" LAL_INT8_FORMAT " rows in first extension.\n",fn,(*stamps)->length);
1226
1227 /* get number of columns in the data table */
1228 if (fits_read_key(fptr,TINT,string_TFIELDS,&ncols,comment,&status)) {
1229 fits_report_error(stderr,status);
1230 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,string_TFIELDS);
1232 }
1233 LogPrintf(LOG_DEBUG,"%s : found %d fields in first extension.\n",fn,ncols);
1234
1235 /* check if there are columns called time and barytime */
1236 {
1237 char timestring[STRINGLENGTH];
1238 char keyword[STRINGLENGTH];
1239 INT4 i;
1240 for (i=0;i<ncols;i++) {
1241 snprintf(keyword,STRINGLENGTH,"TTYPE%d",i+1);
1242 if (fits_read_key(fptr,TSTRING,keyword,&timestring,comment,&status)) {
1243 fits_report_error(stderr,status);
1244 LogPrintf(LOG_CRITICAL,"%s : fits_read_key() failed to read in keyword %s.\n",fn,keyword);
1246 }
1247 if (XLALStringNCaseCompare(timestring,"time",STRINGLENGTH)==0) detidx = i+1;
1248 if (XLALStringNCaseCompare(timestring,"barytime",8)==0) baryidx = i+1;
1249 }
1250
1251 }
1252
1253 /* if we have a time column then allocate memory and read in the timestamps */
1254 if (detidx) {
1255
1256 /* allocate memory for detector frame timestamps */
1257 if (((*stamps)->dettime = (double *)LALCalloc((*stamps)->length,sizeof(double))) == NULL) {
1258 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for detector frame timestamps.\n",fn);
1260 }
1261
1262 /* read the time detector frame timestamps from column 1 */
1263 if (fits_read_col(fptr,TDOUBLE,detidx,1,1,(*stamps)->length,&doublenull,(*stamps)->dettime,&anynull,&status)) {
1264 fits_report_error(stderr,status);
1265 LogPrintf(LOG_CRITICAL,"%s : fits_read_col() failed to read in detector frame timestamps.\n",fn);
1267 }
1268
1269 /* IMPORTANT : convert to GPS using the offset value */
1270 for (j=0;j<(*stamps)->length;j++) (*stamps)->dettime[j] += gpsoffset;
1271 LogPrintf(LOG_DEBUG,"%s : read first detector frame timestamp as %6.12f\n",fn,(*stamps)->dettime[0]);
1272
1273 }
1274 else {
1275 LogPrintf(LOG_CRITICAL,"%s : failed to find \"Time\" column.\n",fn);
1277 }
1278
1279 /* if the file contains barycentered times */
1280 if (baryidx) {
1281
1282 /* allocate memory for barycentric frame timestamps */
1283 if (((*stamps)->barytime = (double *)LALCalloc((*stamps)->length,sizeof(double))) == NULL) {
1284 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for barycentric frame timestamps.\n",fn);
1286 }
1287
1288 /* read the barycentered time values from final column */
1289 if (fits_read_col(fptr,TDOUBLE,baryidx,1,1,(*stamps)->length,&doublenull,(*stamps)->barytime,&anynull,&status)) {
1290 fits_report_error(stderr,status);
1291 LogPrintf(LOG_CRITICAL,"%s : fits_read_col() failed to read in barycentric frame timestamps.\n",fn);
1293 }
1294
1295 /* IMPORTANT : convert to GPS using the offset value */
1296 for (j=0;j<(*stamps)->length;j++) (*stamps)->barytime[j] += gpsoffset;
1297 LogPrintf(LOG_DEBUG,"%s : read first barycentered time value as %6.12f\n",fn,(*stamps)->barytime[0]);
1298
1299 }
1300 else (*stamps)->barytime = NULL;
1301
1302 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
1303 return XLAL_SUCCESS;
1304
1305}
1306
1307/**
1308 * Reads in array mode data from a FITS file.
1309 * Science array mode data is binned data and so contains photon counts.
1310 *
1311 */
1312int XLALReadFITSArrayData(XTEUINT4Array **array, /**< [out] the output data vector */
1313 fitsfile *fptr, /**< [in] a fitsfile file pointer */
1314 FITSHeader *header, /**< [in] a fitsfile header */
1315 INT4 colidx /**< [in] the column to be read */
1316 )
1317{
1318
1319 const char *fn = __func__; /* store function name for log output */
1320 INT4 status = 0; /* fitsio status flag initialised */
1321 INT4 anynull;
1322 INT4 i;
1323 XTETDDESParams *tddes = NULL;
1324 INT4 totallength = 0;
1325 UINT4 *tempdata = NULL;
1326 CHAR *tempundefined = NULL;
1327 INT4 col;
1328
1329 /* check input arguments */
1330 if ((*array) != NULL) {
1331 LogPrintf(LOG_CRITICAL,"%s: Invalid input, output XTEUINT4Vector structure != NULL.\n",fn);
1333 }
1334 if (fptr == NULL) {
1335 LogPrintf(LOG_CRITICAL,"%s: Invalid input, input FITS file pointer = NULL.\n",fn);
1337 }
1338 if (header == NULL) {
1339 LogPrintf(LOG_CRITICAL,"%s: Invalid input, input FITS file header = NULL.\n",fn);
1341 }
1342 col = header->XeCntcolidx[colidx];
1343 if ((col < 1) || (col>header->ncols)) {
1344 LogPrintf(LOG_CRITICAL,"%s: Invalid input, column number must be > 0 and < number of columns in file (%ld).\n",fn,header->ncols);
1346 }
1347 LogPrintf(LOG_DEBUG,"%s : checked input\n",fn);
1348
1349 /* define temporary pointer to current tddes structure for clarity */
1350 tddes = header->tddes[colidx];
1351
1352 /* allocate memory for array */
1353 if (((*array) = (XTEUINT4Array *)LALCalloc(1,sizeof(XTEUINT4Array))) == NULL) {
1354 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for array.\n",fn);
1356 }
1357 LogPrintf(LOG_DEBUG,"%s : allocated memory for array\n",fn);
1358
1359 /* allocate memory for array data (one for each channel) */
1360 if (((*array)->channeldata = (XTEUINT4Vector *)LALCalloc(tddes->nchannels,sizeof(XTEUINT4Vector))) == NULL) {
1361 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for array.\n",fn);
1363 }
1364 (*array)->nchannels = tddes->nchannels;
1365 LogPrintf(LOG_DEBUG,"%s : allocated memory for %d channels\n",fn,tddes->nchannels);
1366
1367 /* define number of elements to read in - this is the total number of expected data values */
1368 totallength = (INT8)(header->rowlength[colidx]*header->nrows*tddes->nchannels);
1369 LogPrintf(LOG_DEBUG,"%s : computed total number of expected data samples as %d\n",fn,totallength);
1370
1371 /* allocate mem for temporary data storage of data and data undefined flag */
1372 if ((tempdata = (UINT4 *)LALCalloc(totallength,sizeof(UINT4))) == NULL) {
1373 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for array data.\n",fn);
1375 }
1376 if ((tempundefined = (CHAR *)LALCalloc(totallength,sizeof(CHAR))) == NULL) {
1377 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for data quality flag.\n",fn);
1379 }
1380 LogPrintf(LOG_DEBUG,"%s : allocated memory for data (approx %.1f MB)\n",fn,totallength*2e-6);
1381
1382 /* read the complete column data set (all channels together) */
1383 if (fits_read_colnull(fptr,TINT,col,1,1,totallength,tempdata,tempundefined,&anynull,&status)) {
1384 fits_report_error(stderr,status);
1385 LogPrintf(LOG_CRITICAL,"%s : fits_read_colnull() failed to read col %d in science array data.\n",fn,col);
1387 }
1388
1389 /* loop over the channels and divide up the data accordingly */
1390 for (i=0;i<tddes->nchannels;i++) {
1391
1392 INT8 idx = 0;
1393 INT4 j;
1394
1395 /* store energy information */
1396 (*array)->channeldata[i].energy[0] = tddes->minenergy[i];
1397 (*array)->channeldata[i].energy[1] = tddes->maxenergy[i];
1398
1399 /* construct detector string from tddes info */
1400 for (j=0;j<NPCU;j++) {
1401 char temp[12];
1402 if (tddes->detectors[i][j]) {
1403 snprintf(temp,12,"%d",j);
1404 strcat((*array)->channeldata[i].detconfig,temp);
1405 }
1406 }
1407
1408 /* record the sampling time and rowlength for this channel */
1409 (*array)->channeldata[i].deltat = tddes->deltat;
1410 (*array)->channeldata[i].rowlength = header->rowlength[colidx];
1411
1412 /* define number of elements to read in - this is the total number of expected data values for this channel */
1413 (*array)->channeldata[i].length = (INT8)(tddes->nsamples*header->nrows);
1414 LogPrintf(LOG_DEBUG,"%s : channel %d number of expected data samples as %ld\n",fn,i,tddes->nsamples*header->nrows);
1415
1416 /* allocate mem for data and data undefined flag for the current channel */
1417 if (((*array)->channeldata[i].data = (UINT4 *)LALCalloc((*array)->channeldata[i].length,sizeof(UINT4))) == NULL) {
1418 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for array data.\n",fn);
1420 }
1421 if (((*array)->channeldata[i].undefined = (CHAR *)LALCalloc((*array)->channeldata[i].length,sizeof(CHAR))) == NULL) {
1422 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for data quality flag.\n",fn);
1424 }
1425 LogPrintf(LOG_DEBUG,"%s : allocated memory for data (approx %.1f MB)\n",fn,(*array)->channeldata[i].length*2e-6);
1426
1427 /* fill in the data - first loop over rows */
1428 for (j=0;j<header->nrows;j++) {
1429
1430 /* for each row extract the correct set of data for the current channel */
1431 INT8 sidx = (tddes->nchannels*j+i)*tddes->nsamples;
1432 INT8 k;
1433
1434 for (k=sidx;k<sidx+tddes->nsamples;k++) {
1435 (*array)->channeldata[i].data[idx] = tempdata[k];
1436 (*array)->channeldata[i].undefined[idx] = tempundefined[k];
1437 idx++;
1438 }
1439
1440 }
1441
1442 /* output debugging information */
1443 {
1444 int M = (*array)->channeldata[i].length > 10 ? 10 : (*array)->channeldata[i].length;
1445 LogPrintf(LOG_DEBUG,"%s : read array data as : ",fn);
1446 for (j=0;j<M;j++) {
1447 LogPrintf(LOG_DEBUG,"%d(%d),",(*array)->channeldata[i].data[j],(*array)->channeldata[i].undefined[j]);
1448 }
1449 LogPrintf(LOG_DEBUG,"...\n");
1450 }
1451
1452 }
1453
1454 /* free temporary mem */
1455 XLALFree(tempdata);
1456 XLALFree(tempundefined);
1457
1458 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
1459 return XLAL_SUCCESS;
1460
1461}
1462
1463/**
1464 * Reads in event mode data from a FITS file.
1465 * The information regarding each event is stored in groups of nbytes. The first char in each
1466 * group defined whether the event is real. We read in all information (real and non-real events).
1467 * We group all energies together her so we only have a single channel
1468 *
1469 */
1470int XLALReadFITSEventData(XTECHARArray **event, /**< [out] The FITSdata structure */
1471 fitsfile *fptr, /**< [in] a fitsfile file pointer */
1472 FITSHeader *header, /**< [in] the fits file header */
1473 INT4 colidx /**< [in] the column to be read */
1474 )
1475{
1476
1477 const CHAR *fn = __func__; /* store function name for log output */
1478 INT4 status = 0; /* fitsio status flag initialised */
1479 XTETDDESParams *tddes = NULL;
1480 INT4 col;
1481 INT4 j;
1482
1483 /* check input arguments */
1484 if ((*event) != NULL) {
1485 LogPrintf(LOG_CRITICAL,"%s: Invalid input, output XTECHARArray structure != NULL.\n",fn);
1487 }
1488 if (fptr == NULL) {
1489 LogPrintf(LOG_CRITICAL,"%s: Invalid input, input FITS file pointer = NULL.\n",fn);
1491 }
1492 if (header == NULL) {
1493 LogPrintf(LOG_CRITICAL,"%s: Invalid input, input FITS file header = NULL.\n",fn);
1495 }
1496 col = header->XeCntcolidx[colidx];
1497 if ((col < 1) || (col>header->ncols)) {
1498 LogPrintf(LOG_CRITICAL,"%s: Invalid input, column number must be > 0 and < number of columns in file (%ld).\n",fn,header->ncols);
1500 }
1501 LogPrintf(LOG_DEBUG,"%s : checked input\n",fn);
1502
1503 /* define temporary pointer to current tddes structure for clarity */
1504 tddes = header->tddes[colidx];
1505
1506 /* allocate memory for array */
1507 if (((*event) = (XTECHARArray *)LALCalloc(1,sizeof(XTECHARArray))) == NULL) {
1508 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for event data.\n",fn);
1510 }
1511 LogPrintf(LOG_DEBUG,"%s : allocated memory for array\n",fn);
1512
1513 /* allocate memory for array data (we enforce only one channel) */
1514 if (((*event)->channeldata = (XTECHARVector *)LALCalloc(1,sizeof(XTECHARVector))) == NULL) {
1515 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for events.\n",fn);
1517 }
1518 (*event)->nchannels = 1;
1519 LogPrintf(LOG_DEBUG,"%s : allocated memory for 1 channel (event mode)\n",fn);
1520
1521 /* store energy information (take the smallest and largest energy since we're grouping all the energies together) */
1522 (*event)->channeldata[0].energy[0] = tddes->minenergy[0];
1523 (*event)->channeldata[0].energy[1] = tddes->maxenergy[tddes->nchannels-1];
1524
1525 /* construct detector string from tddes info */
1526 for (j=0;j<NPCU;j++) {
1527 char temp[12];
1528 snprintf(temp,12,"%d",j);
1529 strcat((*event)->channeldata[0].detconfig,temp);
1530 }
1531
1532 /* record the sampling time and energy range for this column using the TDDES string data */
1533 (*event)->channeldata[0].deltat = tddes->deltat;
1534
1535 /* define number of elements to read in (each of size char) - this is the total number of expected data values */
1536 (*event)->channeldata[0].nevents = header->nrows;
1537 (*event)->channeldata[0].rowlength = header->rowlength[0];
1538 (*event)->channeldata[0].length = (INT8)(header->rowlength[0]*header->nrows);
1539 LogPrintf(LOG_DEBUG,"%s : preparing to read in %" LAL_INT8_FORMAT " events\n",fn,(*event)->channeldata[0].nevents);
1540 LogPrintf(LOG_DEBUG,"%s : this corresponds to %" LAL_INT8_FORMAT " CHARS\n",fn,(*event)->channeldata[0].length);
1541
1542 /* allocate mem for data and data undefined flag */
1543 if (((*event)->channeldata[0].data = (CHAR *)LALCalloc((*event)->channeldata[0].length,sizeof(CHAR))) == NULL ) {
1544 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for event data.\n",fn);
1546 }
1547 LogPrintf(LOG_DEBUG,"%s : allocated memory for %" LAL_INT8_FORMAT " CHARS\n",fn,(*event)->channeldata[0].length);
1548 LogPrintf(LOG_DEBUG,"%s : reading column %d\n",fn,col);
1549
1550 /* read the complete data set - we must remember that any event with the most significant bit = 0 is not a real event !! */
1551 /* IMPORTANT : we read in rowlength chars for each event and the first char in each row defines whether the event is real */
1552 if (fits_read_col_bit(fptr,col,1,1,(*event)->channeldata[0].length,(*event)->channeldata[0].data,&status)) {
1553 fits_report_error(stderr,status);
1554 LogPrintf(LOG_CRITICAL,"%s : fits_read_col_bit() failed to read in event data.\n",fn);
1556 }
1557 LogPrintf(LOG_DEBUG,"%s : read in %" LAL_INT8_FORMAT " events\n",fn,(*event)->channeldata[0].nevents);
1558 LogPrintf(LOG_DEBUG,"%s : read rowlength as %" LAL_INT8_FORMAT "\n",fn,(*event)->channeldata[0].rowlength);
1559
1560 /* output debugging information */
1561 {
1562 int i;
1563 int M = (*event)->channeldata[0].nevents > 100 ? 100 : (*event)->channeldata[0].nevents;
1564 LogPrintf(LOG_DEBUG,"%s : read array data as : ",fn);
1565 for (i=0;i<M;i++) {
1566 LogPrintf(LOG_DEBUG,"%d,",(*event)->channeldata[0].data[(*event)->channeldata[0].rowlength*i]);
1567 }
1568 LogPrintf(LOG_DEBUG,"\n");
1569 }
1570
1571 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
1572 return XLAL_SUCCESS;
1573
1574}
1575
1576/**
1577 * Extracts PCA config, energy range and sampling parameters from tddes2 DDL string.
1578 * It's not pretty but it does the job.
1579 */
1580int XLALConvertTDDES(XTETDDESParams **params, /**< [out] a null TDDES parameter structure */
1581 char *tddes /**< [in] a TDDES DDL string */
1582 )
1583{
1584
1585 /* the following is an example TDDES2 DDL string */
1586 /* 'D[0~4] & E[X1L^X1R^X2L^X2R^X3L^X3R] & C[0~7,8,9,10,11,12,13,14,15,16,17~18,19~21,22~25,26~29,30~35,36~49] & T[0.0;0.0078125;1024]' */
1587
1588 const CHAR *fn = __func__; /* store function name for log output */
1589
1590 char *Dstart,*Dend,*Estart,*Eend,*Tstart,*Tend;
1591 CHAR *Dstring,*Estring,*Tstring;
1592 INT4 Dlength,Elength,Tlength;
1593 CHAR *temp;
1594 CHAR *c2,*c1;
1595 INT4 Dcount = 0;
1596 INT4 Ecount = 0;
1597 INT4 Tcount = 0;
1598 CHAR *sub;
1599 INT4 sublen;
1600 INT4 i;
1601
1602 /* allocate memory for the output params */
1603 if (((*params) = (XTETDDESParams *)XLALCalloc(1,sizeof(XTETDDESParams))) == NULL) {
1604 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for an XTETDDESParams structure.\n",fn);
1606 }
1607
1608 /* initialise energy ranges (assume the max number of possible energy channels) */
1609 (*params)->deltat = 0.0;
1610 (*params)->nsamples = 0;
1611 (*params)->offset = 0.0;
1612
1613 /********************************************************************************************/
1614 /* Detector config */
1615
1616 /* find start of PCA section of string - exit if not found */
1617 if ((temp = strstr(tddes,"D["))==NULL) return XLAL_SUCCESS;
1618 Dstart = temp + 2;
1619
1620 /* find end of energy section of string - exit if not found */
1621 if ((Dend = strstr(Dstart,"]"))==NULL) return XLAL_SUCCESS;
1622 Dlength = strlen(Dstart) - strlen(Dend) + 1;
1623
1624 /* extract PCA config string (add a comma at the end to make it easier to distinguish configs) */
1625 Dstring = (CHAR *)XLALCalloc(Dlength+2,sizeof(CHAR));
1626 snprintf(Dstring,Dlength,"%s",Dstart);
1627 strcat(Dstring,",");
1628 LogPrintf(LOG_DEBUG,"%s : read detector DDL string as %s\n",fn,Dstring);
1629
1630 /* count each instance of the delimiter "," */
1631 c2 = Dstring;
1632 while ((c1 = strstr(c2,",")) != NULL) {
1633 c2 = c1+1;
1634 Dcount++;
1635 }
1636
1637 /*allocate memory */
1638 LogPrintf(LOG_DEBUG,"%s : read %d detector configs\n",fn,Dcount);
1639 (*params)->ndetconfig = Dcount;
1640 (*params)->detectors = (INT4 **)XLALCalloc((*params)->ndetconfig,sizeof(INT4 *));
1641 for (i=0;i<(*params)->ndetconfig;i++) (*params)->detectors[i] = (INT4 *)XLALCalloc(NPCU,sizeof(INT4));
1642
1643 /* loop over each instance of the delimiter "," */
1644 c2 = Dstring;
1645 Dcount = 0;
1646 while ((c1 = strstr(c2,",")) != NULL) {
1647
1648 /* copy string */
1649 CHAR *subs,*til;
1650 sublen = 1 + strcspn(c2,",");
1651 subs = (CHAR *)XLALCalloc(sublen+1,sizeof(CHAR));
1652 snprintf(subs,sublen,"%s",c2);
1653
1654 /* check if there is a "~" separating two energy values */
1655 if ((til = strstr(subs,"~")) != NULL) {
1656 CHAR *e1,*e2;
1657 INT4 e1len = 1 + strcspn(subs,"~");
1658 INT4 e2len = sublen - e1len;
1659 INT4 s,e,k;
1660 e1 = (CHAR *)XLALCalloc(e1len+1,sizeof(CHAR));
1661 e2 = (CHAR *)XLALCalloc(e2len+1,sizeof(CHAR));
1662 snprintf(e1,e1len,"%s",subs);
1663 snprintf(e2,e2len,"%s",til+1);
1664 s = atoi(e1);
1665 e = atoi(e2);
1666 for (k=s;k<=e;k++) (*params)->detectors[Dcount][k] = 1;
1667 XLALFree(e1);
1668 XLALFree(e2);
1669 }
1670 else {
1671
1672 /* check if there is are instances of 0,1,2,3,4,5 in the string */
1673 if (strstr(subs,"0") != NULL) (*params)->detectors[Dcount][0] = 1;
1674 if (strstr(subs,"1") != NULL) (*params)->detectors[Dcount][1] = 1;
1675 if (strstr(subs,"2") != NULL) (*params)->detectors[Dcount][2] = 1;
1676 if (strstr(subs,"3") != NULL) (*params)->detectors[Dcount][3] = 1;
1677 if (strstr(subs,"4") != NULL) (*params)->detectors[Dcount][4] = 1;
1678 }
1679
1680 LogPrintf(LOG_DEBUG,"%s : read detectors as [%d %d %d %d %d]\n",fn,(*params)->detectors[Dcount][0],
1681 (*params)->detectors[Dcount][1],(*params)->detectors[Dcount][2],
1682 (*params)->detectors[Dcount][3],(*params)->detectors[Dcount][4]);
1683 Dcount++;
1684 c2 = c1+1;
1685 XLALFree(subs);
1686
1687 }
1688
1689 XLALFree(Dstring);
1690
1691 /********************************************************************************************/
1692 /* ENERGY */
1693
1694 /* find start of energy section of string - exit if not found */
1695 if ((temp = strstr(tddes,"C["))==NULL) return XLAL_SUCCESS;
1696 Estart = temp + 2;
1697
1698 /* find end of energy section of string - exit if not found */
1699 if ((Eend = strstr(Estart,"]"))==NULL) return XLAL_SUCCESS;
1700 Elength = strlen(Estart) - strlen(Eend) + 1;
1701
1702 /* extract energy string (add a comma at the end to make it easier to distinguish energies) */
1703 Estring = (CHAR *)XLALCalloc(Elength+2,sizeof(CHAR));
1704 snprintf(Estring,Elength,"%s",Estart);
1705 strcat(Estring,",");
1706 LogPrintf(LOG_DEBUG,"%s : read energy DDL string as %s\n",fn,Estring);
1707
1708 /* count each instance of the delimiter "," */
1709 c2 = Estring;
1710 while ((c1 = strstr(c2,",")) != NULL) {
1711 c2 = c1+1;
1712 Ecount++;
1713 }
1714
1715 /*allocate memory */
1716 LogPrintf(LOG_DEBUG,"%s : read %d channels\n",fn,Ecount);
1717 (*params)->nenergy = Ecount;
1718 (*params)->minenergy = (INT4 *)XLALCalloc((*params)->nenergy,sizeof(INT4));
1719 (*params)->maxenergy = (INT4 *)XLALCalloc((*params)->nenergy,sizeof(INT4));
1720
1721 /* loop over each instance of the delimiter "," */
1722 c2 = Estring;
1723 Ecount = 0;
1724 while ((c1 = strstr(c2,",")) != NULL) {
1725
1726 /* copy string */
1727 CHAR *subs,*til;
1728 sublen = 1 + strcspn(c2,",");
1729 subs = (CHAR *)XLALCalloc(sublen+1,sizeof(CHAR));
1730 snprintf(subs,sublen,"%s",c2);
1731
1732 /* check if there is a "~" separating two energy values */
1733 if ((til = strstr(subs,"~")) != NULL) {
1734 CHAR *e1,*e2;
1735 INT4 e1len = 1 + strcspn(subs,"~");
1736 INT4 e2len = sublen - e1len;
1737 e1 = (CHAR *)XLALCalloc(e1len+1,sizeof(CHAR));
1738 e2 = (CHAR *)XLALCalloc(e2len+1,sizeof(CHAR));
1739 snprintf(e1,e1len,"%s",subs);
1740 snprintf(e2,e2len,"%s",til+1);
1741 (*params)->minenergy[Ecount] = atoi(e1);
1742 (*params)->maxenergy[Ecount] = atoi(e2);
1743 XLALFree(e1);
1744 XLALFree(e2);
1745 }
1746 else {
1747 (*params)->minenergy[Ecount] = atoi(subs);
1748 (*params)->maxenergy[Ecount] = atoi(subs);
1749 }
1750 LogPrintf(LOG_DEBUG,"%s : read energies as %d %d\n",fn,(*params)->minenergy[Ecount],(*params)->maxenergy[Ecount]);
1751 Ecount++;
1752 c2 = c1+1;
1753 XLALFree(subs);
1754
1755 }
1756
1757 XLALFree(Estring);
1758
1759 /********************************************************************************************/
1760 /* MAKE CHANNELS CONSISTENT */
1761
1762 /* right now we only really care about multiple energy channels OR multiple detector configs */
1763 /* NOT both together. So we now make both detectors and energies all have the same length equal */
1764 /* to the number of channels in total. */
1765
1766 /* record number of channels as the product of the number of energy channels and the number of detector configs */
1767 if (((*params)->nenergy == 1) || ((*params)->ndetconfig == 1)) {
1768 (*params)->nchannels = (*params)->nenergy*(*params)->ndetconfig;
1769 }
1770 else {
1771 LogPrintf(LOG_CRITICAL,"%s : read multiple energy AND detector configs from TDDES. Exiting.\n",fn);
1773 }
1774
1775 /* extend memory */
1776 if ((*params)->nenergy == 1) {
1777 (*params)->minenergy = (INT4 *)XLALRealloc((*params)->minenergy,(*params)->nchannels*sizeof(INT4));
1778 (*params)->maxenergy = (INT4 *)XLALRealloc((*params)->maxenergy,(*params)->nchannels*sizeof(INT4));
1779
1780 /* fill in */
1781 for (i=1;i<(*params)->nchannels;i++) {
1782 (*params)->minenergy[i] = (*params)->minenergy[0];
1783 (*params)->maxenergy[i] = (*params)->maxenergy[0];
1784 }
1785 }
1786
1787 if ((*params)->ndetconfig == 1) {
1788 (*params)->detectors = (INT4 **)XLALRealloc((*params)->detectors,(*params)->nchannels*sizeof(INT4 *));
1789 for (i=1;i<(*params)->nchannels;i++) (*params)->detectors[i] = (INT4 *)XLALCalloc(NPCU,sizeof(INT4));
1790
1791 /* fill in */
1792 for (i=1;i<(*params)->nchannels;i++) {
1793 INT4 j;
1794 for (j=0;j<NPCU;j++) (*params)->detectors[i][j] = (*params)->detectors[0][j];
1795 }
1796 }
1797
1798 /********************************************************************************************/
1799 /* TIMING */
1800
1801 /* find start of timing section of string - exit if not found */
1802 if ((temp = strstr(tddes,"T["))==NULL) return XLAL_SUCCESS;
1803 Tstart = temp + 2;
1804
1805 /* find end of timing section of string - exit if not found */
1806 if ((Tend = strstr(Tstart,"]"))==NULL) return XLAL_SUCCESS;
1807 Tlength = strlen(Tstart) - strlen(Tend) + 1;
1808
1809 /* extract energy string (add a comma at the end to make it easier to distinguish energies) */
1810 Tstring = (CHAR *)XLALCalloc(Tlength+2,sizeof(CHAR));
1811 snprintf(Tstring,Tlength,"%s",Tstart);
1812 strcat(Tstring,";");
1813 LogPrintf(LOG_DEBUG,"%s : read timing DDL string as %s\n",fn,Tstring);
1814
1815 /* count each instance of the delimiter ";" */
1816 c2 = Tstring;
1817 while ((c1 = strstr(c2,";")) != NULL) {
1818 c2 = c1+1;
1819 Tcount++;
1820 }
1821
1822 /* check consistency - the timing section should only have 3 entries */
1823 if (Tcount != 3) {
1824 LogPrintf(LOG_CRITICAL,"%s : read %d timing elements, should be 3 ! Exiting.\n",fn,Tcount);
1825 exit(0);
1826 }
1827
1828 /* extract offset */
1829 c2 = Tstring; /* point to time string */
1830 c1 = strstr(c2,";"); /* find location of delimiter */
1831 sublen = 1 + strcspn(c2,";"); /* length of required string (including terminator) */
1832 sub = (CHAR *)XLALCalloc(sublen+1,sizeof(CHAR)); /* allocate mem */
1833 snprintf(sub,sublen,"%s",c2); /* copy substring */
1834 (*params)->offset = atof(sub); /* cast substring to a float */
1835 XLALFree(sub); /* free mem */
1836
1837 /* extract deltat */
1838 c2 = c1+1; /* point to next char after previous delimiter */
1839 c1 = strstr(c2,";"); /* find location of delimiter */
1840 sublen = 1 + strcspn(c2,";"); /* length of required string (including terminator) */
1841 sub = (CHAR *)XLALCalloc(sublen+1,sizeof(CHAR)); /* allocate mem */
1842 snprintf(sub,sublen,"%s",c2); /* copy substring */
1843 (*params)->deltat = atof(sub); /* cast substring to a float */
1844 XLALFree(sub); /* free mem */
1845
1846 /* extract nsamples */
1847 c2 = c1+1; /* point to next char after previous delimiter */
1848 c1 = strstr(c2,";"); /* find location of delimiter */
1849 sublen = 1 + strcspn(c2,";"); /* length of required string (including terminator) */
1850 sub = (CHAR *)XLALCalloc(sublen+1,sizeof(CHAR)); /* allocate mem */
1851 snprintf(sub,sublen,"%s",c2); /* copy substring */
1852 (*params)->nsamples = atoi(sub); /* cast substring to an int */
1853 XLALFree(sub); /* free mem */
1854
1855 /* free mem */
1856 XLALFree(Tstring);
1857
1858 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
1859 return XLAL_SUCCESS;
1860
1861}
1862
1863/**
1864 * Converts a FITS event data file to a binned timeseries.
1865 *
1866 * This function acts as a wrapper for XLALEventDataToXTEUINT4TimeSeries which deals
1867 * with single timeseries. We enforce that each timeseries has the same start, end,
1868 * and sampling time for consistency.
1869 *
1870 */
1872 FITSData *fits, /**< in] a FITSHeader structure */
1873 REAL8 dt /**< [in] the desired sampling time */
1874 )
1875{
1876
1877 const CHAR *fn = __func__; /* store function name for log output */
1878 INT8 i,j; /* counters */
1879 REAL8 newdt = dt; /* the modified sampling time */
1880 INT4 count = 0;
1881 INT4 nts = 0; /* used to count the number of timeseries */
1882
1883 /* check input and output pointers */
1884 if ((*ts) != NULL) {
1885 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure has non-null pointer.\n",fn);
1887 }
1888 if (fits == NULL) {
1889 LogPrintf(LOG_CRITICAL,"%s : input FITSData structure has null pointer.\n",fn);
1891 }
1892 if (fits->header == NULL) {
1893 LogPrintf(LOG_CRITICAL,"%s : input FITSHeader structure has null pointer.\n",fn);
1895 }
1896
1897 /* check timeseries consistency */
1898 for (i=0;i<fits->header->nXeCntcol;i++) {
1899 for (j=0;j<fits->event[i]->nchannels;j++) {
1900 if ((fits->event[i]->channeldata[j].deltat != fits->event[0]->channeldata[j].deltat) || (fits->event[i]->channeldata[j].length != fits->event[0]->channeldata[j].length)) {
1901 LogPrintf(LOG_CRITICAL,"%s : inconsistent parameters between column timeseries.\n",fn);
1903 }
1904 }
1905 }
1906
1907 /* check that requested sampling rate is at least as large as the original rate */
1908 {
1909 INT4 n = (INT4)ceil(fits->event[0]->channeldata[0].deltat/dt);
1910 newdt = n*dt;
1911 LogPrintf(LOG_NORMAL,"%s : requested sampling time %6.12f -> %6.12f sec.\n",fn,dt,newdt);
1912 }
1913
1914 /* calculate the number of timeseries required (sum of all energy channels for all columns) */
1915 for (i=0;i<fits->header->nXeCntcol;i++) nts += fits->event[i]->nchannels;
1916
1917 /* allocate mem for output timeseries array */
1918 if (((*ts) = (XTEUINT4TimeSeriesArray *)LALCalloc(1,sizeof(XTEUINT4TimeSeriesArray))) == NULL) {
1919 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for XTEUINT4TimeSeriesArray.\n",fn);
1921 }
1922 if (((*ts)->ts = (XTEUINT4TimeSeries **)LALCalloc(nts,sizeof(XTEUINT4TimeSeries *))) == NULL) {
1923 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for XTEUINT4TimeSeries pointers.\n",fn);
1925 }
1926 LogPrintf(LOG_DEBUG,"%s : allocated memory for the timeseries.\n",fn);
1927
1928 /* loop over each relevant FITS data column */
1929 for (i=0;i<fits->header->nXeCntcol;i++) {
1930
1931 /* loop over each relevant FITS data column channel */
1932 for (j=0;j<fits->event[i]->nchannels;j++) {
1933
1934 if (XLALEventDataToXTEUINT4TimeSeries(&((*ts)->ts[count]),&(fits->event[i]->channeldata[j]),fits->stamps,newdt)) {
1935 LogPrintf(LOG_CRITICAL,"%s : XLALEventDataToXTEUINT4TimeSeries() failed with error = %d\n",fn,xlalErrno);
1937 }
1938 LogPrintf(LOG_DEBUG,"%s : Converted data from col %d and channel %" LAL_INT8_FORMAT " to a timeseries.\n",fn,fits->header->XeCntcolidx[i],j+1);
1939
1940 /* add column name info */
1941 snprintf((*ts)->ts[count]->colname,STRINGLENGTH,"%s",fits->header->colname[i]);
1942 count++;
1943
1944 }
1945
1946 }
1947
1948 /* update header info */
1949 strncpy((*ts)->objectname,fits->header->objectname,STRINGLENGTH);
1950 strncpy((*ts)->obsid,fits->header->obsid,STRINGLENGTH);
1951 strncpy((*ts)->apid,fits->header->apid,APIDLENGTH);
1952 strncpy((*ts)->mode,fits->header->mode,STRINGLENGTH);
1953 (*ts)->bary = 0;
1954 (*ts)->lld = fits->header->LLD;
1955 (*ts)->length = nts;
1956
1957 /* allocate mem for the header dump */
1958 if (((*ts)->headerdump = (CHAR *)XLALCalloc(1+strlen(fits->header->headerdump),sizeof(CHAR))) == NULL) {
1959 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for FITS header dump copy.\n",fn);
1961 }
1962 strcpy((*ts)->headerdump,fits->header->headerdump);
1963
1964 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
1965 return XLAL_SUCCESS;
1966
1967}
1968
1969/**
1970 * Converts a FITS event data file to a binned timeseries.
1971 * Using the detector timestamps data we convert the FITS data into a continuous binned timeseries.
1972 *
1973 */
1974int XLALEventDataToXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, /**< [out] a NULL timeseries */
1975 XTECHARVector *event, /**< [in] a FITSdata structure */
1976 BarycentricData *stamps, /**< [in] timestamps data */
1977 REAL8 dt /**< [in] the sampling time */
1978 )
1979{
1980
1981 const CHAR *fn = __func__; /* store function name for log output */
1982 INT8 i; /* counter */
1983
1984 /* check input and output pointers */
1985 if ((*ts) != NULL) {
1986 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure has non-null pointer.\n",fn);
1988 }
1989 if (event == NULL) {
1990 LogPrintf(LOG_CRITICAL,"%s : input XTECHARVector structure has null pointer.\n",fn);
1992 }
1993 if (stamps == NULL) {
1994 LogPrintf(LOG_CRITICAL,"%s : input BarycentricData structure has null pointer.\n",fn);
1996 }
1997
1998 /* compute number of samples in the continuous timeseries */
1999 /* define the time span in the detector frame from start of first bin to end of last bin */
2000 {
2001 REAL8 tstart = stamps->dettime[0];
2002 REAL8 tempspan = stamps->dettime[stamps->length-1] - tstart + stamps->dtrow;
2003 INT8 N = (INT8)(tempspan/dt);
2004
2005 /* allocate mem for output timeseries */
2007 LogPrintf(LOG_CRITICAL,"%s : XLALCreateXTEUINT4TimeSeries() failed with error = %d.\n",fn,xlalErrno);
2009 }
2010
2011 /* fill in the timeseries array params */
2012 (*ts)->tstart = tstart;
2013 (*ts)->T = dt*N;
2014 (*ts)->deltat = dt;
2015 (*ts)->energy[0] = event->energy[0];
2016 (*ts)->energy[1] = event->energy[1];
2017 snprintf((*ts)->detconfig,NPCU+1,"%s",event->detconfig);
2018 LogPrintf(LOG_DEBUG,"%s : new binned timeseries parameters :\n",fn);
2019 LogPrintf(LOG_DEBUG,"%s : tstart = %6.12f\n",fn,(*ts)->tstart);
2020 LogPrintf(LOG_DEBUG,"%s : T = %f\n",fn,(*ts)->T);
2021 LogPrintf(LOG_DEBUG,"%s : dt = %e\n",fn,(*ts)->deltat);
2022 LogPrintf(LOG_DEBUG,"%s : length = %" LAL_INT8_FORMAT "\n",fn,(*ts)->length);
2023 LogPrintf(LOG_DEBUG,"%s : energy = %d - %d\n",fn,(*ts)->energy[0],(*ts)->energy[1]);
2024 LogPrintf(LOG_DEBUG,"%s : detconfig = %s\n",fn,(*ts)->detconfig);
2025 }
2026
2027 /* initialise undefined as zero - for event data all times are good except for those defined by the GTI table */
2028 /* time marker events are not real events and are not counted anyway so we treat those times as good */
2029 for (i=0;i<(*ts)->length;i++) (*ts)->undefined[i] = 0;
2030
2031 /* loop over each event and bin it if its not a time marker */
2032 for (i=0;i<event->nevents;i++) {
2033
2034 /* set counter tracking 1st bit for each event */
2035 long int k = i*event->rowlength;
2036
2037 /* define bin index corresponding to this event time with reference to the timestamp of the first event */
2038 long int idx = (long int)floor((stamps->dettime[i]-stamps->dettime[0])/(*ts)->deltat);
2039
2040 /* only add to bin if event was NOT a time marker */
2041 (*ts)->data[idx] += (unsigned char)event->data[k];
2042
2043 }
2044
2045 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2046 return XLAL_SUCCESS;
2047
2048}
2049
2050/**
2051 * Converts a FITS array data file to a binned timeseries.
2052 * This function acts as a wrapper for XLALArrayDataToXTEUINT4TimeSeries which deals
2053 * with single timeseries. We enforce that each timeseries has the same start, end,
2054 * and sampling time for consistency.
2055 *
2056 */
2058 FITSData *fits, /**< in] a FITSHeader structure */
2059 REAL8 dt /**< [in] the desired sampling time */
2060 )
2061{
2062
2063 const CHAR *fn = __func__; /* store function name for log output */
2064 INT8 i,j; /* counter */
2065 REAL8 newdt = dt; /* modified sampling time */
2066 INT4 count = 0;
2067 INT4 nts = 0; /* used to count the number of timeseries */
2068
2069 /* check input and output pointers */
2070 if ((*ts) != NULL) {
2071 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure has non-null pointer.\n",fn);
2073 }
2074 if (fits == NULL) {
2075 LogPrintf(LOG_CRITICAL,"%s : input FITSData structure has null pointer.\n",fn);
2077 }
2078 if (fits->header == NULL) {
2079 LogPrintf(LOG_CRITICAL,"%s : input FITSHeader structure has null pointer.\n",fn);
2081 }
2082
2083 /* check timeseries consistency */
2084 for (i=0;i<fits->header->nXeCntcol;i++) {
2085 for (j=0;j<fits->array[i]->nchannels;j++) {
2086 if ((fits->array[i]->channeldata[j].deltat != fits->array[0]->channeldata[j].deltat) || (fits->array[i]->channeldata[j].length != fits->array[0]->channeldata[j].length)) {
2087 LogPrintf(LOG_CRITICAL,"%s : inconsistent parameters between column timeseries.\n",fn);
2089 }
2090 }
2091 }
2092
2093 /* check that requested sampling rate is at least as large as the original rate */
2094 {
2095 INT4 n = (INT4)ceil(fits->array[0]->channeldata[0].deltat/dt);
2096 newdt = n*dt;
2097 LogPrintf(LOG_NORMAL,"%s : requested sampling time %6.12f -> %6.12f sec.\n",fn,dt,newdt);
2098 }
2099
2100 /* calculate the number of timeseries required (sum of all energy channels for all columns) */
2101 for (i=0;i<fits->header->nXeCntcol;i++) nts += fits->array[i]->nchannels;
2102 LogPrintf(LOG_NORMAL,"%s : calculated that we have %d seperate timeseries.\n",fn,nts);
2103
2104 /* allocate mem for output timeseries array */
2105 if (((*ts) = (XTEUINT4TimeSeriesArray *)LALCalloc(1,sizeof(XTEUINT4TimeSeriesArray))) == NULL) {
2106 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for XTEUINT4TimeSeriesArray.\n",fn);
2108 }
2109 if (((*ts)->ts = (XTEUINT4TimeSeries **)LALCalloc(nts,sizeof(XTEUINT4TimeSeries *))) == NULL) {
2110 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for XTEUINT4TimeSeries pointers.\n",fn);
2112 }
2113 LogPrintf(LOG_DEBUG,"%s : allocated memory for %d timeseries.\n",fn,nts);
2114
2115 /* loop over each relevant FITS data column */
2116 for (i=0;i<fits->header->nXeCntcol;i++) {
2117
2118 /* loop over each relevant FITS data column channel */
2119 for (j=0;j<fits->array[i]->nchannels;j++) {
2120
2121 if (XLALArrayDataToXTEUINT4TimeSeries(&((*ts)->ts[count]),&(fits->array[i]->channeldata[j]),fits->stamps,newdt)) {
2122 LogPrintf(LOG_CRITICAL,"%s : XLALArrayDataToXTEUINT4TimeSeries() failed with error = %d\n",fn,xlalErrno);
2124 }
2125 LogPrintf(LOG_DEBUG,"%s : Converted data from col %d and channel %" LAL_INT8_FORMAT " to a timeseries.\n",fn,fits->header->XeCntcolidx[i],j+1);
2126
2127 /* add column name info */
2128 snprintf((*ts)->ts[count]->colname,STRINGLENGTH,"%s",fits->header->colname[i]);
2129 count++;
2130
2131 }
2132
2133 }
2134
2135 /* update header info */
2136 strncpy((*ts)->objectname,fits->header->objectname,STRINGLENGTH);
2137 strncpy((*ts)->obsid,fits->header->obsid,STRINGLENGTH);
2138 strncpy((*ts)->mode,fits->header->mode,STRINGLENGTH);
2139 strncpy((*ts)->apid,fits->header->apid,APIDLENGTH);
2140 (*ts)->bary = 0;
2141 (*ts)->lld = fits->header->LLD;
2142 (*ts)->length = nts;
2143
2144 /* allocate mem for the header dump */
2145 if (((*ts)->headerdump = (CHAR *)XLALCalloc(1+strlen(fits->header->headerdump),sizeof(CHAR))) == NULL) {
2146 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for FITS header dump copy.\n",fn);
2148 }
2149 strcpy((*ts)->headerdump,fits->header->headerdump);
2150
2151 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2152 return XLAL_SUCCESS;
2153
2154}
2155
2156/**
2157 * Converts a FITS file data structure containing science array (binned) data into a timeseries.
2158 * Using the detector timestamps data we convert the FITS data into a continuous binned timeseries.
2159 *
2160 */
2161int XLALArrayDataToXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, /**< [out] a null timeseries */
2162 XTEUINT4Vector *array, /**< [in] a FITSdata structure */
2163 BarycentricData *stamps, /**< [in] timestamps data */
2164 REAL8 dt /**< [in] the sampling time */
2165 )
2166{
2167
2168 const CHAR *fn = __func__; /* store function name for log output */
2169 INT4 i,j; /* counters */
2170 INT2 *temp_undefined = NULL; /* temporary data quality vector */
2171
2172 /* check input and output pointers */
2173 if ((*ts) != NULL) {
2174 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure has non-null pointer.\n",fn);
2176 }
2177 if (array == NULL) {
2178 LogPrintf(LOG_CRITICAL,"%s : input FITSdata structure has null pointer.\n",fn);
2180 }
2181 if (stamps == NULL) {
2182 LogPrintf(LOG_CRITICAL,"%s : input FITSHeader structure has null pointer.\n",fn);
2184 }
2185
2186 /* compute number of samples in the continuous timeseries */
2187 /* define the time span in the detector frame from start of first bin to end of last bin */
2188 {
2189 REAL8 tstart = stamps->dettime[0];
2190 REAL8 tempspan = stamps->dettime[stamps->length-1] - tstart + stamps->dtrow;
2191 INT8 N = (INT8)(tempspan/dt);
2192
2193 /* allocate mem for output timeseries */
2195 LogPrintf(LOG_CRITICAL,"%s : XLALCreateXTEUINT4TimeSeries() failed with error = %d.\n",fn,xlalErrno);
2197 }
2198
2199 /* fill in params */
2200 (*ts)->tstart = tstart;
2201 (*ts)->T = dt*N;
2202 (*ts)->deltat = dt;
2203 (*ts)->energy[0] = array->energy[0];
2204 (*ts)->energy[1] = array->energy[1];
2205 snprintf((*ts)->detconfig,NPCU+1,"%s",array->detconfig);
2206 LogPrintf(LOG_DEBUG,"%s : new binned timeseries parameters :\n",fn);
2207 LogPrintf(LOG_DEBUG,"%s : tstart = %6.12f\n",fn,(*ts)->tstart);
2208 LogPrintf(LOG_DEBUG,"%s : T = %f\n",fn,(*ts)->T);
2209 LogPrintf(LOG_DEBUG,"%s : dt = %e\n",fn,(*ts)->deltat);
2210 LogPrintf(LOG_DEBUG,"%s : length = %" LAL_INT8_FORMAT "\n",fn,(*ts)->length);
2211 LogPrintf(LOG_DEBUG,"%s : energy = %d - %d\n",fn,(*ts)->energy[0],(*ts)->energy[1]);
2212 LogPrintf(LOG_DEBUG,"%s : detconfig = %s\n",fn,(*ts)->detconfig);
2213 }
2214
2215 /* allocate memory for a temporary data quality vector */
2216 if ((temp_undefined = (short int *)LALCalloc((*ts)->length,sizeof(short int))) == NULL) {
2217 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for temporary data quality vector.\n",fn);
2219 }
2220 LogPrintf(LOG_DEBUG,"%s : allocated %" LAL_INT8_FORMAT " short ints for temp_undefined\n",fn,(*ts)->length);
2221
2222 /* initialise as zero and all undefined - therefore all gaps will be automatically undefined */
2223 for (i=0;i<(*ts)->length;i++) {
2224 (*ts)->data[i] = 0;
2225 (*ts)->undefined[i] = 1;
2226 temp_undefined[i] = 0;
2227 }
2228 LogPrintf(LOG_DEBUG,"%s : initialised output\n",fn);
2229
2230 /* loop over each timestamp and fill in timeseries */
2231 /* remember that times are in reference to bin edges */
2232 for (i=0;i<stamps->length;i++) {
2233
2234 /* loop over data within timestamp span */
2235 for (j=0;j<array->rowlength;j++) {
2236
2237 /* the index in the fits data in the j'th element in the i'th row */
2238 long int idxin = i*array->rowlength + j;
2239
2240 /* the index in the output timeseries of the fits data in the j'th element in the i'th row */
2241 long int idxout = floor((stamps->dettime[i] - stamps->dettime[0] + j*array->deltat)/(*ts)->deltat);
2242
2243 if ((idxin>=array->length) || (idxout>=(*ts)->length)) printf("idxin = %ld (%ld) idxout = %ld (%ld)\n",idxin,(long int)array->length,idxout,(long int)(*ts)->length);
2244
2245 /* add corresponding data to correct time output bin */
2246 (*ts)->data[idxout] += array->data[idxin];
2247 temp_undefined[idxout] += array->undefined[idxin];
2248
2249 }
2250
2251 }
2252
2253 /* make sure the undefined flags are either 0 or 1 - if greater than 1 then set to 1 */
2254 for (i=0;i<(*ts)->length;i++) {
2255 if (temp_undefined[i] > 1) (*ts)->undefined[i] = 1;
2256 else (*ts)->undefined[i] = 0;
2257 }
2258
2259 /* free memory */
2260 XLALFree(temp_undefined);
2261
2262 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2263 return XLAL_SUCCESS;
2264
2265}
2266
2267/**
2268 * Allocates memory for a XTEUINT4TimeSeries.
2269 */
2270int XLALCreateXTEUINT4TimeSeries(XTEUINT4TimeSeries **x, /**< [out] a null timeseries */
2271 INT8 N /**< [in] the desired number of elements in the timeseries */
2272 )
2273{
2274
2275 const char *fn = __func__; /* store function name for log output */
2276
2277 /* check input */
2278 if (N<1) {
2279 LogPrintf(LOG_CRITICAL,"%s : tried to allocate an XTEUINT4TimeSeries with non-positive size.\n",fn);
2281 }
2282 if ((*x) != NULL) {
2283 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure does not have null pointer.\n",fn);
2285 }
2286
2287 if (((*x) = (XTEUINT4TimeSeries *)LALCalloc(1,sizeof(XTEUINT4TimeSeries))) == NULL) {
2288 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for an XTEUINT4TimeSeries structure.\n",fn);
2290 }
2291 (*x)->length = N;
2292 if (((*x)->data = (UINT4 *)LALCalloc(N,sizeof(UINT4))) == NULL) {
2293 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for an XTEUINT4TimeSeries data vector.\n",fn);
2295 }
2296 if (((*x)->undefined = (char *)LALCalloc(N,sizeof(char))) == NULL) {
2297 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for an XTEUINT4TimeSeries data quality vector.\n",fn);
2299 }
2300
2301 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2302 return XLAL_SUCCESS;
2303
2304}
2305
2306/**
2307 * Frees a FITS data structure.
2308 */
2309int XLALFreeFITSData(FITSData *x /**< [in/out] a FITS data structure */
2310 )
2311{
2312
2313 const char *fn = __func__; /* store function name for log output */
2314 INT4 i,j;
2315
2316 /* check input */
2317 if (x == NULL) {
2318 LogPrintf(LOG_CRITICAL,"%s : input FITSdata structure has null pointer.\n",fn);
2320 }
2321
2322 if (x->event != NULL) {
2323 for (i=0;i<x->header->nXeCntcol;i++) {
2324 if (x->event[i] != NULL) {
2325 for (j=0;j<x->event[i]->nchannels;j++) {
2326 if (x->event[i]->channeldata[j].data != NULL) XLALFree(x->event[i]->channeldata[j].data);
2327 if (x->event[i]->channeldata[j].undefined != NULL) XLALFree(x->event[i]->channeldata[j].undefined);
2328 }
2329 XLALFree(x->event[i]->channeldata);
2330 XLALFree(x->event[i]);
2331 }
2332 }
2333 XLALFree(x->event);
2334 }
2335 LogPrintf(LOG_DEBUG,"%s : freed event data from FITS data structure\n",fn);
2336 if (x->array != NULL) {
2337 for (i=0;i<x->header->nXeCntcol;i++) {
2338 if (x->array[i] != NULL) {
2339 for (j=0;j<x->array[i]->nchannels;j++) {
2340 if (x->array[i]->channeldata[j].data != NULL) XLALFree(x->array[i]->channeldata[j].data);
2341 if (x->array[i]->channeldata[j].undefined != NULL) XLALFree(x->array[i]->channeldata[j].undefined);
2342 }
2343 XLALFree(x->array[i]->channeldata);
2344 XLALFree(x->array[i]);
2345 }
2346 }
2347 XLALFree(x->array);
2348 }
2349 LogPrintf(LOG_DEBUG,"%s : freed array data from FITS data structure\n",fn);
2350 if (x->header != NULL) {
2351 XLALFree(x->header->XeCntcolidx);
2352 for (i=0;i<x->header->nXeCntcol;i++) {
2353 XLALFree(x->header->colname[i]);
2354 XLALFree(x->header->tddes[i]->minenergy);
2355 XLALFree(x->header->tddes[i]->maxenergy);
2356 for (j=0;j<x->header->tddes[i]->nchannels;j++) XLALFree(x->header->tddes[i]->detectors[j]);
2357 XLALFree(x->header->tddes[i]->detectors);
2358 XLALFree(x->header->tddes[i]);
2359 }
2360 XLALFree(x->header->rowlength);
2361 XLALFree(x->header->tddes);
2362 XLALFree(x->header->colname);
2363 XLALFree(x->header->headerdump);
2364 XLALFree(x->header);
2365 }
2366 LogPrintf(LOG_DEBUG,"%s : freed header info from FITS data structure\n",fn);
2367 if (x->gti != NULL) {
2368 if (XLALFreeGTIData(x->gti)) {
2369 LogPrintf(LOG_CRITICAL,"%s : unable to free GTI data with error = %d\n",fn,xlalErrno);
2371 }
2372 }
2373 LogPrintf(LOG_DEBUG,"%s : freed GTI data from FITS data structure\n",fn);
2374 if (x->stamps != NULL) {
2375 if (XLALFreeBarycentricData(x->stamps)) {
2376 LogPrintf(LOG_CRITICAL,"%s : unable to free barycentric data with error = %d\n",fn,xlalErrno);
2378 }
2379
2380 }
2381 LogPrintf(LOG_DEBUG,"%s : freed timestamps data from FITS data structure\n",fn);
2382 XLALFree(x);
2383
2384 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2385 return XLAL_SUCCESS;
2386
2387}
2388
2389/**
2390 * Frees an XTEUINT4TimeSeriesArray data structure.
2391 */
2393 )
2394{
2395
2396 const char *fn = __func__; /* store function name for log output */
2397 INT4 i; /* counter */
2398
2399 /* check input */
2400 if (ts == NULL) {
2401 LogPrintf(LOG_CRITICAL,"%s : input timeseries array has null pointer.\n",fn);
2403 }
2404
2405 if (ts->ts != NULL) {
2406 for (i=0;i<ts->length;i++) {
2407 if (ts->ts[i] != NULL) {
2408
2409 if (XLALFreeXTEUINT4TimeSeries(ts->ts[i])) {
2410 LogPrintf(LOG_CRITICAL,"%s : unable to free array data timeseries with error = %d\n",fn,xlalErrno);
2412 }
2413
2414 }
2415 }
2416 XLALFree(ts->ts);
2417 }
2418 XLALFree(ts->headerdump);
2419 XLALFree(ts->comment);
2420 XLALFree(ts);
2421
2422 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2423 return XLAL_SUCCESS;
2424
2425}
2426
2427/**
2428 * Frees an XTEUINT4TimeSeries data structure.
2429 */
2430int XLALFreeXTEUINT4TimeSeries(XTEUINT4TimeSeries *ts /**< [in/out] a timeseries */
2431 )
2432{
2433
2434 const char *fn = __func__; /* store function name for log output */
2435
2436 /* check input */
2437 if (ts == NULL) {
2438 LogPrintf(LOG_CRITICAL,"%s : input timeseries vector has null pointer.\n",fn);
2440 }
2441
2442 if (ts->data != NULL) XLALFree(ts->data);
2443 if (ts->undefined != NULL) XLALFree(ts->undefined);
2444 XLALFree(ts);
2445
2446 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2447 return XLAL_SUCCESS;
2448
2449}
2450
2451/**
2452 * Sets timeseries array samples NOT in the GTI table as undefined and zeros the corresponding data.
2453 * This is a wrapper for XLALApplyGTIToXTEUINT4TimeSeries.
2454 *
2455 */
2457 GTIData *gti /**< [in] a GTIdata structure containing GTI information */
2458 )
2459{
2460
2461 const CHAR *fn = __func__; /* store function name for log output */
2462 INT4 i;
2463
2464 /* check input and output pointers */
2465 if ((*ts) == NULL) {
2466 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure has a null pointer.\n",fn);
2468 }
2469 if (gti == NULL) {
2470 LogPrintf(LOG_CRITICAL,"%s : input GTIData structure has null pointer.\n",fn);
2472 }
2473
2474 /* loop over each relavent column */
2475 for (i=0;i<(*ts)->length;i++) {
2476
2477 if (XLALApplyGTIToXTEUINT4TimeSeries(&((*ts)->ts[i]),gti)) {
2478 LogPrintf(LOG_CRITICAL,"%s : XLALApplyGTIToXTEUINT4TimeSeries() failed with error = %d\n",fn,xlalErrno);
2480 }
2481 LogPrintf(LOG_DEBUG,"%s : applied GTI table to data from column (%d/%d).\n",fn,i+1,(*ts)->length);
2482 }
2483
2484 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2485 return XLAL_SUCCESS;
2486
2487}
2488
2489/**
2490 * Sets timeseries samples NOT in the GTI table as undefined and zeros the corresponding data.
2491 */
2492int XLALApplyGTIToXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, /**< [in/out] the timeseries */
2493 GTIData *gti /**< [in] a GTIData structure containing GTI information */
2494 )
2495{
2496
2497 const char *fn = __func__; /* store function name for log output */
2498 INT4 i,k;
2499 INT8 newstartindex,newendindex,newN;
2500 GTIData *bti = NULL;
2501
2502 /* check input */
2503 if ((*ts) == NULL) {
2504 LogPrintf(LOG_CRITICAL,"%s : input timeseries vector has null pointer.\n",fn);
2506 }
2507 if (gti == NULL) {
2508 LogPrintf(LOG_CRITICAL,"%s : input GTIData structure has null pointer.\n",fn);
2510 }
2511
2512 /* allocate memory for bad time intervals BTIs - more useful than good time intervals for vetoing data */
2513 if (XLALCreateGTIData(&bti,gti->length+1)) {
2514 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for GTI start time data with error = %d.\n",fn,xlalErrno);
2516 }
2517
2518 /* compute first BTI from the timeseries start to the first GTI */
2519 bti->start[0] = (*ts)->tstart;
2520 bti->end[0] = gti->start[0];
2521 if (bti->end[0]<bti->start[0]) bti->start[0] = bti->end[0]; /* from rebinning the new start can be after the first gti start point */
2522
2523 /* compute BTI (bad time interval) - inbetween gti times */
2524 for (i=1;i<gti->length;i++) {
2525 bti->start[i] = gti->end[i-1];
2526 bti->end[i] = gti->start[i];
2527 }
2528
2529 /* compute last BTI from the last GTI to the timeseries end */
2530 bti->start[bti->length-1] = gti->end[gti->length-1];
2531 bti->end[gti->length] = (*ts)->tstart + (*ts)->T;
2532 if (bti->start[bti->length-1]>bti->end[bti->length-1]) bti->start[bti->length-1] = bti->end[bti->length-1]; /* from rebinning the new end can be before the last gti end point */
2533 for (i=0;i<bti->length;i++) LogPrintf(LOG_DEBUG,"%s : computed BTI : %f -> %f\n",fn,bti->start[i],bti->end[i]);
2534
2535 /* loop over each GTI gap */
2536 for (i=0;i<bti->length;i++) {
2537
2538 /* define start and end indices for this BTI - make sure that indices are within valid bounds */
2539 long int sindex = (bti->start[i] - (*ts)->tstart)/(*ts)->deltat;
2540 long int eindex = (bti->end[i] - (*ts)->tstart)/(*ts)->deltat;
2541 if (sindex<0) sindex = 0;
2542 if (eindex>(*ts)->length) eindex = (*ts)->length;
2543
2544 /* loop over the data between GTIs and set as undefined and zero the data */
2545 for (k=sindex;k<eindex;k++) {
2546 (*ts)->undefined[k]=1;
2547 (*ts)->data[k] = 0;
2548 }
2549
2550 }
2551 LogPrintf(LOG_DEBUG,"%s : zeroed and undefined non-GTI data in timeseries.\n",fn);
2552
2553 /* cut out start and end data */
2554 newstartindex = (bti->end[0]-(*ts)->tstart)/(*ts)->deltat;
2555 newendindex = (bti->start[bti->length-1]-(*ts)->tstart)/(*ts)->deltat;
2556 newN = newendindex - newstartindex;
2557 LogPrintf(LOG_DEBUG,"%s : computed new timeseries span as %" LAL_INT8_FORMAT " samples.\n",fn,newN);
2558
2559 /* if the new start index is moved then slide all of the data */
2560 if (newstartindex>0) {
2561 long int count = 0;
2562 for (i=newstartindex;i<newendindex;i++) {
2563 (*ts)->data[count] = (*ts)->data[i];
2564 (*ts)->undefined[count] = (*ts)->undefined[i];
2565 count++;
2566 }
2567 }
2568
2569 /* resize timeseries vector */
2570 if (newN > 0) {
2572 LogPrintf(LOG_CRITICAL,"%s : failed to resize memory for XTEUINT4TimeSeries.\n",fn);
2574 }
2575 }
2576 else {
2577 XLALFree((*ts)->data);
2578 (*ts)->data = NULL;
2579 }
2580
2581 /* update timeseries params */
2582 (*ts)->length = newN;
2583 (*ts)->T = newN*(*ts)->deltat;
2584 (*ts)->tstart += newstartindex*(*ts)->deltat;
2585 LogPrintf(LOG_DEBUG,"%s : changed start time and duration to %f and %f.\n",fn,(*ts)->tstart,(*ts)->T);
2586
2587 /* free the bad time interval data */
2588 if (XLALFreeGTIData(bti)) {
2589 LogPrintf(LOG_CRITICAL,"%s : failed to free memory for GTIData with error = %d.\n",fn,xlalErrno);
2591 }
2592 LogPrintf(LOG_DEBUG,"%s : freed the bad time interval data.\n",fn);
2593
2594 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2595 return XLAL_SUCCESS;
2596
2597}
2598
2599/**
2600 * Resizes an XTEUINT4TimeSeries data structure.
2601 */
2602int XLALReallocXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, /**< [in/out] the timeseries */
2603 INT8 N /**< [in] the new length */
2604 )
2605{
2606 const char *fn = __func__; /* store function name for log output */
2607
2608 /* check input */
2609 if (N<1) {
2610 LogPrintf(LOG_CRITICAL,"%s : tried to resize an XTEUINT4TimeSeries with non-positive size.\n",fn);
2612 }
2613
2614 if (((*ts)->data = (UINT4 *)LALRealloc((*ts)->data,N*sizeof(UINT4))) == NULL) {
2615 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for an XTEUINT4TimeSeries data vector.\n",fn);
2617 }
2618 if (((*ts)->undefined = (CHAR *)LALRealloc((*ts)->undefined,N*sizeof(CHAR))) == NULL) {
2619 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for an XTEUINT4TimeSeries undefined vector.\n",fn);
2621 }
2622 (*ts)->length = N;
2623
2624 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2625 return XLAL_SUCCESS;
2626
2627}
2628
2629/**
2630 * Reduces the number of barycentric timestamps from a FITS data structure.
2631 * We do this because we don't need fast sampling in time to perform accurate barycentering. For event data
2632 * there will be a timestamp for every event which means a lot of timestamps. Here we reduce the number to
2633 * one timestamp per TIMESTAMPDELTAT seconds.
2634 *
2635 */
2636int XLALReduceBarycentricData(BarycentricData **stamps /**< [in/out] barycentered null timestamps vector */
2637 )
2638{
2639
2640 const CHAR *fn = __func__; /* store function name for log output */
2641 INT8 i; /* counter */
2642 INT4 m = 1; /* another count */
2643 REAL8 thresh = 0.0;
2644
2645 /* check input */
2646 if ((*stamps) == NULL) {
2647 LogPrintf(LOG_CRITICAL,"%s : input timestamps vector has null pointer.\n",fn);
2649 }
2650
2651 /* initialise the first timestamp threshold */
2652 thresh = (*stamps)->dettime[0] + TIMESTAMPDELTAT;
2653
2654 /* loop over each timestamp and record a timestamp every time the timestamp step threshold is passed */
2655 /* start at index 1 so that we keep the first timestamp */
2656 for (i=1;i<(*stamps)->length;i++) {
2657
2658 /* if we've crossed the threshold then record timestamps */
2659 if ((*stamps)->dettime[i]>thresh) {
2660
2661 INT4 n = ceil(((*stamps)->dettime[i] - (*stamps)->dettime[0])/TIMESTAMPDELTAT);
2662 thresh = (*stamps)->dettime[0] + n*TIMESTAMPDELTAT;
2663 (*stamps)->dettime[m] = (*stamps)->dettime[i];
2664 (*stamps)->barytime[m] = (*stamps)->barytime[i];
2665 m++;
2666 }
2667
2668 }
2669
2670 /* if last timestamp is different to original last timestamp then record last timestamp and new size of vector */
2671 if ((*stamps)->dettime[m-1]<(*stamps)->dettime[(*stamps)->length-1]) {
2672 (*stamps)->dettime[m] = (*stamps)->dettime[(*stamps)->length-1];
2673 (*stamps)->barytime[m] = (*stamps)->barytime[(*stamps)->length-1];
2674 m++;
2675 }
2676 (*stamps)->length = m;
2677 LogPrintf(LOG_DEBUG,"%s : reduced timestamps vector size to %" LAL_INT8_FORMAT ".\n",fn,(*stamps)->length);
2678
2679 /* resize stamps vectors */
2680 if (((*stamps)->dettime = (double *)LALRealloc((*stamps)->dettime,(*stamps)->length*sizeof(double))) == NULL) {
2681 LogPrintf(LOG_CRITICAL,"%s : failed to resize memory for detector frame timestamps.\n",fn);
2683 }
2684 if (((*stamps)->barytime = (double *)LALRealloc((*stamps)->barytime,(*stamps)->length*sizeof(double))) == NULL) {
2685 LogPrintf(LOG_CRITICAL,"%s : failed to resize memory for barycentric frame timestamps.\n",fn);
2687 }
2688
2689 /* output debugging information */
2690 {
2691 int M = (*stamps)->length > 5 ? 5 : (*stamps)->length;
2692 LogPrintf(LOG_DEBUG,"%s : extracted timestamps as :\n",fn);
2693 for (i=0;i<M;i++) LogPrintf(LOG_DEBUG,"%s : %6.12f (%6.12f)\n",
2694 fn,(*stamps)->dettime[i],(*stamps)->barytime[i]);
2695 }
2696
2697 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2698 return XLAL_SUCCESS;
2699
2700}
2701
2702/**
2703 * Allocates memory for a GTI structure.
2704 */
2705int XLALCreateGTIData(GTIData **gti, /**< [out] a null timeseries */
2706 INT8 N /**< [in] the desired number of elements in the timeseries */
2707 )
2708{
2709
2710 const char *fn = __func__; /* store function name for log output */
2711
2712 /* check input */
2713 if (N<1) {
2714 LogPrintf(LOG_CRITICAL,"%s : tried to allocate GTI data with non-positive size.\n",fn);
2716 }
2717 if ((*gti) != NULL) {
2718 LogPrintf(LOG_CRITICAL,"%s : input timestamps structure does not have null pointer.\n",fn);
2720 }
2721
2722 if (((*gti) = (GTIData *)LALCalloc(1,sizeof(GTIData))) == NULL) {
2723 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for GTI structure.\n",fn);
2725 }
2726 if (((*gti)->start = (double *)LALCalloc(N,sizeof(double))) == NULL) {
2727 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for GTI start vector.\n",fn);
2729 }
2730 if (((*gti)->end = (double *)LALCalloc(N,sizeof(double))) == NULL) {
2731 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for GTI end vector.\n",fn);
2733 }
2734 (*gti)->length = N;
2735
2736 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2737 return XLAL_SUCCESS;
2738
2739}
2740
2741/**
2742 * Frees memory for a GTI structure.
2743 */
2744int XLALFreeGTIData(GTIData *gti /**< [out] a null timeseries */
2745 )
2746{
2747
2748 const char *fn = __func__; /* store function name for log output */
2749
2750 /* check input */
2751 if (gti == NULL) {
2752 LogPrintf(LOG_CRITICAL,"%s : input GTI structure has null pointer.\n",fn);
2754 }
2755
2756 if (gti->start != NULL) XLALFree(gti->start);
2757 if (gti->end != NULL) XLALFree(gti->end);
2758 XLALFree(gti);
2759
2760 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2761 return XLAL_SUCCESS;
2762
2763}
2764
2765/**
2766 * Allocates memory for a barycentric timestamps structure.
2767 */
2768int XLALCreateBarycentricData(BarycentricData **stamps, /**< [out] a null timeseries */
2769 INT8 N /**< [in] the desired number of elements in the timeseries */
2770 )
2771{
2772
2773 const char *fn = __func__; /* store function name for log output */
2774
2775 /* check input */
2776 if (N<1) {
2777 LogPrintf(LOG_CRITICAL,"%s : tried to allocate an barycenteredtimestamps with non-positive size.\n",fn);
2779 }
2780 if ((*stamps) != NULL) {
2781 LogPrintf(LOG_CRITICAL,"%s : input timestamps structure does not have null pointer.\n",fn);
2783 }
2784
2785 if (((*stamps) = (BarycentricData *)LALCalloc(1,sizeof(BarycentricData))) == NULL) {
2786 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for timestamps structure.\n",fn);
2788 }
2789 if (((*stamps)->dettime = (double *)LALCalloc(N,sizeof(double))) == NULL) {
2790 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for detector frame timestamps.\n",fn);
2792 }
2793 if (((*stamps)->barytime = (double *)LALCalloc(N,sizeof(double))) == NULL) {
2794 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for barycentric frame timestamps.\n",fn);
2796 }
2797 (*stamps)->length = N;
2798
2799 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2800 return XLAL_SUCCESS;
2801
2802}
2803
2804/**
2805 * Allocates memory for a barycentric timestamps structure.
2806 */
2807int XLALFreeBarycentricData(BarycentricData *stamps /**< [out] a null timeseries */
2808 )
2809{
2810
2811 const char *fn = __func__; /* store function name for log output */
2812
2813 /* check input */
2814 if (stamps == NULL) {
2815 LogPrintf(LOG_CRITICAL,"%s : input timestamps structure has null pointer.\n",fn);
2817 }
2818
2819 if (stamps->dettime != NULL) XLALFree(stamps->dettime);
2820 if (stamps->dettime != NULL) XLALFree(stamps->barytime);
2821 XLALFree(stamps);
2822
2823 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2824 return XLAL_SUCCESS;
2825
2826}
2827/**
2828 * This function outputs an XTEUINT4TimeSeriesArray to a frame file or files.
2829 */
2830int XLALXTEUINT4TimeSeriesArrayToGTI(GTIData **gti, /**< [out] the output GTI table */
2831 XTEUINT4TimeSeriesArray *ts /**< [in] the timeseries array */
2832 )
2833{
2834
2835 static const char *fn = __func__; /* store function name for log output */
2836 INT4 ngti = 0; /* the number of gti entries */
2837 CHAR *temp_undefined = NULL; /* temporary pointer to master undefined vector */
2838 XTEUINT4TimeSeries *tempts = NULL; /* temporary pointer to first timeseries */
2839 INT4 i; /* counter */
2840 INT8 j; /* counter */
2841
2842 /* check input */
2843 if (ts == NULL) {
2844 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure has null pointer.\n",fn);
2846 }
2847 if ((*gti) != NULL) {
2848 LogPrintf(LOG_CRITICAL,"%s : input GTIData structure has non-null pointer.\n",fn);
2850 }
2851
2852 /* point temporary timeseries pointer to first timeseries */
2853 tempts = ts->ts[0];
2854
2855 /* allocate memory for a master list of undefined samples */
2856 if ((temp_undefined = (CHAR *)LALCalloc(tempts->length,sizeof(CHAR))) == NULL) {
2857 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for master undefined vector.\n",fn);
2859 }
2860
2861 /* initialise master list and then loop over each timeseries and make a master list of undefined samples */
2862 for (j=0;j<tempts->length;j++) temp_undefined[j] = 0;
2863 for (i=0;i<ts->length;i++) {
2864 for (j=0;j<ts->ts[i]->length;j++) if (ts->ts[i]->undefined[j]) temp_undefined[j] = 1;
2865 }
2866
2867 /* test for extended zero data - this is only really applicable to sources with high expected counts */
2868 /* weak sources may have extended spans of zero counts */
2869 for (i=0;i<ts->length;i++) {
2870
2871 j = 0;
2872 UINT4 zerocount = 0;
2873
2874 /* loop over samples within the timeseries */
2875 while (j<ts->ts[i]->length) {
2876
2877 /* identify a stretch of zeros */
2878 if (ts->ts[i]->data[j] == 0) zerocount++;
2879
2880 /* if the number of zeros is beyond the max allowed then we mark the stretch undefined */
2881 else if (ts->ts[i]->data[j] != 0) {
2882
2883 if (zerocount>MAXZEROCOUNT) {
2884 UINT4 k;
2885 for (k=j-zerocount;k<j;k++) temp_undefined[k] = 1;
2886 }
2887 zerocount = 0;
2888
2889 }
2890 j++;
2891 }
2892 }
2893
2894 /* test for sections of data too short for analysis */
2895 for (i=0;i<ts->length;i++) {
2896
2897 j = 0;
2898 UINT4 goodcount = 0;
2899
2900 /* loop over samples within the timeseries */
2901 while (j<ts->ts[i]->length) {
2902 /* fprintf(stdout,"index = (%ld/%ld) undefined = %d ->",(long int)j,(long int)ts->ts[i]->length,temp_undefined[j]); */
2903 /* identify a stretch of good data */
2904 if (temp_undefined[j] == 0) goodcount++;
2905
2906 /* if the length of the data is too short then set the data undefined */
2907 else if (temp_undefined[j] != 0) {
2908
2909 if (goodcount*ts->ts[i]->deltat<MINFRAMELENGTH) {
2910 UINT4 k;
2911
2912 for (k=j-goodcount;k<j;k++) temp_undefined[k] = 1;
2913 }
2914 goodcount = 0;
2915
2916 }
2917 /* fprintf(stdout," %d\n",temp_undefined[j]); */
2918 j++;
2919 }
2920 }
2921
2922 /* compute the number of GTIs */
2923 {
2924 BOOLEAN flag = FALSE;
2925 for (j=0;j<tempts->length;j++) {
2926 if ((!flag) && (temp_undefined[j] == 0)) flag = TRUE;
2927 if (flag && temp_undefined[j]) {
2928 flag = FALSE;
2929 ngti++;
2930 }
2931 }
2932 if (flag) ngti++;
2933 }
2934 LogPrintf(LOG_DEBUG,"%s : final GTI table has %d entries.\n",fn,ngti);
2935
2936 /* if there were actual good time intervals */
2937 if (ngti > 0) {
2938
2939 /* allocate memory for a GTI table */
2940 if (XLALCreateGTIData(gti,ngti)) {
2941 LogPrintf(LOG_CRITICAL,"%s : failed to allocate memory for GTI with error = %d.\n",fn,xlalErrno);
2943 }
2944
2945 /* go back through the data quality and fill in the GTI table */
2946 {
2947 BOOLEAN flag = FALSE;
2948 i = 0;
2949 for (j=0;j<tempts->length;j++) {
2950 if ((!flag) && (temp_undefined[j] == 0)) {
2951 flag = TRUE;
2952 (*gti)->start[i] = tempts->tstart + (REAL8)j*tempts->deltat;
2953 }
2954 if (flag && temp_undefined[j]) {
2955 flag = FALSE;
2956 (*gti)->end[i] = tempts->tstart + (REAL8)j*tempts->deltat;
2957 i++;
2958 }
2959 }
2960 if (flag) (*gti)->end[i] = tempts->tstart + tempts->T;
2961 }
2962
2963 /* debugging */
2964 LogPrintf(LOG_DEBUG,"%s : master GTI times :\n",fn);
2965 for (i=0;i<(*gti)->length;i++) LogPrintf(LOG_DEBUG,"%s : %6.12f -> %6.12f\n",fn,(*gti)->start[i],(*gti)->end[i]);
2966
2967 }
2968 else {
2969 LogPrintf(LOG_NORMAL,"%s : no GTIs found for the current timeseries array.\n",fn);
2970 (*gti) = NULL;
2971 }
2972
2973 /* free memory */
2974 XLALFree(temp_undefined);
2975
2976 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
2977 return XLAL_SUCCESS;
2978
2979}
2980
2981/**
2982 * This function outputs an XTEUINT4TimeSeriesArray to a frame file or files.
2983 * It creates a frame channel for each seperate timeseries extracted from the
2984 * FITS file. It creates multiple frames if there are gaps in the data.
2985 *
2986 */
2987int XLALXTEUINT4TimeSeriesArrayToFrames(XTEUINT4TimeSeriesArray *ts, /**< [in] the input xte timeseries array */
2988 CHAR *outputdir /**< [in] the output directory name */
2989 )
2990{
2991
2992 /* FIXME - need to put comments into the frame */
2993
2994 static const char *fn = __func__; /* store function name for log output */
2995 INT4 i; /* counter */
2996 INT4 k; /* counter */
2997 XTEUINT4TimeSeries *tempts = NULL; /* pointer to first timeseries */
2998 GTIData *gti = NULL; /* final GTI information */
2999
3000 /* check input */
3001 if (ts == NULL) {
3002 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure has null pointer.\n",fn);
3004 }
3005
3006 /* point temporary pointer to first timeseries */
3007 tempts = ts->ts[0];
3008
3009 /* make sure all timeseries have identical start, duration and sampling times */
3010 for (i=0;i<ts->length;i++) {
3011 if ((ts->ts[i]->length != tempts->length) ||
3012 (ts->ts[i]->tstart != tempts->tstart) ||
3013 (ts->ts[i]->T != tempts->T)) {
3014 LogPrintf(LOG_CRITICAL,"%s : input timeseries have different parameters.\n",fn);
3016 }
3017 }
3018
3019 /* make a new GTI table based on data quality from all timeseries */
3021 LogPrintf(LOG_CRITICAL,"%s : XLALXTEUINT4TimeSeriesToTGI() failed with error = %d\n",fn,xlalErrno);
3022 return 1;
3023 }
3024 else if (gti == NULL) {
3025 LogPrintf(LOG_NORMAL,"%s : No GTI entries found after processing. Exiting.\n",fn);
3026 exit(0);
3027 }
3028 LogPrintf(LOG_DEBUG,"%s : generated a master GTI table\n",fn);
3029
3030 /* if there is any GTI data */
3031 if (gti != NULL) {
3032
3033 /* loop over each GTI entry such that we output a single frame for each one */
3034 for (k=0;k<gti->length;k++) {
3035
3036 char outputfile[STRINGLENGTH]; /* stores name of output frame file */
3037 LALFrameH *outFrame = NULL; /* frame data structure */
3038 LIGOTimeGPS epoch; /* stores the timeseries epoch */
3039 INT8 sidx; /* the integer GPS second starting index of the data */
3040 INT8 N; /* the new number of data samples */
3041
3042 /* enforce integer seconds duration */
3043 INT4 start = (INT4)ceil(gti->start[k]); /* the new end time of the data */
3044 INT4 end = (INT4)floor(gti->end[k]); /* the new end time of the data */
3045 INT4 T = end - start; /* the new observation time */
3046 LogPrintf(LOG_DEBUG,"%s : segment %d -> %d (%d sec)\n",fn,start,end,T);
3047
3048 /* if the segment is long enough to warrant making a frame */
3049 if (T>=MINFRAMELENGTH) {
3050
3051 /* convert start epoch to a GPS structure - we enforce integer GPS start times for simplicity */
3052 epoch.gpsSeconds = start;
3053 epoch.gpsNanoSeconds = 0;
3054 LogPrintf(LOG_DEBUG,"%s : modifying start time to integer epoch %d\n",fn,epoch.gpsSeconds);
3055
3056 /* compute new number of samples and starting index */
3057 sidx = (INT8)floor(0.5 + (epoch.gpsSeconds - tempts->tstart)/tempts->deltat);
3058 N = (INT8)floor(T/tempts->deltat);
3059 LogPrintf(LOG_DEBUG,"%s : outputting %" LAL_INT8_FORMAT " samples to frame\n",fn,N);
3060
3061 /* construct file name - we use the LIGO format <DETECTOR>-<COMMENT>-<GPSSTART>-<DURATION>.gwf */
3062 /* the comment field we sub-format into <INSTRUMENT>_<FRAME>_<SOURCE>_<OBSID_APID> */
3063 if (ts->bary)
3064 {
3065 if(STRINGLENGTH <= snprintf(outputfile,STRINGLENGTH,"%s/X1-PCA_SSB_%s_%s_%s-%d-%d.gwf",
3066 outputdir,ts->objectname,ts->obsid,ts->apid,epoch.gpsSeconds,T))
3067 printf("Warning: truncated string %s\n",outputfile);
3068 }
3069 else
3070 {
3071 if(STRINGLENGTH <= snprintf(outputfile,STRINGLENGTH,"%s/X1-PCA_DET_%s_%s_%s-%d-%d.gwf",
3072 outputdir,ts->objectname,ts->obsid,ts->apid,epoch.gpsSeconds,T))
3073 printf("Warning: truncated string %s\n",outputfile);
3074 }
3075 LogPrintf(LOG_DEBUG,"%s : output file = %s\n",fn,outputfile);
3076
3077 /* generate a frame data structure - last threee inputs are [project, run, frnum, detectorFlags] */
3078 if ((outFrame = XLALFrameNew(&epoch,(REAL8)T,"XTE_PCA",1,0,0)) == NULL) {
3079 LogPrintf(LOG_CRITICAL, "%s : XLALFrameNew() failed with error = %d.\n",fn,xlalErrno);
3081 }
3082 LogPrintf(LOG_DEBUG,"%s : set-up frame structure\n",fn);
3083
3084 /* loop over each timeseries (one for each channel from each column) */
3085 for (i=0;i<ts->length;i++) {
3086
3087 INT4TimeSeries *output = NULL; /* temporary output timeseries */
3088 UINT4 j; /* counter */
3089 CHAR channelname[STRINGLENGTH]; /* string used to name each channel in the frame */
3090
3091 /* define current channel name */
3092 /* the format is X1:<MODE>-<COLNAME>-<LLD>-<DETCONFIG>-<MINENERGY>_<MAXENERGY> */
3093 if(STRINGLENGTH<=snprintf(channelname,STRINGLENGTH,"%s:%s-%s-%d-%s-%d_%d",xtechannelname,ts->mode,ts->ts[i]->colname,ts->lld,ts->ts[i]->detconfig,ts->ts[i]->energy[0],ts->ts[i]->energy[1]))
3094 printf("Warning: truncated channel name %s\n",channelname);
3095 LogPrintf(LOG_DEBUG,"%s : defined current channel name as %s\n",fn,channelname);
3096
3097 /* create empty timeseries - this is INT4 not UINT4 because there is no frame writing function for UINT4 */
3098 if ((output = XLALCreateINT4TimeSeries(channelname,&epoch,0,tempts->deltat,&lalDimensionlessUnit,N)) == NULL) {
3099 LogPrintf(LOG_CRITICAL, "%s : XLALCreateINT4TimeSeries() failed to allocate an %" LAL_INT8_FORMAT " length timeseries with error = %d.\n",fn,N,xlalErrno);
3101 }
3102 LogPrintf(LOG_DEBUG,"%s : allocated memory for temporary timeseries\n",fn);
3103
3104 /* fill in timeseries starting from first integer second */
3105 for (j=0;j<output->data->length;j++) {
3106 output->data->data[j] = (INT4)ts->ts[i]->data[j+sidx];
3107 }
3108 LogPrintf(LOG_DEBUG,"%s : populated temporary timeseries\n",fn);
3109
3110 /* add timeseries to frame structure */
3112 LogPrintf(LOG_CRITICAL, "%s : XLALFrameAddINT4TimeSeries() failed with error = %d.\n",fn,xlalErrno);
3114 }
3115 LogPrintf(LOG_DEBUG,"%s : added timeseries from col %s for epoch %d to frame structure\n",fn,ts->ts[i]->colname,epoch.gpsSeconds);
3116
3117 /* free timeseries */
3119
3120 }
3121
3122 /* Here's where we add extra information into the frame */
3123 {
3124 CHAR *versionstring = NULL; /* pointer to a string containing the git version information */
3125
3126 versionstring = XLALVCSInfoString(lalAppsVCSInfoList, 1, "%% ");
3127 XLALFrameAddFrHistory(outFrame,"headerdump",ts->headerdump);
3128 XLALFrameAddFrHistory(outFrame,"comment",ts->comment);
3129 XLALFrameAddFrHistory(outFrame,"versionstring",versionstring);
3130 XLALFree(versionstring);
3131 }
3132
3133 /* write frame structure to file (opens, writes, and closes file) - last argument is compression level */
3134 if (XLALFrameWrite(outFrame,outputfile)) {
3135 LogPrintf(LOG_CRITICAL, "%s : XLALFrameWrite() failed with error = %d.\n",fn,xlalErrno);
3137 }
3138
3139 }
3140 else {
3141 LogPrintf(LOG_DEBUG, "%s : segment %f -> %f not long enough so no frame generated.\n",fn,gti->start[k],gti->end[k]);
3142 }
3143
3144 }
3145
3146 if (XLALFreeGTIData(gti)) {
3147 LogPrintf(LOG_CRITICAL,"%s : XLALFreeGTIData() failed with error = %d\n",fn,xlalErrno);
3148 return 1;
3149 }
3150
3151 }
3152 else {
3153 LogPrintf(LOG_NORMAL,"%s : no GTIs found for this segment so no frames produced.\n",fn);
3154 }
3155
3156 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
3157 return XLAL_SUCCESS;
3158
3159}
3160
3161/**
3162 * This function barycenters an XTEUINT4TimeSeriesArray using a set of barycentric timestamps.
3163 * This is a wrapper for XLALBarycenterXTEUINT4TimeSeries.
3164 *
3165 */
3167 BarycentricData *stamps /**< [in] vector of pairs of detector/barycentered timestamps */
3168 )
3169{
3170
3171 static const char *fn = __func__; /* store function name for log output */
3172 INT8 i; /* counter */
3173 GTIData *gti = NULL; /* final GTI information */
3174
3175 /* check input and output pointers */
3176 if ((*ts) == NULL) {
3177 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure has null pointer.\n",fn);
3179 }
3180 if (stamps == NULL) {
3181 LogPrintf(LOG_CRITICAL,"%s : input barycentric timestamps structure has non-null pointer.\n",fn);
3183 }
3184
3185 /* make a new GTI table based on data quality from all timeseries */
3186 if (XLALXTEUINT4TimeSeriesArrayToGTI(&gti,(*ts))) {
3187 LogPrintf(LOG_CRITICAL,"%s : XLALXTEUINT4TimeSeriesToTGI() failed with error = %d\n",fn,xlalErrno);
3188 return 1;
3189 }
3190 else if (gti == NULL) {
3191 LogPrintf(LOG_NORMAL,"%s : No GTI entries found after processing. Exiting.\n",fn);
3192 exit(0);
3193 }
3194 LogPrintf(LOG_DEBUG,"%s : generated a master GTI table\n",fn);
3195
3196 /* loop over each relevant column and energy channel */
3197 for (i=0;i<(*ts)->length;i++) {
3198
3199 if (XLALBarycenterXTEUINT4TimeSeries(&((*ts)->ts[i]),stamps,gti)) {
3200 LogPrintf(LOG_CRITICAL,"%s : XLALBarycenterXTEUINT4TimeSeries() failed with error = %d\n",fn,xlalErrno);
3202 }
3203 LogPrintf(LOG_DEBUG,"%s : barycentered data from column (%" LAL_INT8_FORMAT "/%d).\n",fn,i+1,(*ts)->length);
3204
3205 }
3206
3207 (*ts)->bary = 1;
3208
3209 /* free gti data */
3210 if (XLALFreeGTIData(gti)) {
3211 LogPrintf(LOG_CRITICAL,"%s : XLALFreeGTIData() failed with error = %d\n",fn,xlalErrno);
3212 return 1;
3213 }
3214
3215 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
3216 return XLAL_SUCCESS;
3217
3218}
3219
3220/**
3221 * This function barycenters an XTEUINT4TimeSeries using a set of barycentric timestamps.
3222 * The input detector frame timeseries is replaced with the output barycentered timeseries.
3223 *
3224 */
3225int XLALBarycenterXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, /**< [in/out] timeseries */
3226 BarycentricData *stamps, /**< [in] vector of pairs of detector/barycentered timestamps */
3227 GTIData *gti /**< [in] GTI data */
3228 )
3229{
3230
3231 static const char *fn = __func__; /* store function name for log output */
3232 INT8 i; /* counter */
3233 INT4 k;
3234 XTEUINT4TimeSeries *tempts = NULL; /* temporary storage for barycentered timeseries */
3235 double start_det,end_det; /* start and end times of detector frame timeseries */
3236 double start_bary,end_bary; /* start and end times of barycentric frame timeseries */
3237 gsl_interp_accel *detbary_acc = NULL; /* structure for accelerating gsl interpolation */
3238 gsl_interp *detbary_interp = NULL; /* structure for gsl interpolation */
3239
3240 /* check input and output pointers */
3241 if ((*ts) == NULL) {
3242 LogPrintf(LOG_CRITICAL,"%s : input timeseries structure has null pointer.\n",fn);
3244 }
3245 if (stamps == NULL) {
3246 LogPrintf(LOG_CRITICAL,"%s : input barycentric timestamps structure has non-null pointer.\n",fn);
3248 }
3249
3250 /* select latest start time and earliest end time that are within the timestamps AND data limits */
3251 start_det = (*ts)->tstart > stamps->dettime[0] ? (*ts)->tstart : stamps->dettime[0];
3252 end_det = ((*ts)->tstart + (*ts)->T) < stamps->dettime[stamps->length-1] ? ((*ts)->tstart + (*ts)->T) : stamps->dettime[stamps->length-1];
3253
3254 /* check that times are still valid - we exit cleanly here without an error */
3255 if (start_det>=end_det) {
3256 LogPrintf(LOG_NORMAL, "%s : GPS start (%f) > GPS end time (%f), unable to generate a barycentric time series. Exiting.\n",fn,start_det,end_det);
3257 exit(0);
3258 }
3259
3260 /* gsl memory allocation for interpolation of the timestamps */
3261 if ((detbary_acc = gsl_interp_accel_alloc()) == NULL) {
3262 LogPrintf(LOG_CRITICAL, "%s : gsl_interp_accel_alloc() failed to allocate memory for acceleration.\n",fn);
3264 }
3265
3266 /* only perform gsl spline interpolation if we have more than 2 timestamps - otherwise use linear */
3267 if (stamps->length > 2) {
3268 if ((detbary_interp = gsl_interp_alloc(gsl_interp_cspline,stamps->length)) == NULL) {
3269 LogPrintf(LOG_CRITICAL, "%s : gsl_spline_alloc() failed to allocate memory for acceleration.\n",fn);
3271 }
3272 LogPrintf(LOG_DEBUG,"%s : performing nearest neighbour spline interpolation for barycentering\n",fn);
3273 }
3274 else if (stamps->length == 2) {
3275 if ((detbary_interp = gsl_interp_alloc(gsl_interp_linear,stamps->length)) == NULL) {
3276 LogPrintf(LOG_CRITICAL, "%s : gsl_spline_alloc() failed to allocate memory for acceleration.\n",fn);
3278 }
3279 LogPrintf(LOG_DEBUG,"%s : performing nearest neighbour linear interpolation for barycentering\n",fn);
3280 }
3281 else {
3282 LogPrintf(LOG_CRITICAL, "%s : only one timestamp so unable to perform barycentering, exiting.\n",fn);
3284 }
3285
3286 /* set up gsl interpolation for det -> bary to get start and end times of barycentric timeseries */
3287 if (gsl_interp_init(detbary_interp,stamps->dettime,stamps->barytime,stamps->length)) {
3288 LogPrintf(LOG_CRITICAL, "%s : gsl_spline_init() failed for det -> bary interpolation.\n",fn);
3290 }
3291
3292 /* compute barycentric time of first and last sample */
3293 start_bary = gsl_interp_eval(detbary_interp,stamps->dettime,stamps->barytime,start_det,detbary_acc);
3294 end_bary = gsl_interp_eval(detbary_interp,stamps->dettime,stamps->barytime,end_det,detbary_acc);
3295 LogPrintf(LOG_DEBUG,"%s : barycentric GPS start %f\n",fn,start_bary);
3296 LogPrintf(LOG_DEBUG,"%s : barycentric GPS end = %f\n",fn,end_bary);
3297 LogPrintf(LOG_DEBUG,"%s : barycentric duration = %f\n",fn,end_bary-start_bary);
3298
3299 {
3300 /* define number of barycentric timesamples */
3301 INT8 N = (INT8)floor(0.5 + (end_bary-start_bary)/(*ts)->deltat);
3302
3303 /* allocate temp memory first */
3305 LogPrintf(LOG_DEBUG,"%s : created a temporary short int timeseries with %" LAL_INT8_FORMAT " points\n",fn,N);
3306 }
3307
3308 /* initialise the data - since the vector will only be filled in for GTI data segments we need to */
3309 /* make sure that all remaining data is initialised and undefined */
3310 for (i=0;i<tempts->length;i++) {
3311 tempts->data[i] = 0;
3312 tempts->undefined[i] = 1;
3313 }
3314
3315 /* we perform the barycentering seperately for each GTI interval since in bad data we may not have */
3316 /* timestamps. The interpolation could do unpredictable things with very large gaps. */
3317
3318 /* loop over each GTI entry */
3319 for (k=0;k<gti->length;k++) {
3320
3321 INT4 sidx = stamps->length - 1; /* timestamps indices */
3322 INT4 eidx = 0; /* timestamps indices */
3323 INT4 nstamps = 0; /* the number of temporary timestamps */
3324 BarycentricData *tempstamps = NULL; /* temporary timestamps vector */
3325 gsl_interp *barydet_interp = NULL; /* structure for gsl interpolation */
3326 gsl_interp_accel *barydet_acc = NULL; /* structure for accelerating gsl interpolation */
3327 REAL8 tempstart_det,tempend_det; /* start and end times of detector frame timeseries */
3328 INT4 gap = 0; /* timestamp gap flag */
3329
3330 /* find the min and max timestamps associated with this GTI entry */
3331 while ( ( stamps->dettime[sidx] > gti->start[k] ) && ( sidx >= 0 ) ) sidx--;
3332 while ( ( stamps->dettime[eidx] < gti->end[k] ) && ( eidx < stamps->length - 1 ) ) eidx++;
3333
3334 /* test timestamp gaps at the start and end points */
3335 if ( sidx < stamps->length - 1 ) {
3336 if ( ( stamps->dettime[sidx+1] - stamps->dettime[sidx] ) > MAXTIMESTAMPDELTAT ) sidx += 1;
3337 }
3338 if ( eidx > 0 ) {
3339 if ( ( stamps->dettime[eidx] - stamps->dettime[eidx-1] ) > MAXTIMESTAMPDELTAT ) eidx -= 1;
3340 }
3341
3342 nstamps = eidx - sidx + 1;
3343 if ( (sidx > stamps->length-1) || (eidx < 0) ) {
3344 LogPrintf(LOG_CRITICAL, "%s : timestamps indices for GTI range %d -> %d are out of range, exiting.\n",fn,sidx,eidx);
3346 }
3347 LogPrintf(LOG_DEBUG,"%s : temporary timestamps have indices %d -> %d\n",fn,sidx,eidx);
3348
3349 /* check timestamp gaps - they can't be too far apart */
3350 for (i=sidx;i<eidx;i++) {
3351 /* LogPrintf(LOG_DEBUG, "%s : detector subset stamps %f -> %f (%f)\n",fn,stamps->dettime[i],stamps->dettime[i+1],stamps->dettime[i+1]-stamps->dettime[i]); */
3352 if (stamps->dettime[i+1]-stamps->dettime[i]>MAXTIMESTAMPDELTAT) {
3353 LogPrintf(LOG_NORMAL, "%s : timestamp spacing is too large for accurate barycentering.\n",fn);
3354 gap = 1;
3355 }
3356 }
3357
3358 /* only proceed if we have at least 2 timestamps */
3359 if ((sidx<eidx) && (!gap)) {
3360
3361 /* allocate memory for temporary stamps */
3362 if (XLALCreateBarycentricData(&tempstamps,nstamps)) {
3363 LogPrintf(LOG_CRITICAL, "%s : XLALCreateBarycentricData() failed to allocate memory for temporary timestamps.\n",fn);
3365 }
3366
3367 /* copy stamps to tempstamps */
3368 for (i=0;i<tempstamps->length;i++) {
3369 tempstamps->dettime[i] = stamps->dettime[sidx+i];
3370 tempstamps->barytime[i] = stamps->barytime[sidx+i];
3371 }
3372
3373 /* select latest start time and earliest end time that are within the timestamps AND data limits */
3374 tempstart_det = (*ts)->tstart > tempstamps->dettime[0] ? (*ts)->tstart : tempstamps->dettime[0];
3375 tempend_det = ((*ts)->tstart + (*ts)->T) < tempstamps->dettime[tempstamps->length-1] ? ((*ts)->tstart + (*ts)->T) : tempstamps->dettime[tempstamps->length-1];
3376
3377 /* compute barycentric time of first and last sample in this GTI entry */
3378 REAL8 tempstart_bary = gsl_interp_eval(detbary_interp,stamps->dettime,stamps->barytime,tempstart_det,detbary_acc);
3379 REAL8 tempend_bary = gsl_interp_eval(detbary_interp,stamps->dettime,stamps->barytime,tempend_det,detbary_acc);
3380 /* INT8 tempN = (INT8)((tempend_bary-tempstart_bary)/(*ts)->deltat); */
3381 LogPrintf(LOG_DEBUG,"%s : GTI[%d] barycentric GPS start %f (delta = %f)\n",fn,k,tempstart_bary,tempstart_bary-start_bary);
3382 LogPrintf(LOG_DEBUG,"%s : GTI[%d] barycentric GPS end = %f (delta = %f)\n",fn,k,tempend_bary,tempend_bary-start_bary);
3383 LogPrintf(LOG_DEBUG,"%s : GTI[%d] barycentric duration = %f\n",fn,k,tempend_bary-tempstart_bary);
3384
3385 /* gsl memory allocation for interpolation of the timestamps */
3386 if ((barydet_acc = gsl_interp_accel_alloc()) == NULL) {
3387 LogPrintf(LOG_CRITICAL, "%s : gsl_interp_accel_alloc() failed to allocate memory for acceleration.\n",fn);
3389 }
3390
3391 /* only perform gsl spline interpolation if we have more than 2 timestamps - otherwise use linear */
3392 if (tempstamps->length > 2) {
3393 if ((barydet_interp = gsl_interp_alloc(gsl_interp_cspline,tempstamps->length)) == NULL) {
3394 LogPrintf(LOG_CRITICAL, "%s : gsl_spline_alloc() failed to allocate memory for acceleration.\n",fn);
3396 }
3397 LogPrintf(LOG_DEBUG,"%s : performing nearest neighbour spline interpolation for barycentering\n",fn);
3398 }
3399 else if (tempstamps->length == 2) {
3400 if ((barydet_interp = gsl_interp_alloc(gsl_interp_linear,tempstamps->length)) == NULL) {
3401 LogPrintf(LOG_CRITICAL, "%s : gsl_spline_alloc() failed to allocate memory for acceleration.\n",fn);
3403 }
3404 LogPrintf(LOG_DEBUG,"%s : performing nearest neighbour linear interpolation for barycentering\n",fn);
3405 }
3406
3407 /* if we have enough timestamps then perform barycentering */
3408 if (tempstamps->length >= 2) {
3409
3410 /* set up gsl interpolation for bary -> det for actual resampling */
3411 if (gsl_interp_init(barydet_interp,tempstamps->barytime,tempstamps->dettime,tempstamps->length)) {
3412 LogPrintf(LOG_CRITICAL, "%s : gsl_spline_init() failed for bary -> det interpolation.\n",fn);
3414 }
3415 LogPrintf(LOG_DEBUG,"%s : initialised the spline interpolation\n",fn);
3416
3417 /* loop over each evenly spaced time sample in barycentric frame and interpolate to generate barycentric timeseries */
3418 {
3419 INT8 s = floor(0.5 + (tempstart_bary-start_bary)/(*ts)->deltat);
3420 INT8 e = floor(0.5 + (tempend_bary-start_bary)/(*ts)->deltat);
3421 for (i=s;i<e;i++) {
3422
3423 REAL8 bt = start_bary + (REAL8)i*(*ts)->deltat;
3424 REAL8 delta_dettime = gsl_interp_eval(barydet_interp,tempstamps->barytime,tempstamps->dettime,bt,barydet_acc) - (*ts)->tstart;
3425 INT8 idx = floor(0.5 + delta_dettime/(*ts)->deltat);
3426 tempts->data[i] = (*ts)->data[idx];
3427 tempts->undefined[i] = (*ts)->undefined[idx];
3428
3429 }
3430 }
3431 LogPrintf(LOG_DEBUG,"%s : performed barycentering using nearest bin interpolation\n",fn);
3432
3433 /* free mem */
3434 gsl_interp_free(barydet_interp);
3435 gsl_interp_accel_free(barydet_acc);
3436
3437 }
3438 else {
3439 LogPrintf(LOG_NORMAL, "%s : only one timestamp so unable to perform barycentering on this GTI segment.\n",fn);
3440 }
3441
3442 /* free mem */
3443 XLALFreeBarycentricData(tempstamps);
3444
3445 }
3446
3447 }
3448
3449 /* reallocate input time series and fill it with barycentric timeseries and params */
3451 LogPrintf(LOG_CRITICAL, "%s : XLALReallocXTEUINT4TimeSeries() failed with error = %d.\n",fn,xlalErrno);
3453 }
3454
3455 /* fill it with barycentric timeseries and params */
3456 for (i=0;i<tempts->length;i++) {
3457 (*ts)->data[i] = tempts->data[i];
3458 (*ts)->undefined[i] = tempts->undefined[i];
3459 }
3460 (*ts)->length = tempts->length;
3461 (*ts)->T = (*ts)->length*(*ts)->deltat;
3462 (*ts)->tstart = start_bary;
3463 LogPrintf(LOG_DEBUG,"%s : resized original timeseries and replaced it with barycentered timeseries\n",fn);
3464
3465 /* free temp timeseries */
3466 if (XLALFreeXTEUINT4TimeSeries(tempts)) {
3467 LogPrintf(LOG_CRITICAL, "%s : XLALFreeXTEUINT4TimeSeries() failed with error = %d.\n",fn,xlalErrno);
3469 }
3470 LogPrintf(LOG_DEBUG,"%s : freed temporary memory\n",fn);
3471
3472 /* free interpolation structures */
3473 gsl_interp_free(detbary_interp);
3474 gsl_interp_accel_free(detbary_acc);
3475 LogPrintf(LOG_DEBUG,"%s : freed interpolation structures\n",fn);
3476
3477 /* debugging */
3478 {
3479 int M = (*ts)->length > 10 ? 10 : (*ts)->length;
3480 LogPrintf(LOG_DEBUG,"%s : barycentered timeseries :\n",fn);
3481 for (i=0;i<M;i++) LogPrintf(LOG_DEBUG,"%s : %6.12f %d (%d)\n",fn,start_bary+(double)i*(*ts)->deltat,(*ts)->data[i],(*ts)->undefined[i]);
3482 }
3483
3484 LogPrintf(LOG_DEBUG,"%s : leaving.\n",fn);
3485 return XLAL_SUCCESS;
3486
3487}
#define __func__
const LALVCSInfoList lalAppsVCSInfoList
NULL-terminated list of VCS and build information for LALApps and its dependencies
int j
int k
void LALCheckMemoryLeaks(void)
#define LALRealloc(p, n)
#define LALCalloc(m, n)
const double c1
const double c2
#define char
#define STRING(a)
INT4 dummy
#define TRUE
Definition: animate.c:94
#define FALSE
Definition: animate.c:95
int s
double e
LIGOTimeGPS tstart
unsigned char BOOLEAN
double REAL8
#define XLAL_INIT_DECL(var,...)
int16_t INT2
int64_t INT8
char CHAR
uint32_t UINT4
int32_t INT4
LALFrameUFrameH LALFrameH
int XLALFrameAddFrHistory(LALFrameH *frame, const char *name, const char *comment)
int XLALFrameWrite(LALFrameH *frame, const char *fname)
int XLALFrameAddINT4TimeSeriesProcData(LALFrameH *frame, const INT4TimeSeries *series)
LALFrameH * XLALFrameNew(const LIGOTimeGPS *epoch, double duration, const char *project, int run, int frnum, INT8 detectorFlags)
void * XLALCalloc(size_t m, size_t n)
void * XLALRealloc(void *p, size_t n)
void XLALFree(void *p)
#define LAL_INT8_FORMAT
int XLALStringCaseCompare(const char *s1, const char *s2)
int XLALStringNCaseCompare(const char *s1, const char *s2, size_t n)
char * XLALVCSInfoString(const LALVCSInfoList vcs_list, const int verbose, const char *prefix)
void LogPrintf(LogLevel_t, const char *format,...) _LAL_GCC_PRINTF_FORMAT_(2
LOG_CRITICAL
LOG_DEBUG
LOG_NORMAL
static const INT4 m
void XLALDestroyINT4TimeSeries(INT4TimeSeries *series)
INT4TimeSeries * XLALCreateINT4TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalDimensionlessUnit
int XLALUserVarReadAllInput(BOOLEAN *should_exit, int argc, char *argv[], const LALVCSInfoList vcs_list)
void XLALDestroyUserVars(void)
#define XLALRegisterUvarMember(name, type, option, category,...)
#define xlalErrno
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
#define XLAL_CHECK_MAIN(assertion,...)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EINVAL
XLAL_EFAILED
long long count
CHAR comment[LIGOMETA_COMMENT_MAX]
Definition: inspfrinj.c:350
static LALStatus status
Definition: inspinj.c:552
int i
Definition: inspinj.c:596
M
header
type
T
temp
c
int
string mode
start
ts
int N
A structure for storing vectors of detector and barycentric frame timestamps A pre-barycentered FITS ...
REAL8 dtrow
the time steps for the timestamps
REAL8 * dettime
the detector timestamps
INT8 length
the number of timestamps
REAL8 * barytime
the barycentered timestamps
A structure containing all of the relavent information extracted from a single (R)XTE FITS PCA file.
FITSHeader * header
FITS file header information.
BarycentricData * stamps
barycentric timestamps information
XTEUINT4Array ** array
array of vectors containing array data
XTECHARArray ** event
array of vectors containing event data
GTIData * gti
good time interval information
A structure containing all of the relavent information extracted from the header of an (R)XTE FITS PC...
char apid[APIDLENGTH]
stores the APID hex string
double timedel
the timedel keyword for this time series
int * XeCntcolidx
the XeCnt column index
char ** colname
stores the Cnt and Event column names
double dec
the source declination
char objectname[STRINGLENGTH]
the name of the source object
char * headerdump
the entire header dumped in ascii
int LLD
flag for whether it's LLD2 data
long int ncols
the total number of columns in the data table
int type
is the data array (0) or event (1)
char filename[STRINGLENGTH]
the name of the fits file
char mode[STRINGLENGTH]
stores the data mode
char obsid[STRINGLENGTH]
the observation ID
INT4 * rowlength
the row length for each column
long int nrows
the number of rows ( = number of timestamps)
XTETDDESParams ** tddes
the TDDES params for each column
long int nbytesperrow
the number of bytes per row for event data
double gpsoffset
the number to be added to TAI times to get to GPS
int nXeCntcol
the number of columns with Cnt or Event data
double ra
the source right ascension
The good time interval data read from a FITS file.
INT8 length
the number of gti segments
REAL8 * start
the start times of good data
REAL8 * end
the end times of good data
A structure containing a vector of event data information.
XTECHARVector * channeldata
pointers to individual event data vectors
INT4 nchannels
the number of channels
A structure containing event information from a single channel found in an (R)XTE FITS file.
CHAR * data
vector of data
REAL8 deltat
the sampling time
CHAR * undefined
data quality flag
INT8 nevents
the actual number of events
INT8 length
length of the vector
INT8 rowlength
the number of data per timestamp
A structure to store TDDES2 DDL data.
INT4 ndetconfig
the number of detector configurations
INT4 * minenergy
minimum energy channel (0-255) (one for each channel)
INT4 nsamples
the number of samples
INT4 ** detectors
flags indicating which detectors were being used
INT4 * maxenergy
maximum energy channel (0-255) (one for each channel)
INT4 nenergy
the number of energy channels
REAL8 deltat
the sampling time
INT4 nchannels
the number of channels (nenergy * ndetconfig)
REAL8 offset
the time offset
A structure containing a vector of array data information.
INT4 nchannels
the number of channels
XTEUINT4Vector * channeldata
a pointer to array data vectors
A structure for storing an array of integer timeseries for XTE data.
XTEUINT4TimeSeries ** ts
pointer to single timeseries vectors
INT4 bary
barycentered flag
INT4 length
number of timeseries
CHAR * comment
a comment field (used to store original clargs)
CHAR * headerdump
an ascii dump of the original FITS header
A structure for storing a timeseries of unsigned integers for XTE data.
REAL8 tstart
the GPS start time
UINT4 * data
the data (timeseries of binned photon counts)
REAL8 deltat
the time step size in seconds
CHAR * undefined
a data quality flag (0=good, 1=bad)
INT8 length
length of the timeseries
REAL8 T
the time span in seconds
A structure containing array data information from a single channel found in an (R)XTE FITS file.
INT8 rowlength
the number of data per timestamp
CHAR * undefined
data quality flag
INT8 length
length of the vector
REAL8 deltat
the sampling time
UINT4 * data
vector of data
INT4 energy[2]
the energy channel range (0-255)
CHAR detconfig[NPCU+1]
contains detector config string
enum @1 epoch
int output(const char *outfile, int outtype, REAL4TimeSeries *series)
Definition: view.c:603
char string_NAXIS1[]
int main(int argc, char *argv[])
The main function of xtefitstoframe.c.
char string_OBJECT[]
int XLALEventDataToXTEUINT4TimeSeriesArray(XTEUINT4TimeSeriesArray **ts, FITSData *fits, REAL8 dt)
Converts a FITS event data file to a binned timeseries.
int XLALXTEUINT4TimeSeriesArrayToFrames(XTEUINT4TimeSeriesArray *ts, CHAR *outputdir)
This function outputs an XTEUINT4TimeSeriesArray to a frame file or files.
int XLALReadFITSEventData(XTECHARArray **event, fitsfile *fptr, FITSHeader *header, int col)
int XLALCreateBarycentricData(BarycentricData **stamps, INT8 N)
Allocates memory for a barycentric timestamps structure.
#define TIMESTAMPDELTAT
int XLALCreateXTEUINT4TimeSeriesArray(XTEUINT4TimeSeriesArray **x, INT8 N)
int XLALFreeXTEUINT4TimeSeriesArray(XTEUINT4TimeSeriesArray *ts)
Frees an XTEUINT4TimeSeriesArray data structure.
const char * USELESSDATAMODE[5]
int XLALConvertTDDES(XTETDDESParams **params, char *tddes)
Extracts PCA config, energy range and sampling parameters from tddes2 DDL string.
int XLALFreeXTEUINT4TimeSeries(XTEUINT4TimeSeries *ts)
Frees an XTEUINT4TimeSeries data structure.
int XLALCreateGTIData(GTIData **gti, INT8 N)
Allocates memory for a GTI structure.
const char xtechannelname[16]
char string_TIMEZERO[]
#define MIN_DT
int XLALReallocXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, INT8 N)
Resizes an XTEUINT4TimeSeries data structure.
int XLALReadFITSGTI(GTIData **fitsfilegti, fitsfile *fptr)
Read in GTI (good time interval) table from FITS file.
int XLALCreateXTEUINT4TimeSeries(XTEUINT4TimeSeries **x, INT8 N)
Allocates memory for a XTEUINT4TimeSeries.
#define MAXTIMESTAMPDELTAT
int XLALReadFITSFile(FITSData **data, char *filename)
This function reads in data from a FITS file and returns a FITSdata data structure.
char string_OBS_ID[]
int XLALApplyGTIToXTEUINT4TimeSeriesArray(XTEUINT4TimeSeriesArray **ts, GTIData *gti)
Sets timeseries array samples NOT in the GTI table as undefined and zeros the corresponding data.
char string_2LLD[]
int XLALArrayDataToXTEUINT4TimeSeriesArray(XTEUINT4TimeSeriesArray **ts, FITSData *fits, REAL8 dt)
Converts a FITS array data file to a binned timeseries.
#define EVENT
int XLALReadFITSTimeStamps(BarycentricData **fitsfilebary, fitsfile *fptr)
Reads in FITS file first extension header timestamps information.
char string_DATAMODE[]
#define NPCU
char string_TDDES2[]
#define MAXZEROCOUNT
int XLALFreeGTIData(GTIData *gti)
Frees memory for a GTI structure.
char string_HDUCLAS1[]
char string_TFIELDS[]
char string_TIMEDEL[]
int XLALReadFITSArrayData(XTEUINT4Array **array, fitsfile *fptr, FITSHeader *header, int col)
#define GPSMINUSTAI
const char * APID[6]
int XLALXTEUINT4TimeSeriesArrayToGTI(GTIData **gti, XTEUINT4TimeSeriesArray *ts)
This function outputs an XTEUINT4TimeSeriesArray to a frame file or files.
#define STRINGLENGTH
int XLALFreeBarycentricData(BarycentricData *stamps)
Allocates memory for a barycentric timestamps structure.
#define MINFRAMELENGTH
char string_RA_PNT[]
#define LONGSTRINGLENGTH
int ReadUserVars(int argc, char *argv[], UserInput_t *uvar, CHAR *clargs)
Read in input user arguments.
int removechar(CHAR *p, CHAR ch)
Removes a character from a string.
int vrbflg
defined in lal/lib/std/LALError.c
char string_DEC_PNT[]
int XLALBarycenterXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, BarycentricData *stamps, GTIData *gti)
This function barycenters an XTEUINT4TimeSeries using a set of barycentric timestamps.
#define NAPID
int XLALReduceBarycentricData(BarycentricData **stamps)
Reduces the number of barycentric timestamps from a FITS data structure.
#define APIDLENGTH
char string_TTYPE1[]
#define NUSELESSDATAMODE
int XLALBarycenterXTEUINT4TimeSeriesArray(XTEUINT4TimeSeriesArray **ts, BarycentricData *stamps)
This function barycenters an XTEUINT4TimeSeriesArray using a set of barycentric timestamps.
int XLALArrayDataToXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, XTEUINT4Vector *event, BarycentricData *stamps, REAL8 dt)
Converts a FITS file data structure containing science array (binned) data into a timeseries.
int XLALEventDataToXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, XTECHARVector *array, BarycentricData *stamps, REAL8 dt)
Converts a FITS event data file to a binned timeseries.
char string_DELTAT[]
int XLALReadFITSHeader(FITSHeader *fitsfileheader, fitsfile *fptr)
Reads in the FITS file first extension header information.
int XLALFreeFITSData(FITSData *x)
Frees a FITS data structure.
#define ARRAY
int XLALApplyGTIToXTEUINT4TimeSeries(XTEUINT4TimeSeries **ts, GTIData *gti)
Sets timeseries samples NOT in the GTI table as undefined and zeros the corresponding data.