LALPulsar  6.1.0.1-b72065a
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 
37 static long get_file_len( FILE *fp );
38 
39 static BOOLEAN consistent_mSFT_header( SFTtype header1, UINT4 version1, UINT4 nsamples1, UINT2 windowspec1, SFTtype header2, UINT4 version2, UINT4 nsamples2, UINT2 windowspec2 );
40 static BOOLEAN timestamp_in_list( LIGOTimeGPS timestamp, LIGOTimeGPSVector *list );
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  */
70 SFTCatalog *
71 XLALSFTdataFind( 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 );
109  XLALDestroySFTCatalog( ret );
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 );
117  XLALDestroySFTCatalog( ret );
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 );
137  XLALDestroySFTCatalog( ret );
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 );
146  XLALDestroySFTCatalog( ret );
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 );
157  XLALDestroySFTCatalog( ret );
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 );
199  XLALDestroySFTCatalog( ret );
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" );
222  XLALDestroySFTCatalog( ret );
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 );
254  XLALDestroySFTCatalog( ret );
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 ) {
271  XLALDestroySFTCatalog( ret );
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 ) {
309  XLALDestroySFTCatalog( ret );
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' */
328 void
329 XLALDestroySFTCatalog( 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 */
455  MultiSFTCatalogView *ret;
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  */
495 void
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  */
523 int
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  */
601 const CHAR *
602 XLALshowSFTLocator( const struct tagSFTLocator *locator )
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;
643  XLAL_CHECK( ( timestamps.data = XLALCalloc( timestamps.length, sizeof( timestamps.data[0] ) ) ) != NULL, XLAL_ENOMEM );
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  */
691 SFTCatalog *
692 XLALAddToFakeSFTCatalog( 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
706  XLAL_CHECK_NULL( channel != NULL, XLAL_EFUNC );
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  */
748 SFTCatalog *
749 XLALMultiAddToFakeSFTCatalog( 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 */
774 static 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 */
812 static BOOLEAN
813 consistent_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 
862 static 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 * XLALFindFiles(const CHAR *globstring)
Returns a list of filenames matching the input argument, which may be one of the following:
Definition: FindFiles.c:61
LALStringVector * XLALListIFOsInCatalog(const SFTCatalog *catalog)
Return a sorted string vector listing the unique IFOs in the given catalog.
Definition: SFTcatalog.c:562
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
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
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 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)
LALStringVector * XLALAppendString2Vector(LALStringVector *vect, const CHAR *string)
void XLALDestroyStringVector(LALStringVector *vect)
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)
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
CHAR * fname
Definition: SFTinternal.h:90