Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
SFTcatalog.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010, 2014, 2016, 2019, 2020, 2022 Karl Wette
3 * Copyright (C) 2010 Chris Messenger
4 * Copyright (C) 2009 Adam Mercer
5 * Copyright (C) 2004--2008, 2013, 2014, 2017 Reinhard Prix
6 * Copyright (C) 2004, 2005, 2009, 2010, 2017 Bernd Machenschalk
7 * Copyright (C) 2004, 2005 Alicia Sintes
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with with program; see the file COPYING. If not, write to the
21 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * MA 02110-1301 USA
23 */
24
25/*---------- includes ----------*/
26
27#include <sys/types.h>
28#include <sys/stat.h>
29
30#include <lal/Units.h>
31#include <lal/Sequence.h>
32
33#include "SFTinternal.h"
34
35/*---------- internal prototypes ----------*/
36
37static long get_file_len( FILE *fp );
38
39static BOOLEAN consistent_mSFT_header( SFTtype header1, UINT4 version1, UINT4 nsamples1, UINT2 windowspec1, SFTtype header2, UINT4 version2, UINT4 nsamples2, UINT2 windowspec2 );
41
42/*========== function definitions ==========*/
43
44/// \addtogroup SFTfileIO_h
45/// @{
46
47/**
48 * Find the list of SFTs matching the \a file_pattern and satisfying the given \a constraints,
49 * return an \c SFTCatalog of the matching SFTs.
50 *
51 * The optional \a constraints that can be specified are (type SFTConstraints)
52 * - 'detector': which detector
53 * - 'time-span': GPS start- and end-times
54 * - 'timestamps': list of GPS start-times
55 *
56 * ==> The returned SFTCatalog can be used directly as input to XLALLoadSFTs()
57 * to load a single-IFO SFTVector, or XLALLoadMultiSFTs() to load a
58 * multi-IFO vector of SFTVectors
59 *
60 * Except for the 'file_pattern' input, all the other constraints are optional
61 * and can be passed as NULL (either globally constraings==NULL, or individually).
62 *
63 * Note that the constraints are combined by 'AND' and the resulting full constraint
64 * MUST be satisfied (in particular: if 'timestamps' is given, all timestamps within
65 * [minStartTime, maxStartTime) MUST be found!.
66 *
67 * The returned SFTs in the catalogue are sorted by increasing GPS-epochs !
68 *
69 */
71XLALSFTdataFind( const CHAR *file_pattern, /**< which SFT-files */
72 const SFTConstraints *constraints /**< additional constraints for SFT-selection */
73 )
74{
75 /* ----- check input */
76 XLAL_CHECK_NULL( file_pattern != NULL, XLAL_EINVAL );
77
78 if ( constraints && constraints->detector ) {
79 if ( !XLALIsValidCWDetector( constraints->detector ) ) {
80 XLAL_ERROR_NULL( XLAL_EDOM, "Invalid detector-constraint '%s'\n\n", constraints->detector );
81 }
82 }
83
84 /* prepare return-catalog */
85 SFTCatalog *ret;
86 XLAL_CHECK_NULL( ( ret = LALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_ENOMEM );
87
88 /* find matching filenames */
90 XLAL_CHECK_NULL( ( fnames = XLALFindFiles( file_pattern ) ) != NULL, XLAL_EFUNC, "Failed to find filelist matching pattern '%s'.\n\n", file_pattern );
91 UINT4 numFiles = fnames->length;
92
93 UINT4 numSFTs = 0;
94 /* ----- main loop: parse all matching files */
95 for ( UINT4 i = 0; i < numFiles; i ++ ) {
96 const CHAR *fname = fnames->data[i];
97
98 /* merged SFTs need to satisfy stronger consistency-constraints (-> see spec) */
99 BOOLEAN mfirst_block = TRUE;
100 UINT4 mprev_version = 0;
101 SFTtype XLAL_INIT_DECL( mprev_header );
102 REAL8 mprev_nsamples = 0;
103 UINT2 mprev_windowspec = 0;
104
105 FILE *fp;
106 if ( ( fp = fopen( fname, "rb" ) ) == NULL ) {
107 XLALPrintError( "ERROR: Failed to open matched file '%s'\n\n", fname );
111 }
112
113 long file_len;
114 if ( ( file_len = get_file_len( fp ) ) == 0 ) {
115 XLALPrintError( "ERROR: got file-len == 0 for '%s'\n\n", fname );
118 fclose( fp );
120 }
121
122 /* go through SFT-blocks in fp */
123 while ( ftell( fp ) < file_len ) {
124 SFTtype this_header;
125 UINT4 this_version;
126 UINT4 this_nsamples;
127 UINT8 this_crc;
128 UINT2 this_windowspec;
129 CHAR *this_comment = NULL;
130 BOOLEAN endian;
131 BOOLEAN want_this_block = FALSE;
132
133 long this_filepos;
134 if ( ( this_filepos = ftell( fp ) ) == -1 ) {
135 XLALPrintError( "ERROR: ftell() failed for '%s'\n\n", fname );
138 fclose( fp );
140 }
141
142 if ( read_sft_header_from_fp( fp, &this_header, &this_version, &this_crc, &this_windowspec, &endian, &this_comment, &this_nsamples ) != 0 ) {
143 XLALPrintError( "ERROR: File-block '%s:%ld' is not a valid SFT!\n\n", fname, ftell( fp ) );
145 XLALFree( this_comment );
147 fclose( fp );
149 }
150
151 /* if merged-SFT: check consistency constraints */
152 if ( !mfirst_block ) {
153 if ( ! consistent_mSFT_header( mprev_header, mprev_version, mprev_nsamples, mprev_windowspec, this_header, this_version, this_nsamples, this_windowspec ) ) {
154 XLALPrintError( "ERROR: merged SFT-file '%s' contains inconsistent SFT-blocks!\n\n", fname );
155 XLALFree( this_comment );
158 fclose( fp );
160 }
161 } /* if !mfirst_block */
162
163 mprev_header = this_header;
164 mprev_version = this_version;
165 mprev_nsamples = this_nsamples;
166 mprev_windowspec = this_windowspec;
167
168 want_this_block = TRUE; /* default */
169 /* but does this SFT-block satisfy the user-constraints ? */
170 if ( constraints ) {
171 if ( constraints->detector ) {
172 if ( strncmp( constraints->detector, this_header.name, 2 ) ) {
173 want_this_block = FALSE;
174 }
175 }
176
177 if ( XLALCWGPSinRange( this_header.epoch, constraints->minStartTime, constraints->maxStartTime ) != 0 ) {
178 want_this_block = FALSE;
179 }
180
181 if ( constraints->timestamps && !timestamp_in_list( this_header.epoch, constraints->timestamps ) ) {
182 want_this_block = FALSE;
183 }
184
185 } /* if constraints */
186
187 if ( want_this_block ) {
188 numSFTs ++;
189
190 /* do we need to alloc more memory for the SFTs? */
191 if ( numSFTs > ret->length ) {
192 /* we realloc SFT-memory blockwise in order to
193 * improve speed in debug-mode (using LALMalloc/LALFree)
194 */
195 int len = ( ret->length + SFTFILEIO_REALLOC_BLOCKSIZE ) * sizeof( *( ret->data ) );
196 if ( ( ret->data = LALRealloc( ret->data, len ) ) == NULL ) {
197 XLALPrintError( "ERROR: SFT memory reallocation failed: nSFT:%d, len = %d\n", numSFTs, len );
200 XLALFree( this_comment );
201 fclose( fp );
203 }
204
205 /* properly initialize data-fields pointers to NULL to avoid SegV when Freeing */
206 for ( UINT4 j = 0; j < SFTFILEIO_REALLOC_BLOCKSIZE; j ++ ) {
207 memset( &( ret->data[ret->length + j] ), 0, sizeof( ret->data[0] ) );
208 }
209
211 } // if numSFTs > ret->length
212
213 SFTDescriptor *desc = &( ret->data[numSFTs - 1] );
214
215 desc->locator = XLALCalloc( 1, sizeof( *( desc->locator ) ) );
216 if ( desc->locator ) {
217 desc->locator->fname = XLALCalloc( 1, strlen( fname ) + 1 );
218 }
219 if ( ( desc->locator == NULL ) || ( desc->locator->fname == NULL ) ) {
220 XLALPrintError( "ERROR: XLALCalloc() failed\n" );
223 fclose( fp );
225 }
226 strcpy( desc->locator->fname, fname );
227 desc->locator->offset = this_filepos;
228
229 XLAL_CHECK_NULL( parse_sft_windowspec( this_windowspec, &desc->window_type, &desc->window_param ) == XLAL_SUCCESS, XLAL_EFUNC );
230
231 desc->header = this_header;
232 desc->comment = this_comment;
233 desc->numBins = this_nsamples;
234 desc->version = this_version;
235 desc->crc64 = this_crc;
236
237 } /* if want_this_block */
238 else {
239 XLALFree( this_comment );
240 }
241
242 mfirst_block = FALSE;
243
244 /* skip seeking if we know we would reach the end */
245 if ( ftell( fp ) + ( long )this_nsamples * 8 >= file_len ) {
246 break;
247 }
248
249 /* seek to end of SFT data-entries in file */
250 if ( fseek( fp, this_nsamples * 8, SEEK_CUR ) == -1 ) {
251 XLALPrintError( "ERROR: Failed to skip DATA field for SFT '%s': %s\n", fname, strerror( errno ) );
252 XLALFree( this_comment );
255 fclose( fp );
257 }
258
259 } /* while !feof */
260
261 fclose( fp );
262
263 } /* for i < numFiles */
264
265 /* free matched filenames */
267
268 /* now realloc SFT-vector (alloc'ed blockwise) to its *actual size* */
269 int len;
270 if ( ( ret->data = XLALRealloc( ret->data, len = numSFTs * sizeof( *( ret->data ) ) ) ) == NULL ) {
272 XLAL_ERROR_NULL( XLAL_ENOMEM, "XLALRecalloc ( %d ) failed.\n", len );
273 }
274 ret->length = numSFTs;
275
276 /* ----- final consistency-checks: ----- */
277
278 /* did we find all timestamps that lie within [minStartTime, maxStartTime)? */
279 if ( constraints && constraints->timestamps ) {
280 LIGOTimeGPSVector *ts = constraints->timestamps;
281
282 for ( UINT4 i = 0; i < ts->length; i ++ ) {
283 const LIGOTimeGPS *ts_i = &( ts->data[i] );
284 if ( XLALCWGPSinRange( *ts_i, constraints->minStartTime, constraints->maxStartTime ) == 0 ) {
285 UINT4 j;
286 for ( j = 0; j < ret->length; j ++ ) {
287 const LIGOTimeGPS *sft_i = &( ret->data[j].header.epoch );
288 if ( ( ts_i->gpsSeconds == sft_i->gpsSeconds ) && ( ts_i->gpsNanoSeconds == sft_i->gpsNanoSeconds ) ) {
289 break;
290 }
291 }
292 XLAL_CHECK_NULL( j < ret->length, XLAL_EFAILED,
293 "Timestamp %d : [%d, %d] did not find a matching SFT\n\n", ( i + 1 ), ts_i->gpsSeconds, ts_i->gpsNanoSeconds );
294 }
295 } // for i < ts->length
296
297 } /* if constraints->timestamps */
298
299 SFTtype XLAL_INIT_DECL( first_header );
300 /* have all matched SFTs identical dFreq values ? */
301 for ( UINT4 i = 0; i < ret->length; i ++ ) {
302 SFTtype this_header = ret->data[i].header;
303
304 if ( i == 0 ) {
305 first_header = this_header;
306 }
307
308 if ( this_header.deltaF != first_header.deltaF ) {
310 XLAL_ERROR_NULL( XLAL_EDATA, "Pattern '%s' matched SFTs with inconsistent deltaF: %.18g != %.18g!\n\n",
311 file_pattern, this_header.deltaF, first_header.deltaF );
312 }
313
314 } /* for i < numSFTs */
315
316
317 /* sort catalog in order of increasing GPS-time */
318 qsort( ( void * )ret->data, ret->length, sizeof( ret->data[0] ), compareSFTdesc );
319
320
321 /* return result catalog (=sft-vect and locator-vect) */
322 return ret;
323
324} /* XLALSFTdataFind() */
325
326
327/** Free an 'SFT-catalogue' */
328void
329XLALDestroySFTCatalog( SFTCatalog *catalog /**< the 'catalogue' to free */ )
330{
331 if ( catalog ) {
332
333 if ( catalog -> data ) {
334 UINT4 i;
335 for ( i = 0; i < catalog->length; i ++ ) {
336 SFTDescriptor *ptr = &( catalog->data[i] );
337 if ( ptr->locator ) {
338 if ( ptr->locator->fname ) {
339 XLALFree( ptr->locator->fname );
340 }
341 XLALFree( ptr->locator );
342 }
343 if ( ptr->comment ) {
344 XLALFree( ptr->comment );
345 }
346
347 /* this should not happen, but just in case: free data-entry in SFT-header */
348 if ( ptr->header.data ) {
349 XLALDestroyCOMPLEX8Sequence( ptr->header.data );
350 }
351 } /* for i < length */
352
353 catalog->length = 0;
354
355 XLALFree( catalog->data );
356
357 } /* if catalog->data */
358
359 XLALFree( catalog );
360
361 } /* if catalog */
362
363} /* XLALDestroySFTCatalog() */
364
365
366/**
367 * Return a MultiSFTCatalogView generated from an input SFTCatalog.
368 *
369 * The input catalog can describe SFTs from several IFOs in one vector,
370 * while the returned multi-Catalog view contains an array of single-IFO SFTCatalogs.
371 *
372 * NOTE: remember that this is only a multi-IFO "view" of the existing SFTCatalog,
373 * various allocated memory of the original catalog is only pointed to, not duplicated!
374 * This means one must not free the original catalog while this multi-view is still in use!
375 *
376 * NOTE2: the returned multi-IFO catalog is sorted alphabetically by detector-name
377 *
378 */
381{
382 XLAL_CHECK_NULL( catalog != NULL, XLAL_EINVAL );
383
384 UINT4 numSFTsTotal = catalog->length;
385
386 /* the number of ifos can be at most equal to numSFTsTotal */
387 /* each ifo name is 2 characters + \0 */
388 UINT4 numIFOsMax = 3; /* should be sufficient -- realloc used later in case required */
389 UINT4 numIFOsMaxNew; /* for memory allocation purposes */
390
391 CHAR **ifolist; /* list of ifo names */
392 XLAL_CHECK_NULL( ( ifolist = XLALCalloc( 1, numIFOsMax * sizeof( *ifolist ) ) ) != NULL, XLAL_ENOMEM );
393
394 UINT4 **sftLocationInCatalog; /* location of sfts in catalog for each ifo */
395 XLAL_CHECK_NULL( ( sftLocationInCatalog = XLALCalloc( 1, numIFOsMax * sizeof( *sftLocationInCatalog ) ) ) != NULL, XLAL_ENOMEM );
396
397 UINT4 *numSFTsPerIFO; /* number of sfts for each ifo 'X' */
398 XLAL_CHECK_NULL( ( numSFTsPerIFO = XLALCalloc( 1, numIFOsMax * sizeof( *numSFTsPerIFO ) ) ) != NULL, XLAL_ENOMEM );
399
400 for ( UINT4 X = 0; X < numIFOsMax; X++ ) {
401 XLAL_CHECK_NULL( ( ifolist[X] = XLALCalloc( 1, 3 * sizeof( *ifolist[X] ) ) ) != NULL, XLAL_ENOMEM );
402 XLAL_CHECK_NULL( ( sftLocationInCatalog[X] = XLALCalloc( 1, numSFTsTotal * sizeof( *sftLocationInCatalog[X] ) ) ) != NULL, XLAL_ENOMEM );
403 } // for k < numIFOsMax
404
405 UINT4 numIFOs = 0; /* number of ifos found so far */
406
407 /* loop over sfts in catalog and look at ifo names and
408 * find number of different ifos and number of sfts for each ifo
409 * Also find location of sft in catalog */
410 for ( UINT4 k = 0; k < numSFTsTotal; k++ ) {
411 CHAR name[3];
412 memcpy( name, catalog->data[k].header.name, 3 * sizeof( CHAR ) );
413
414 UINT4 X;
415 /* go through list of ifos till a match is found or list is exhausted */
416 for ( X = 0; ( X < numIFOs ) && strncmp( name, ifolist[X], 3 ); X++ )
417 ;
418
419 if ( X < numIFOs ) {
420 /* match found with X-th existing ifo */
421 sftLocationInCatalog[X][ numSFTsPerIFO[X] ] = k;
422 numSFTsPerIFO[X] ++;
423 } else {
424 /* add ifo to list of ifos */
425
426 /* first check if number of ifos is larger than numIFOsmax */
427 /* and realloc if necessary */
428 if ( numIFOs >= numIFOsMax ) {
429 numIFOsMaxNew = numIFOsMax + 3;
430 XLAL_CHECK_NULL( ( ifolist = XLALRealloc( ifolist, numIFOsMaxNew * sizeof( *ifolist ) ) ) != NULL, XLAL_ENOMEM );
431
432 XLAL_CHECK_NULL( ( sftLocationInCatalog = XLALRealloc( sftLocationInCatalog, numIFOsMaxNew * sizeof( *sftLocationInCatalog ) ) ) != NULL, XLAL_ENOMEM );
433
434 XLAL_CHECK_NULL( ( numSFTsPerIFO = XLALRealloc( numSFTsPerIFO, numIFOsMaxNew * sizeof( *numSFTsPerIFO ) ) ) != NULL, XLAL_ENOMEM );
435
436 for ( UINT4 Y = numIFOsMax; Y < numIFOsMaxNew; Y++ ) {
437 XLAL_CHECK_NULL( ( ifolist[Y] = XLALCalloc( 1, 3 * sizeof( *ifolist[Y] ) ) ) != NULL, XLAL_ENOMEM );
438 XLAL_CHECK_NULL( ( sftLocationInCatalog[Y] = XLALCalloc( 1, numSFTsTotal * sizeof( *sftLocationInCatalog[Y] ) ) ) != NULL, XLAL_ENOMEM );
439 } // endfor X=numIFOsMax < numIFOsMaxNew
440
441 numIFOsMax = numIFOsMaxNew; // reset numIFOsMax
442
443 } /* endif ( numIFOs >= numIFOsMax) -- end of realloc */
444
445 strncpy( ifolist[numIFOs], name, 3 );
446 sftLocationInCatalog[X][0] = k;
447 numSFTsPerIFO[numIFOs] = 1;
448 numIFOs ++;
449
450 } /* else part of if ( X < numIFOs ) */
451
452 } /* for ( k = 0; k < numSFTsTotal; k++) */
453
454 /* now we can create the return multi-SFT catalog view */
456
457 XLAL_CHECK_NULL( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_ENOMEM );
458 XLAL_CHECK_NULL( ( ret->data = XLALCalloc( numIFOs, sizeof( *ret->data ) ) ) != NULL, XLAL_ENOMEM );
459 ret->length = numIFOs;
460
461 for ( UINT4 X = 0; X < numIFOs; X++ ) {
462 ret->data[X].length = numSFTsPerIFO[X];
463
464 XLAL_CHECK_NULL( ( ret->data[X].data = XLALCalloc( numSFTsPerIFO[X], sizeof( *( ret->data[X].data ) ) ) ) != NULL, XLAL_ENOMEM );
465
466 for ( UINT4 k = 0; k < numSFTsPerIFO[X]; k++ ) {
467 UINT4 location = sftLocationInCatalog[X][k];
468 ret->data[X].data[k] = catalog->data[location]; // struct copy, but keep all original pointers in struct!
469 } // for k < numSFTsPerIFO[X]
470
471 } // for X < numIFOs
472
473 // free all temporary internal memory
474 for ( UINT4 X = 0; X < numIFOsMax; X ++ ) {
475 XLALFree( ifolist[X] );
476 XLALFree( sftLocationInCatalog[X] );
477 }
478 XLALFree( ifolist );
479 XLALFree( sftLocationInCatalog );
480 XLALFree( numSFTsPerIFO );
481
482 // sort final multi-catalog view alphabetically by detector name
483 qsort( ret->data, ret->length, sizeof( ret->data[0] ), compareDetNameCatalogs );
484
485 return ret;
486
487} // XLALGetMultiSFTCatalogView()
488
489
490/**
491 * Destroys a MultiSFTCatalogView, without freeing the original
492 * catalog that the 'view' was referring to, which
493 * must be destroyed separately using XLALDestroySFTCatalog().
494 */
495void
497{
498 if ( !multiView ) {
499 return;
500 }
501
502 for ( UINT4 X = 0; X < multiView->length; X ++ ) {
503 XLALFree( multiView->data[X].data );
504 }
505
506 XLALFree( multiView->data );
507 XLALFree( multiView );
508
509 return;
510
511} // XLALDestroyMultiSFTCatalog()
512
513
514/**
515 * This function reads in the SFTs in the catalog and validates their CRC64 checksums.
516 * The result of the validation is returned in '*crc_check'. The function itself returns
517 * XLAL_SUCCESS if the operation suceeds (even if the checksums fail to validate),
518 * and XLAL_FAILURE otherwise.
519 *
520 * \note: because this function has to read the complete SFT data into memory it is
521 * potentially slow and memory-intensive.
522 */
523int
525 BOOLEAN *crc_check, /**< set to true if checksum validation passes */
526 SFTCatalog *catalog /**< catalog of SFTs to check */
527)
528{
529
530 XLAL_CHECK( crc_check != NULL, XLAL_EINVAL );
531 XLAL_CHECK( catalog != NULL, XLAL_EINVAL );
532
533 /* CRC checks are assumed to pass until one fails */
534 *crc_check = 1;
535
536 /* step through SFTs and check CRC64 */
537 for ( UINT4 i = 0; i < catalog->length; i ++ ) {
538 FILE *fp;
539 if ( ( fp = fopen_SFTLocator( catalog->data[i].locator ) ) == NULL ) {
540 XLALPrintError( "Failed to open locator '%s'\n",
541 XLALshowSFTLocator( catalog->data[i].locator ) );
542 return XLAL_FAILURE;
543 }
544 if ( !( has_valid_crc64( fp ) != 0 ) ) {
545 XLALPrintError( "CRC64 checksum failure for SFT '%s'\n",
546 XLALshowSFTLocator( catalog->data[i].locator ) );
547 *crc_check = 0;
548 fclose( fp );
549 return XLAL_SUCCESS;
550 }
551 fclose( fp );
552 } /* for i < numSFTs */
553
554 return XLAL_SUCCESS;
555
556} /* XLALCheckCRCSFTCatalog() */
557
558
559/**
560 * Return a sorted string vector listing the unique IFOs in the given catalog.
561 */
563{
564 XLAL_CHECK_NULL( catalog != NULL, XLAL_EFAULT );
565 LALStringVector *ifos = NULL;
566 for ( UINT4 k = 0; k < catalog->length; ++k ) {
567 char *name = XLALGetChannelPrefix( catalog->data[k].header.name );
568 if ( XLALFindStringInVector( name, ifos ) < 0 ) {
570 XLAL_CHECK_NULL( ifos != NULL, XLAL_EFUNC );
571 }
572 XLALFree( name );
573 }
575 return ifos;
576} // XLALListIFOsInCatalog()
577
578
579/**
580 * Count the number of the unique IFOs in the given catalog.
581 */
583{
584 XLAL_CHECK( catalog != NULL, XLAL_EFAULT );
586 XLAL_CHECK( ifos != NULL, XLAL_EFUNC );
587 UINT4 nifos = ifos->length;
589 return nifos;
590} // XLALCountIFOsInCatalog()
591
592
593/**
594 * Mostly for *debugging* purposes: provide a user-API to allow inspecting the SFT-locator
595 * [which is an OPAQUE entry in the SFTCatalog!]
596 *
597 * NOTE: this returns a STATIC string, so don't try to FREE it, and make a copy if you need
598 * to keep it beyond one call of this function!
599 *
600 */
601const CHAR *
603{
604 static CHAR ret[512];
605
606 if ( !locator ) {
607 return NULL;
608 }
609
610 snprintf( ret, sizeof( ret ), "%s : %ld", locator->fname, locator->offset );
611 XLAL_LAST_ELEM( ret ) = 0;
612
613 return ret;
614
615} /* XLALshowSFTLocator() */
616
617
618///
619/// Set a SFT catalog 'slice' to a timeslice of a larger SFT catalog 'catalog', with entries
620/// restricted to the interval ['minStartGPS','maxStartGPS') according to XLALCWGPSinRange().
621/// The catalog 'slice' just points to existing data in 'catalog', and therefore should not
622/// be deallocated.
623///
625 SFTCatalog *slice, ///< [out] Timeslice of SFT catalog
626 const SFTCatalog *catalog, ///< [in] SFT catalog
627 const LIGOTimeGPS *minStartGPS, ///< [in] Minimum starting GPS time
628 const LIGOTimeGPS *maxStartGPS ///< [in] Maximum starting GPS time
629)
630{
631
632 // Check input
633 XLAL_CHECK( slice != NULL, XLAL_EFAULT );
634 XLAL_CHECK( catalog != NULL, XLAL_EFAULT );
635 XLAL_CHECK( minStartGPS != NULL && maxStartGPS != NULL, XLAL_EFAULT );
636 XLAL_CHECK( catalog->length > 0, XLAL_EINVAL );
637 XLAL_CHECK( XLALGPSCmp( minStartGPS, maxStartGPS ) < 1, XLAL_EINVAL, "minStartGPS (%"LAL_GPS_FORMAT") is greater than maxStartGPS (%"LAL_GPS_FORMAT")\n",
638 LAL_GPS_PRINT( *minStartGPS ), LAL_GPS_PRINT( *maxStartGPS ) );
639
640 // get a temporary timestamps vector with SFT epochs so we can call XLALFindTimesliceBounds()
642 timestamps.length = catalog->length;
644 for ( UINT4 i = 0; i < timestamps.length; i ++ ) {
645 timestamps.data[i] = catalog->data[i].header.epoch;
646 }
647
648 UINT4 iStart, iEnd;
649 XLAL_CHECK( XLALFindTimesliceBounds( &iStart, &iEnd, &timestamps, minStartGPS, maxStartGPS ) == XLAL_SUCCESS, XLAL_EFUNC );
651
652 // Initialise timeslice of SFT catalog
653 XLAL_INIT_MEM( *slice );
654
655 // If not empty: set timeslice of SFT catalog
656 if ( iStart <= iEnd ) {
657 slice->length = iEnd - iStart + 1;
658 slice->data = &catalog->data[iStart];
659 }
660
661 return XLAL_SUCCESS;
662
663} // XLALSFTCatalogTimeslice()
664
665
666//
667// Like XLALSFTCatalogTimeslice, but actually returning the resulting SFTCatalog
668// so that memory can be properly freed whenever using SWIG bindings.
669//
671 const SFTCatalog *catalog, ///< [in] SFT catalog
672 const LIGOTimeGPS *minStartGPS, ///< [in] Minimum starting GPS time
673 const LIGOTimeGPS *maxStartGPS ///< [in] Maximum starting GPS time
674)
675{
676
677 // Allocate the output SFTCatalog
678 SFTCatalog *slice = NULL;
679 XLAL_CHECK_NULL( ( slice = LALCalloc( 1, sizeof( *slice ) ) ) != NULL, XLAL_ENOMEM );
680
681 XLAL_CHECK_NULL( XLALSFTCatalogTimeslice( slice, catalog, minStartGPS, maxStartGPS ) == XLAL_SUCCESS, XLAL_EFUNC );
682
683 return slice;
684
685} // XLALReturnSFTCatalogTimeslice()
686
687
688/**
689 * Create a 'fake' SFT catalog which contains only detector and timestamp information.
690 */
692XLALAddToFakeSFTCatalog( SFTCatalog *catalog, /**< [in] SFT catalog; if NULL, a new catalog is created */
693 const CHAR *detector, /**< [in] Name of detector to set fake catalog entries to */
694 const LIGOTimeGPSVector *timestamps /**< [in] Timestamps of each fake catalog entry */
695 )
696{
697
698 // Check input
703
704 // Get channel prefix
707
708 // If catalog is NULL, create a new fake catalog
709 if ( catalog == NULL ) {
710 catalog = XLALCalloc( 1, sizeof( *catalog ) );
711 XLAL_CHECK_NULL( catalog != NULL, XLAL_ENOMEM );
712 }
713
714 // Extend catalog to add new timestamps
715 const UINT4 new_length = catalog->length + timestamps->length;
716 catalog->data = XLALRealloc( catalog->data, new_length * sizeof( catalog->data[0] ) );
717 XLAL_CHECK_NULL( catalog->data != NULL, XLAL_ENOMEM );
718
719 // Fill out new SFT descriptors with channel name and timestamps info
720 for ( UINT4 i = 0; i < timestamps->length; ++i ) {
721 SFTDescriptor *desc = &catalog->data[catalog->length + i];
722 memset( desc, 0, sizeof( *desc ) );
723 strncpy( desc->header.name, channel, 2 );
724 desc->window_type = "unknown";
725 desc->header.epoch = timestamps->data[i];
726 desc->header.deltaF = 1.0 / timestamps->deltaT;
727 desc->header.sampleUnits = lalDimensionlessUnit;
728 desc->version = MAX_SFT_VERSION;
729 }
730
731 // Set new catalog length
732 catalog->length = new_length;
733
734 // Sort catalog
735 qsort( ( void * )catalog->data, catalog->length, sizeof( catalog->data[0] ), compareSFTdesc );
736
737 // Cleanup
738 XLALFree( channel );
739
740 return catalog;
741
742} /* XLALAddToFakeSFTCatalog() */
743
744
745/**
746 * Multi-detector and multi-timestamp wrapper of XLALAddToFakeSFTCatalog().
747 */
749XLALMultiAddToFakeSFTCatalog( SFTCatalog *catalog, /**< [in] SFT catalog; if NULL, a new catalog is created */
750 const LALStringVector *detectors, /**< [in] Detector names to set fake catalog entries to */
751 const MultiLIGOTimeGPSVector *timestamps /**< [in] Timestamps for each detector of each fake catalog entry */
752 )
753{
754 // Check input
756 XLAL_CHECK_NULL( detectors->length > 0, XLAL_EINVAL );
757 XLAL_CHECK_NULL( detectors->data != NULL, XLAL_EFAULT );
761
762 // Loop over detectors, calling XLALAddToFakeSFTCatalog()
763 for ( UINT4 X = 0; X < detectors->length; ++X ) {
764 catalog = XLALAddToFakeSFTCatalog( catalog, detectors->data[X], timestamps->data[X] );
765 XLAL_CHECK_NULL( catalog != NULL, XLAL_EFUNC );
766 }
767
768 return catalog;
769
770} /* XLALMultiAddToFakeSFTCatalog() */
771
772
773/* portable file-len function */
774static long get_file_len( FILE *fp )
775{
776#ifdef _WIN32
777
778 long save_fp;
779 long len;
780
781 if ( ( save_fp = ftell( fp ) ) == -1 ) {
782 return 0;
783 }
784
785 if ( fseek( fp, 0, SEEK_END ) == -1 ) {
786 return 0;
787 }
788
789 len = ftell( fp );
790
791 if ( fseek( fp, save_fp, SEEK_SET ) == -1 ) {
792 return 0;
793 }
794
795 return len;
796
797#else
798
799 struct stat st;
800
801 if ( fstat( fileno( fp ), &st ) ) {
802 return 0;
803 }
804
805 return st.st_size;
806
807#endif
808} /* get_file_len() */
809
810
811/* check consistency constraints for SFT-blocks within a merged SFT-file, see \cite SFT-spec */
812static BOOLEAN
813consistent_mSFT_header( SFTtype header1, UINT4 version1, UINT4 nsamples1, UINT2 windowspec1, SFTtype header2, UINT4 version2, UINT4 nsamples2, UINT2 windowspec2 )
814{
815 /* 1) identical detector */
816 if ( ( header1.name[0] != header2.name[0] ) || ( header1.name[1] != header2.name[1] ) ) {
817 XLALPrintError( "\nInvalid merged SFT: non-identical detectors\n\n" );
818 return FALSE;
819 }
820
821 /* 2) identical version-number */
822 if ( version1 != version2 ) {
823 XLALPrintError( "\nInvalid merged SFT: non-identical version-numbers\n\n" );
824 return FALSE;
825 }
826
827 /* 3) increasing GPS-times */
828 if ( GPS2REAL8( header1.epoch ) >= GPS2REAL8( header2.epoch ) ) {
829 XLALPrintError( "\nInvalid merged SFT: non-increasing GPS epochs \n\n" );
830 return FALSE;
831 }
832
833 /* 4) identical tbase */
834 if ( header1.deltaF != header2.deltaF ) {
835 XLALPrintError( "\nInvalid merged SFT: non-identical time baselines\n\n" );
836 return FALSE;
837 }
838
839 /* 5) identical start-frequency */
840 if ( header1.f0 != header2.f0 ) {
841 XLALPrintError( "\nInvalid merged SFT: non-identical start-frequencies\n\n" );
842 return FALSE;
843 }
844
845 /* 6) identical number of frequency-bins */
846 if ( nsamples1 != nsamples2 ) {
847 XLALPrintError( "\nInvalid merged SFT: non-identical number of frequency-bins\n\n" );
848 return FALSE;
849 }
850
851 /* 7) identical window specifications */
852 if ( windowspec1 != windowspec2 ) {
853 XLALPrintError( "\nInvalid merged SFT: non-identical window specifications\n\n" );
854 return FALSE;
855 }
856
857 return TRUE;
858
859} /* consistent_mSFT_header() */
860
861
862static BOOLEAN
864{
865 UINT4 i;
866 LIGOTimeGPS *el;
867
868 if ( !list ) {
869 return FALSE;
870 }
871
872 el = &( list->data[0] );
873 for ( i = 0; i < list->length; i++, el++ ) {
874 if ( ( timestamp.gpsSeconds == el->gpsSeconds ) && ( timestamp.gpsNanoSeconds == el->gpsNanoSeconds ) ) {
875 return TRUE;
876 }
877 } /* for i < length */
878
879 return FALSE;
880
881} /* timestamp_in_list() */
882
883/// @}
#define GPS2REAL8(gps)
convert GPS-time to REAL8
int j
ProcessParamsTable * ptr
int k
#define LALRealloc(p, n)
#define LALCalloc(m, n)
Internal SFT types and functions.
#define MAX_SFT_VERSION
Definition: SFTinternal.h:54
#define SFTFILEIO_REALLOC_BLOCKSIZE
size of blocks allocated for SFT data.
Definition: SFTinternal.h:68
const char * name
Definition: SearchTiming.c:93
LIGOTimeGPSVector * timestamps
#define LAL_GPS_FORMAT
#define LAL_GPS_PRINT(gps)
unsigned char BOOLEAN
#define XLAL_INIT_MEM(x)
uint64_t UINT8
double REAL8
#define XLAL_LAST_ELEM(x)
#define XLAL_INIT_DECL(var,...)
uint16_t UINT2
char CHAR
uint32_t UINT4
int32_t INT4
void * XLALCalloc(size_t m, size_t n)
void * XLALRealloc(void *p, size_t n)
void XLALFree(void *p)
int parse_sft_windowspec(const UINT2 windowspec, const char **window_type, REAL8 *window_param)
Parse an SFT 2-byte 'windowspec' into a window name 'window_type' and possible parameter 'window_para...
Definition: SFTnaming.c:752
static BOOLEAN consistent_mSFT_header(SFTtype header1, UINT4 version1, UINT4 nsamples1, UINT2 windowspec1, SFTtype header2, UINT4 version2, UINT4 nsamples2, UINT2 windowspec2)
Definition: SFTcatalog.c:813
void XLALDestroySFTCatalog(SFTCatalog *catalog)
Free an 'SFT-catalogue'.
Definition: SFTcatalog.c:329
void XLALDestroyMultiSFTCatalogView(MultiSFTCatalogView *multiView)
Destroys a MultiSFTCatalogView, without freeing the original catalog that the 'view' was referring to...
Definition: SFTcatalog.c:496
CHAR * XLALGetChannelPrefix(const CHAR *name)
Find the valid CW detector prefix.
Definition: SFTnaming.c:203
SFTCatalog * XLALMultiAddToFakeSFTCatalog(SFTCatalog *catalog, const LALStringVector *detectors, const MultiLIGOTimeGPSVector *timestamps)
Multi-detector and multi-timestamp wrapper of XLALAddToFakeSFTCatalog().
Definition: SFTcatalog.c:749
SFTCatalog * XLALReturnSFTCatalogTimeslice(const SFTCatalog *catalog, const LIGOTimeGPS *minStartGPS, const LIGOTimeGPS *maxStartGPS)
Definition: SFTcatalog.c:670
int XLALCheckCRCSFTCatalog(BOOLEAN *crc_check, SFTCatalog *catalog)
This function reads in the SFTs in the catalog and validates their CRC64 checksums.
Definition: SFTcatalog.c:524
MultiSFTCatalogView * XLALGetMultiSFTCatalogView(const SFTCatalog *catalog)
Return a MultiSFTCatalogView generated from an input SFTCatalog.
Definition: SFTcatalog.c:380
int XLALFindTimesliceBounds(UINT4 *iStart, UINT4 *iEnd, const LIGOTimeGPSVector *timestamps, const LIGOTimeGPS *minStartGPS, const LIGOTimeGPS *maxStartGPS)
LALStringVector * XLALListIFOsInCatalog(const SFTCatalog *catalog)
Return a sorted string vector listing the unique IFOs in the given catalog.
Definition: SFTcatalog.c:562
LALStringVector * XLALFindFiles(const CHAR *globstring)
Returns a list of filenames matching the input argument, which may be one of the following:
Definition: FindFiles.c:61
static long get_file_len(FILE *fp)
Definition: SFTcatalog.c:774
SFTCatalog * XLALAddToFakeSFTCatalog(SFTCatalog *catalog, const CHAR *detector, const LIGOTimeGPSVector *timestamps)
Create a 'fake' SFT catalog which contains only detector and timestamp information.
Definition: SFTcatalog.c:692
FILE * fopen_SFTLocator(const struct tagSFTLocator *locator)
Open an "SFT" defined by the SFT-locator, return a FILE-pointer to the beginning of this SFT.
Definition: SFTfileIO.c:882
int read_sft_header_from_fp(FILE *fp, SFTtype *header, UINT4 *version, UINT8 *crc64, UINT2 *SFTwindowspec, BOOLEAN *swapEndian, CHAR **SFTcomment, UINT4 *numBins)
Definition: SFTfileIO.c:992
SFTCatalog * XLALSFTdataFind(const CHAR *file_pattern, const SFTConstraints *constraints)
Find the list of SFTs matching the file_pattern and satisfying the given constraints,...
Definition: SFTcatalog.c:71
const CHAR * XLALshowSFTLocator(const struct tagSFTLocator *locator)
Mostly for debugging purposes: provide a user-API to allow inspecting the SFT-locator [which is an OP...
Definition: SFTcatalog.c:602
int XLALCWGPSinRange(const LIGOTimeGPS gps, const LIGOTimeGPS *minGPS, const LIGOTimeGPS *maxGPS)
Defines the official CW convention for whether a GPS time is 'within' a given range,...
Definition: SFTtypes.c:52
int compareDetNameCatalogs(const void *ptr1, const void *ptr2)
Definition: SFTtypes.c:1208
BOOLEAN has_valid_crc64(FILE *fp)
Check the SFT-block starting at fp for valid crc64 checksum.
Definition: SFTfileIO.c:1409
int XLALSFTCatalogTimeslice(SFTCatalog *slice, const SFTCatalog *catalog, const LIGOTimeGPS *minStartGPS, const LIGOTimeGPS *maxStartGPS)
Set a SFT catalog 'slice' to a timeslice of a larger SFT catalog 'catalog', with entries restricted t...
Definition: SFTcatalog.c:624
int compareSFTdesc(const void *ptr1, const void *ptr2)
Definition: SFTtypes.c:1161
static BOOLEAN timestamp_in_list(LIGOTimeGPS timestamp, LIGOTimeGPSVector *list)
Definition: SFTcatalog.c:863
INT4 XLALCountIFOsInCatalog(const SFTCatalog *catalog)
Count the number of the unique IFOs in the given catalog.
Definition: SFTcatalog.c:582
BOOLEAN XLALIsValidCWDetector(const CHAR *name)
Determine if 'name' is a valid detector name or prefix.
Definition: SFTnaming.c:188
void XLALDestroyCOMPLEX8Sequence(COMPLEX8Sequence *sequence)
void XLALDestroyStringVector(LALStringVector *vect)
LALStringVector * XLALAppendString2Vector(LALStringVector *vect, const CHAR *string)
int XLALSortStringVector(LALStringVector *strings)
INT4 XLALFindStringInVector(const char *needle, const LALStringVector *haystack)
const LALUnit lalDimensionlessUnit
#define XLAL_ERROR_NULL(...)
#define XLAL_CHECK(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_CHECK_NULL(assertion,...)
XLAL_ENOMEM
XLAL_EDATA
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
XLAL_EIO
XLAL_EINVAL
XLAL_EFAILED
XLAL_FAILURE
int XLALGPSCmp(const LIGOTimeGPS *t0, const LIGOTimeGPS *t1)
float data[BLOCKSIZE]
Definition: hwinject.c:360
nifos
ifos
fnames
desc
ts
#define TRUE
#define FALSE
LALDetector detectors[LAL_NUM_DETECTORS]
CHAR name[LALNameLength]
INT4 gpsNanoSeconds
A vector of 'timestamps' of type LIGOTimeGPS.
Definition: SFTfileIO.h:188
REAL8 deltaT
'length' of each timestamp (e.g.
Definition: SFTfileIO.h:194
LIGOTimeGPS * data
array of timestamps
Definition: SFTfileIO.h:193
UINT4 length
number of timestamps
Definition: SFTfileIO.h:192
A collection of (multi-IFO) LIGOTimeGPSVector time-stamps vectors.
Definition: SFTfileIO.h:198
A multi-SFT-catalogue "view": a multi-IFO vector of SFT-catalogs.
Definition: SFTfileIO.h:255
SFTCatalog * data
array of SFT-catalog pointers
Definition: SFTfileIO.h:260
UINT4 length
number of detectors
Definition: SFTfileIO.h:259
An "SFT-catalogue": a vector of SFTdescriptors, as returned by XLALSFTdataFind()
Definition: SFTfileIO.h:238
SFTDescriptor * data
array of data-entries describing matched SFTs
Definition: SFTfileIO.h:243
UINT4 length
number of SFTs in catalog
Definition: SFTfileIO.h:242
'Constraints' for SFT-matching: which detector, within which time-stretch and which timestamps exactl...
Definition: SFTfileIO.h:212
CHAR * detector
2-char channel-prefix describing the detector (eg 'H1', 'H2', 'L1', 'G1' etc)
Definition: SFTfileIO.h:213
LIGOTimeGPSVector * timestamps
list of timestamps
Definition: SFTfileIO.h:216
LIGOTimeGPS * maxStartTime
only include SFTs whose epoch is < maxStartTime
Definition: SFTfileIO.h:215
LIGOTimeGPS * minStartTime
only include SFTs whose epoch is >= minStartTime
Definition: SFTfileIO.h:214
A 'descriptor' of an SFT: basically containing the header-info plus an opaque description of where ex...
Definition: SFTfileIO.h:226
SFTtype header
SFT-header info.
Definition: SFTfileIO.h:228
struct tagSFTLocator * locator
internal description of where to find this SFT [opaque!]
Definition: SFTfileIO.h:227