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
SFTtimestamps.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020 David Keitel
3 * Copyright (C) 2014, 2015 Evan Goetz
4 * Copyright (C) 2014 Matthew Pitkin
5 * Copyright (C) 2010, 2012--2017, 2020, 2022 Karl Wette
6 * Copyright (C) 2010 Chris Messenger
7 * Copyright (C) 2009, 2011, 2015 Adam Mercer
8 * Copyright (C) 2004--2006, 2009-- 2011, 2013, 2015--2018 Reinhard Prix
9 * Copyright (C) 2004--2006 Bernd Machenschalk
10 * Copyright (C) 2004, 2005 Alicia Sintes
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with with program; see the file COPYING. If not, write to the
24 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 * MA 02110-1301 USA
26 */
27
28/*---------- includes ----------*/
29
30#include <lal/ConfigFile.h>
31
32#include "SFTinternal.h"
33
34/*---------- global variables ----------*/
35
36// XLALReadSegmentsFromFile(): applications which still must support
37// the deprecated 4-column format should set this variable to non-zero
39
40/*========== function definitions ==========*/
41
42/// \addtogroup SFTfileIO_h
43/// @{
44
45/** Allocate a LIGOTimeGPSVector */
48{
49 int len;
50 LIGOTimeGPSVector *out = XLALCalloc( 1, len = sizeof( LIGOTimeGPSVector ) );
51 if ( out == NULL ) {
52 XLAL_ERROR_NULL( XLAL_ENOMEM, "Failed to allocate XLALCalloc(1,%d)\n", len );
53 }
54
55 out->length = length;
56 out->data = XLALCalloc( 1, len = length * sizeof( LIGOTimeGPS ) );
57 if ( out->data == NULL ) {
58 XLALFree( out );
59 XLAL_ERROR_NULL( XLAL_ENOMEM, "Failed to allocate XLALCalloc(1,%d)\n", len );
60 }
61
62 return out;
63
64} /* XLALCreateTimestampVector() */
65
66
67/** De-allocate a LIGOTimeGPSVector */
68void
70{
71 if ( !vect ) {
72 return;
73 }
74
75 XLALFree( vect->data );
76 XLALFree( vect );
77
78 return;
79
80} /* XLALDestroyTimestampVector() */
81
82
83/** Resize a LIGOTimeGPSVector */
86{
87 if ( ! vector ) {
88 return XLALCreateTimestampVector( length );
89 }
90 if ( ! length ) {
92 return NULL;
93 }
94
95 vector->data = XLALRealloc( vector->data, length * sizeof( LIGOTimeGPS ) );
96
97 if ( ! vector->data ) {
98 vector->length = 0;
100 }
101 vector->length = length;
102 return vector;
103}
104
105
106/**
107 * Simple creator function for MultiLIGOTimeGPSVector with numDetectors entries
108 */
111{
113
114 if ( ( ret = XLALMalloc( sizeof( *ret ) ) ) == NULL ) {
115 XLALPrintError( "%s: XLALMalloc(%zu) failed.\n", __func__, sizeof( *ret ) );
117 }
118
119 ret->length = numDetectors;
120 if ( ( ret->data = XLALCalloc( numDetectors, sizeof( *ret->data ) ) ) == NULL ) {
121 XLALPrintError( "%s: XLALCalloc(%d, %zu) failed.\n", __func__, numDetectors, sizeof( *ret->data ) );
122 XLALFree( ret );
124 }
125
126 return ret;
127
128} /* XLALCreateMultiLIGOTimeGPSVector() */
129
130
131/**
132 * Destroy a MultiLIGOTimeGPSVector timestamps vector
133 */
134void
136{
137 UINT4 numIFOs, X;
138
139 if ( !multiTS ) {
140 return;
141 }
142
143 numIFOs = multiTS->length;
144 for ( X = 0; X < numIFOs; X ++ ) {
146 }
147
148 XLALFree( multiTS->data );
149 XLALFree( multiTS );
150
151 return;
152
153} /* XLALDestroyMultiTimestamps() */
154
155
156// Find index values of first and last timestamp within given timeslice range XLALCWGPSinRange(minStartGPS, maxStartGPS)
157int
159 UINT4 *iEnd,
161 const LIGOTimeGPS *minStartGPS,
162 const LIGOTimeGPS *maxStartGPS
163 )
164{
165 XLAL_CHECK( ( iStart != NULL ) && ( iEnd != NULL ) && ( timestamps != NULL ) && ( minStartGPS != NULL ) && ( maxStartGPS != NULL ), XLAL_EINVAL );
166 XLAL_CHECK( XLALGPSCmp( minStartGPS, maxStartGPS ) < 1, XLAL_EINVAL, "minStartGPS (%"LAL_GPS_FORMAT") is greater than maxStartGPS (%"LAL_GPS_FORMAT")\n",
167 LAL_GPS_PRINT( *minStartGPS ), LAL_GPS_PRINT( *maxStartGPS ) );
168
170 ( *iStart ) = 0;
171 ( *iEnd ) = N - 1;
172
173 // check if there's any timestamps falling into the requested timeslice at all
174 if ( ( ( XLALCWGPSinRange( timestamps->data[0], minStartGPS, maxStartGPS ) == 1 ) || ( XLALCWGPSinRange( timestamps->data[N - 1], minStartGPS, maxStartGPS ) == -1 ) ) ) {
175 // if not: set an emtpy index interval in this case
176 ( *iStart ) = 1;
177 ( *iEnd ) = 0;
178 XLALPrintInfo( "Returning empty timeslice: Timestamps span [%"LAL_GPS_FORMAT", %"LAL_GPS_FORMAT "]"
179 " has no overlap with requested timeslice range [%"LAL_GPS_FORMAT", %"LAL_GPS_FORMAT").\n",
181 LAL_GPS_PRINT( *minStartGPS ), LAL_GPS_PRINT( *maxStartGPS )
182 );
183 return XLAL_SUCCESS;
184 }
185
186 while ( ( *iStart ) <= ( *iEnd ) && XLALCWGPSinRange( timestamps->data[( *iStart ) ], minStartGPS, maxStartGPS ) < 0 ) {
187 ++ ( *iStart );
188 }
189 while ( ( *iStart ) <= ( *iEnd ) && XLALCWGPSinRange( timestamps->data[( *iEnd ) ], minStartGPS, maxStartGPS ) > 0 ) {
190 -- ( *iEnd );
191 }
192 // note: *iStart >=0, *iEnd >= 0 is now guaranteed due to previous range overlap-check
193
194 // check if there is any timestamps found witin the interval, ie if iStart <= iEnd
195 if ( ( *iStart ) > ( *iEnd ) ) {
196 XLALPrintInfo( "Returning empty timeslice: no sfttimes fall within given GPS range [%"LAL_GPS_FORMAT", %"LAL_GPS_FORMAT"). "
197 "Closest timestamps are: %"LAL_GPS_FORMAT" and %"LAL_GPS_FORMAT"\n",
198 LAL_GPS_PRINT( *minStartGPS ), LAL_GPS_PRINT( *maxStartGPS ),
199 LAL_GPS_PRINT( timestamps->data[( *iEnd ) ] ), LAL_GPS_PRINT( timestamps->data[( *iStart ) ] )
200 );
201 ( *iStart ) = 1;
202 ( *iEnd ) = 0;
203 }
204
205 return XLAL_SUCCESS;
206
207} // XLALFindTimesliceBounds()
208
209
210/**
211 * Given a start-time, Tspan, Tsft and Toverlap, returns a list of timestamps
212 * covering this time-stretch (allowing for overlapping SFTs).
213 *
214 * NOTE: boundary-handling: the returned list of timestamps fall within the
215 * interval [tStart, tStart+Tspan),
216 * consistent with the convention defined in XLALCWGPSinRange().
217 * Assuming each SFT covers a stretch of data of length 'Tsft',
218 * the returned timestamps correspond to a set of SFTs that is guaranteed
219 * to *cover* all data between 'tStart' and 'tStart+Tspan'.
220 * This implies that, while the last timestamp returned will always be
221 * 'ret->data[numSFTs-1] < tStart+Tspan',
222 * the actual data coverage can extend up to 'Tsft' beyond 'tStart+duration'.
223 */
225XLALMakeTimestamps( LIGOTimeGPS tStart, /**< GPS start-time */
226 REAL8 Tspan, /**< total duration to cover, in seconds */
227 REAL8 Tsft, /**< length of the SFT corresponding to each timestamp, in seconds */
228 REAL8 Toverlap /**< time to overlap successive SFTs by, in seconds */
229 )
230{
234 XLAL_CHECK_NULL( Toverlap < Tsft, XLAL_EDOM ); // we must actually advance
235
236 REAL8 Tstep = Tsft - Toverlap; // guaranteed > 0
237 UINT4 numSFTsMax = ceil( Tspan * fudge_down / Tstep ); /* >= 1 !*/
238 // now we might be covering the end-time several times, if using overlapping SFTs, so
239 // let's trim this back down so that end-time is covered exactly once
240 UINT4 numSFTs = numSFTsMax;
241 while ( ( numSFTs >= 2 ) && ( ( numSFTs - 2 ) * Tstep + Tsft >= Tspan ) ) {
242 numSFTs --;
243 }
244
247
248 ret->deltaT = Tsft;
249
250 LIGOTimeGPS tt = tStart; /* initialize to start-time */
251 for ( UINT4 i = 0; i < numSFTs; i++ ) {
252 ret->data[i] = tt;
253 /* get next time-stamp */
254 /* NOTE: we add the interval tStep successively (rounded correctly to ns each time!)
255 * instead of using iSFT*Tsft, in order to avoid possible ns-rounding problems
256 * with REAL8 intervals, which becomes critial from about 100days on...
257 */
258 XLAL_CHECK_NULL( XLALGPSAdd( &tt, Tstep ) != NULL, XLAL_EFUNC );
259
260 } /* for i < numSFTs */
261
262 return ret;
263
264} /* XLALMakeTimestamps() */
265
266
267/**
268 * Same as XLALMakeTimestamps() just for several detectors,
269 * additionally specify the number of detectors.
270 */
272XLALMakeMultiTimestamps( LIGOTimeGPS tStart, /**< GPS start-time */
273 REAL8 Tspan, /**< total duration to cover, in seconds */
274 REAL8 Tsft, /**< Tsft: SFT length of each timestamp, in seconds */
275 REAL8 Toverlap, /**< time to overlap successive SFTs by, in seconds */
276 UINT4 numDet /**< number of timestamps-vectors to generate */
277 )
278{
280
282 XLAL_CHECK_NULL( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_ENOMEM );
283 XLAL_CHECK_NULL( ( ret->data = XLALCalloc( numDet, sizeof( ret->data[0] ) ) ) != NULL, XLAL_ENOMEM );
284 ret->length = numDet;
285
286 for ( UINT4 X = 0; X < numDet; X ++ ) {
287 XLAL_CHECK_NULL( ( ret->data[X] = XLALMakeTimestamps( tStart, Tspan, Tsft, Toverlap ) ) != NULL, XLAL_EFUNC );
288 } // for X < numDet
289
290 return ret;
291
292} /* XLALMakeMultiTimestamps() */
293
294
295/// backwards compatible wrapper to XLALReadTimestampsFileConstrained() without GPS-time constraints
298{
299 return XLALReadTimestampsFileConstrained( fname, NULL, NULL );
300}
301
302
303/// backwards compatible wrapper to XLALReadMultiTimestampsFilesConstrained() without GPS-time constraints
306{
308}
309
310
311/**
312 * Load timestamps file 'fname' into LIGOTimeGPSVector struct, allocated here.
313 *
314 * The timestamps file must contain one GPS time per line, allowing for '%#' as comments, which are ignored.
315 * The constraints 'minGPS', 'maxGPS' are applied by returning only timestamps that fall within
316 * the range defined by XLALCWGPSinRange(gps, minGPS, maxGPS) == 0.
317 */
319XLALReadTimestampsFileConstrained( const CHAR *fname, const LIGOTimeGPS *minGPS, const LIGOTimeGPS *maxGPS )
320{
321 /** check input consistency */
322 XLAL_CHECK_NULL( fname != NULL, XLAL_EINVAL );
323
324 /* read and parse timestamps-list file contents*/
325 LALParsedDataFile *flines = NULL;
327
328 UINT4 numTS = flines->lines->nTokens;
329 UINT4 numTSinRange = 0;
330
331 /* allocate and initialized segment list */
334
335 char buf[256];
336 for ( UINT4 iTS = 0; iTS < numTS; iTS ++ ) {
337 LIGOTimeGPS gps;
338 INT4 secs, ns;
339 char junk[11] = "";
340
341 // first check if obsolete <sec ns> format is found on this line
342 if ( sscanf( flines->lines->tokens[iTS], "%" LAL_INT4_FORMAT " %" LAL_INT4_FORMAT "%10s\n", &secs, &ns, junk ) > 1 ) {
343 gps.gpsSeconds = secs;
344 gps.gpsNanoSeconds = ns;
345
346 XLALPrintWarning( "Line %d: found obsolete 'sec ns' timestamps format '%s', use 'xx.yy[GPS|MJD]' instead: %s\n", iTS, flines->lines->tokens[iTS], XLALGPSToStr( buf, &gps ) );
347 if ( junk[0] != 0 ) {
350 XLAL_ERROR_NULL( XLAL_EINVAL, "Unconverted trailing junk '%s' found: invalid\n", junk );
351 }
352 } // end: if old-style format 'sec ns' is found
353 else {
354 if ( XLALParseStringValueAsEPOCH( &gps, flines->lines->tokens[iTS] ) != XLAL_SUCCESS ) {
357 XLAL_ERROR_NULL( XLAL_EINVAL, "Failed to parse line %d into epoch: '%s'\n", iTS, flines->lines->tokens[iTS] );
358 }
359 }
360
361 if ( XLALCWGPSinRange( gps, minGPS, maxGPS ) == 0 ) {
362 timestamps->data[numTSinRange ++] = gps;
363 }
364
365 } /* for iTS < numTS */
366
367 /* free parsed segment file contents */
369
370 // adjust size of timestamps vector to those found within range
371 timestamps->length = numTSinRange;
372 timestamps->data = XLALRealloc( timestamps->data, numTSinRange * sizeof( timestamps->data[0] ) );
373
374 return timestamps;
375
376} /* XLALReadTimestampsFileConstrained() */
377
378
379/**
380 * Load several timestamps files, return a MultiLIGOTimeGPSVector struct, allocated here.
381 *
382 * The timestamps files must contain one GPS time per line, allowing for '%#' as comments, which are ignored.
383 * The constraints 'minGPS', 'maxGPS' are applied by returning only timestamps that fall within
384 * the range defined by XLALCWGPSinRange(gps, minGPS, maxGPS) == 0.
385 *
386 */
389{
391 XLAL_CHECK_NULL( fnames->data != NULL, XLAL_EINVAL );
392 XLAL_CHECK_NULL( fnames->length > 0, XLAL_EDOM );
393
394 UINT4 numDet = fnames->length;
395
396 // ----- prepare output container
398 XLAL_CHECK_NULL( ( multiTS = XLALCalloc( 1, sizeof( *multiTS ) ) ) != NULL, XLAL_ENOMEM );
399 XLAL_CHECK_NULL( ( multiTS->data = XLALCalloc( numDet, sizeof( multiTS->data[0] ) ) ) != NULL, XLAL_ENOMEM );
400 multiTS->length = numDet;
401
402 for ( UINT4 X = 0; X < numDet; X ++ ) {
403 XLAL_CHECK_NULL( fnames->data[X] != NULL, XLAL_EINVAL );
404 XLAL_CHECK_NULL( ( multiTS->data[X] = XLALReadTimestampsFileConstrained( fnames->data[X], minGPS, maxGPS ) ) != NULL, XLAL_EFUNC );
405 } // for X < numDet
406
407 return multiTS;
408
409} // XLALReadMultiTimestampsFilesConstrained()
410
411
412/**
413 * Extract timstamps-vector from the given SFTVector
414 */
416XLALExtractTimestampsFromSFTs( const SFTVector *sfts ) /**< [in] input SFT-vector */
417{
418 /* check input consistency */
419 if ( !sfts ) {
420 XLALPrintError( "%s: invalid NULL input 'sfts'\n", __func__ );
422 }
423
424 UINT4 numSFTs = sfts->length;
425 /* create output vector */
426 LIGOTimeGPSVector *ret = NULL;
427 if ( ( ret = XLALCreateTimestampVector( numSFTs ) ) == NULL ) {
428 XLALPrintError( "%s: XLALCreateTimestampVector(%d) failed.\n", __func__, numSFTs );
430 }
431 ret->deltaT = TSFTfromDFreq( sfts->data[0].deltaF );
432
433 UINT4 i;
434 for ( i = 0; i < numSFTs; i ++ ) {
435 ret->data[i] = sfts->data[i].epoch;
436 }
437
438 /* done: return Ts-vector */
439 return ret;
440
441} /* XLALExtractTimestampsFromSFTs() */
442
443
444/**
445 * Given a multi-SFT vector, return a MultiLIGOTimeGPSVector holding the
446 * SFT timestamps
447 */
450{
451 /* check input consistency */
452 if ( !multiSFTs || multiSFTs->length == 0 ) {
453 XLALPrintError( "%s: illegal NULL or empty input 'multiSFTs'.\n", __func__ );
455 }
456 UINT4 numIFOs = multiSFTs->length;
457
458 /* create output vector */
459 MultiLIGOTimeGPSVector *ret = NULL;
460 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
461 XLALPrintError( "%s: failed to XLALCalloc ( 1, %zu ).\n", __func__, sizeof( *ret ) );
463 }
464
465 if ( ( ret->data = XLALCalloc( numIFOs, sizeof( *ret->data ) ) ) == NULL ) {
466 XLALPrintError( "%s: failed to XLALCalloc ( %d, %zu ).\n", __func__, numIFOs, sizeof( ret->data[0] ) );
467 XLALFree( ret );
469 }
470 ret->length = numIFOs;
471
472 /* now extract timestamps vector from each SFT-vector */
473 UINT4 X;
474 for ( X = 0; X < numIFOs; X ++ ) {
475 if ( ( ret->data[X] = XLALExtractTimestampsFromSFTs( multiSFTs->data[X] ) ) == NULL ) {
476 XLALPrintError( "%s: XLALExtractTimestampsFromSFTs() failed for X=%d\n", __func__, X );
479 }
480
481 } /* for X < numIFOs */
482
483 return ret;
484
485} /* XLALExtractMultiTimestampsFromSFTs() */
486
487
488/**
489 * Extract timestamps-vector of *unique* timestamps from the given SFTCatalog
490 *
491 * NOTE: when dealing with catalogs of frequency-slided SFTs, each timestamp will appear in the
492 * catalog multiple times, depending on how many frequency slices have been read in.
493 * In such cases this function will return the list of *unique* timestamps.
494 *
495 * NOTE 2: This function will also enfore the multiplicity of each timestamp to be the
496 * same through the whole catalog, corresponding to the case of 'frequency-sliced' SFTs,
497 * while non-constant multiplicities would indicate a potential problem somewhere.
498 */
500XLALTimestampsFromSFTCatalog( const SFTCatalog *catalog ) /**< [in] input SFT-catalog */
501{
502 // check input consistency
503 XLAL_CHECK_NULL( catalog != NULL, XLAL_EINVAL );
504 XLAL_CHECK_NULL( catalog->length > 0, XLAL_EINVAL );
505
506 UINT4 numEntries = catalog->length;
507
508 // create output vector, assuming maximal length, realloc at the end
510 XLAL_CHECK_NULL( ( ret = XLALCreateTimestampVector( numEntries ) ) != NULL, XLAL_EFUNC );
511
512 REAL8 Tsft0 = 1.0 / catalog->data[0].header.deltaF;
513 if ( fabs( ( Tsft0 - round( Tsft0 ) ) ) / Tsft0 < 10 * LAL_REAL8_EPS ) { // 10-eps 'snap' to closest integer
514 ret->deltaT = round( Tsft0 );
515 } else {
516 ret->deltaT = Tsft0;
517 }
518
519 // For dealing with SFTCatalogs corresponding to frequency-sliced input SFTs:
520 // Given the guaranteed GPS-ordering of XLALSFTDataFind(), we can rely on duplicate
521 // timestamps to all be found next to each other, and therefore can easily skip them
522 ret->data[0] = catalog->data[0].header.epoch;
523 UINT4 numUnique = 1;
524 UINT4 stride = 0;
525 for ( UINT4 i = 1; i < numEntries; i ++ ) {
526 UINT4 thisStride = 1;
527 const LIGOTimeGPS *ti = &( catalog->data[i].header.epoch );
528 const LIGOTimeGPS *tim1 = &( catalog->data[i - 1].header.epoch );
529 if ( XLALGPSCmp( ti, tim1 ) == 0 ) {
530 thisStride ++;
531 continue; // skip duplicates
532 }
533 ret->data[numUnique] = catalog->data[i].header.epoch;
534 numUnique ++;
535
536 // keep track of stride, ensure that it's the same for every unique timestamp
537 if ( stride == 0 ) {
538 stride = thisStride;
539 } else {
540 XLAL_CHECK_NULL( stride == thisStride, XLAL_EINVAL, "Suspicious SFT Catalog with non-constant timestamps multiplicities '%u != %u'\n", stride, thisStride );
541 }
542 } // for i < numEntries
543
544
545 // now truncate output vector to actual length of unique timestamps
546 ret->length = numUnique;
547 XLAL_CHECK_NULL( ( ret->data = XLALRealloc( ret->data, numUnique * sizeof( ( *ret->data ) ) ) ) != NULL, XLAL_ENOMEM );
548
549 // done: return Ts-vector
550 return ret;
551
552} /* XLALTimestampsFromSFTCatalog() */
553
554
555/**
556 * Given a multi-SFTCatalogView, return a MultiLIGOTimeGPSVector holding the
557 * SFT timestamps
558 */
561{
562 /* check input consistency */
563 XLAL_CHECK_NULL( multiView != NULL, XLAL_EINVAL );
564 XLAL_CHECK_NULL( multiView->length > 0, XLAL_EINVAL );
565
566 UINT4 numIFOs = multiView->length;
567
568 /* create output vector */
570 XLAL_CHECK_NULL( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_ENOMEM );
571 XLAL_CHECK_NULL( ( ret->data = XLALCalloc( numIFOs, sizeof( *( ret->data ) ) ) ) != NULL, XLAL_ENOMEM );
572 ret->length = numIFOs;
573
574 /* now extract timestamps vector from each IFO's SFT-Catalog */
575 for ( UINT4 X = 0; X < numIFOs; X ++ ) {
576 XLAL_CHECK_NULL( ( ret->data[X] = XLALTimestampsFromSFTCatalog( &( multiView->data[X] ) ) ) != NULL, XLAL_EFUNC );
577 } /* for X < numIFOs */
578
579 return ret;
580
581} /* XLALTimestampsFromMultiSFTCatalogView() */
582
583
584/**
585 * Function to read a segment list from given filename, returns a *sorted* LALSegList
586 *
587 * The segment list file format is repeated lines (excluding comment lines beginning with
588 * <tt>\%</tt> or <tt>#</tt>) of one of the following forms:
589 * - <tt>startGPS endGPS</tt>
590 * - <tt>startGPS endGPS NumSFTs</tt> (NumSFTs must be a positive integer)
591 * - <tt>startGPS endGPS duration NumSFTs</tt> (\b DEPRECATED, duration is ignored)
592 *
593 * \note We (ab)use the integer \p id field in LALSeg to carry the total number of SFTs
594 * contained in that segment if <tt>NumSFTs</tt> was provided in the segment file.
595 * This can be used as a consistency check when loading SFTs for these segments.
596 */
598XLALReadSegmentsFromFile( const char *fname /**< name of file containing segment list */
599 )
600{
601 LALSegList *segList = NULL;
602
603 /* check input consistency */
604 XLAL_CHECK_NULL( fname != NULL, XLAL_EFAULT );
605
606 /* read and parse segment-list file contents*/
607 LALParsedDataFile *flines = NULL;
609 const UINT4 numSegments = flines->lines->nTokens;
610 XLAL_CHECK_NULL( numSegments > 0, XLAL_EINVAL, "%s: segment file '%s' does not contain any segments", __func__, fname );
611
612 /* allocate and initialized segment list */
613 XLAL_CHECK_NULL( ( segList = XLALCalloc( 1, sizeof( *segList ) ) ) != NULL, XLAL_ENOMEM );
615
616 /* determine number of columns */
617 int ncol = 0;
618 {
619 REAL8 col[4];
620 ncol = sscanf( flines->lines->tokens[0], "%lf %lf %lf %lf", &col[0], &col[1], &col[2], &col[3] );
621 switch ( ncol ) {
622 case 2:
623 case 3:
624 break;
625 case 4:
627 XLALPrintError( "\n%s: WARNING: segment file '%s' is in DEPRECATED 4-column format (startGPS endGPS duration NumSFTs, duration is ignored)\n", __func__, fname );
628 } else {
629 XLAL_ERROR_NULL( XLAL_EIO, "%s: segment file '%s' is in DEPRECATED 4-column format (startGPS endGPS duration NumSFTs)\n", __func__, fname );
630 }
631 break;
632 default:
633 XLAL_ERROR_NULL( XLAL_EIO, "%s: segment file '%s' contains an unknown %i-column format", __func__, fname, ncol );
634 }
635 }
636
637 /* parse segment list */
638 for ( UINT4 iSeg = 0; iSeg < numSegments; iSeg ++ ) {
639
640 /* parse line of segment file, depending on determined number of columns */
641 REAL8 start = 0, end = 0, duration = 0;
642 INT4 NumSFTs = 0;
643 int ret;
644 switch ( ncol ) {
645 case 2:
646 ret = sscanf( flines->lines->tokens[iSeg], "%lf %lf", &start, &end );
647 XLAL_CHECK_NULL( ret == 2, XLAL_EIO, "%s: number of columns in segment file '%s' is inconsistent (line 1: %i, line %u: %i)", __func__, fname, ncol, iSeg + 1, ret );
648 break;
649 case 3:
650 ret = sscanf( flines->lines->tokens[iSeg], "%lf %lf %i", &start, &end, &NumSFTs );
651 XLAL_CHECK_NULL( ret == 3, XLAL_EIO, "%s: number of columns in segment file '%s' is inconsistent (line 1: %i, line %u: %i)", __func__, fname, ncol, iSeg + 1, ret );
652 XLAL_CHECK_NULL( NumSFTs > 0, XLAL_EIO, "%s: number of SFTs (3rd column) in segment file '%s' must be a positive integer if given (line %u: %i)", __func__, fname, iSeg + 1, NumSFTs );
653 break;
654 case 4:
655 ret = sscanf( flines->lines->tokens[iSeg], "%lf %lf %lf %i", &start, &end, &duration, &NumSFTs );
656 XLAL_CHECK_NULL( ret == 4, XLAL_EIO, "%s: number of columns in segment file '%s' is inconsistent (line 1 = %i, line %u = %i)", __func__, fname, ncol, iSeg + 1, ret );
657 break;
658 default:
659 XLAL_ERROR_NULL( XLAL_EFAILED, "Unexpected error!" );
660 }
661
662 /* set GPS start and end times */
663 LIGOTimeGPS startGPS, endGPS;
664 XLALGPSSetREAL8( &startGPS, start );
665 XLALGPSSetREAL8( &endGPS, end );
666
667 /* create segment and append to list
668 - we set number of SFTs as 'id' field, as we have no other use for it */
669 LALSeg thisSeg;
670 XLAL_CHECK_NULL( XLALSegSet( &thisSeg, &startGPS, &endGPS, NumSFTs ) == XLAL_SUCCESS, XLAL_EFUNC );
672
673 } /* for iSeg < numSegments */
674
675 /* sort final segment list in increasing GPS start-times */
677
678 /* free parsed segment file contents */
680
681 return segList;
682
683} /* XLALReadSegmentsFromFile() */
684
685
686/**
687 * Extract timestamps-vector from a segment file, with functionality based on MakeSFTDAG
688 * The filename should point to a file containing <GPSstart GPSend> of segments or <GPSstart GPSend segLength numSFTs> where segLength is in hours.
689 * adjustSegExtraTime is used in MakeSFTDAG to maximize the number of SFTs in each segement by placing the SFTs in the middle of the segment.
690 * synchronize is used to force the start times of the SFTs to be integer multiples of Toverlap from the start time of the first SFT.
691 * adjustSegExtraTime and synchronize cannot be used concurrently (synchronize will be preferred if both values are non-zero).
692 */
694XLALTimestampsFromSegmentFile( const char *filename, //!< filename: Input filename
695 REAL8 Tsft, //!< Tsft: SFT length of each timestamp, in seconds
696 REAL8 Toverlap, //!< Toverlap: time to overlap successive SFTs by, in seconds
697 BOOLEAN adjustSegExtraTime, //!< adjustSegExtraTime: remove the unused time from beginning and end of the segments (see MakeSFTDAG)
698 BOOLEAN synchronize //!< synchronize: synchronize SFT start times according to the start time of the first SFT. Start time of first SFT is shifted to next higher integer value of Tsft
699 )
700{
702 XLAL_CHECK_NULL( !( adjustSegExtraTime && synchronize ), XLAL_EINVAL, "Must specify only one of adjustSegExtraTime or synchronize" );
703
704 LALSegList *list = NULL;
706
707 //Need to know the number of SFTs before creating the timestamps vector, so we have to do the same loop twice
708 INT4 numSFTs = 0;
709 REAL8 firstSFTstartTime = 0.0, overlapFraction = Toverlap / Tsft;
710
711 for ( UINT4 i = 0; i < list->length; i++ ) {
712 INT4 numThisSeg = 0;
713 REAL8 analysisStartTime, analysisEndTime;
714 if ( adjustSegExtraTime && !synchronize ) {
715 REAL8 segStartTime = XLALGPSGetREAL8( &( list->segs[i].start ) );
716 REAL8 segEndTime = XLALGPSGetREAL8( &( list->segs[i].end ) );
718 if ( overlapFraction != 0.0 ) {
719 if ( ( segEndTime - segStartTime ) > Tsft ) {
720 segExtraTime = fmod( ( segEndTime - segStartTime - Tsft ), ( ( 1.0 - overlapFraction ) * Tsft ) );
721 }
722 } else {
723 segExtraTime = fmod( ( segEndTime - segStartTime ), Tsft );
724 }
727 analysisStartTime = segStartTime + segExtraStart;
728 if ( analysisStartTime > segEndTime ) {
729 analysisStartTime = segEndTime;
730 }
731 analysisEndTime = segEndTime - segExtraEnd;
732 if ( analysisEndTime < segStartTime ) {
733 analysisEndTime = segStartTime;
734 }
735 } // if adjustSegExtraTime && !synchronize
736 else if ( synchronize ) {
737 REAL8 segStartTime = XLALGPSGetREAL8( &( list->segs[i].start ) );
738 REAL8 segEndTime = XLALGPSGetREAL8( &( list->segs[i].end ) );
739 if ( firstSFTstartTime == 0.0 ) {
741 }
742 analysisStartTime = round( ceil( ( segStartTime - firstSFTstartTime ) / ( ( 1.0 - overlapFraction ) * Tsft ) ) * ( 1.0 - overlapFraction ) * Tsft ) + firstSFTstartTime;
743 if ( analysisStartTime > segEndTime ) {
744 analysisStartTime = segEndTime;
745 }
746 analysisEndTime = round( floor( ( segEndTime - analysisStartTime - Tsft ) / ( ( 1.0 - overlapFraction ) * Tsft ) ) * ( 1.0 - overlapFraction ) * Tsft ) + Tsft + analysisStartTime;
747 if ( analysisEndTime < segStartTime ) {
748 analysisEndTime = segStartTime;
749 }
750 } else {
751 analysisStartTime = XLALGPSGetREAL8( &( list->segs[i].start ) );
752 analysisEndTime = XLALGPSGetREAL8( &( list->segs[i].end ) );
753 }
754
755 REAL8 endTime = analysisStartTime;
756 while ( endTime < analysisEndTime ) {
757 if ( numThisSeg == 0 ) {
758 endTime += Tsft;
759 } else {
760 endTime += ( 1.0 - overlapFraction ) * Tsft;
761 }
762 if ( endTime <= analysisEndTime ) {
763 numThisSeg++;
764 }
765 } // while endTime < analysisEndTime
767 } // for i < length
768
771
772 ret->deltaT = Tsft;
773
774 //Second time doing the same thing, but now we can set the times of the SFTs in the timestamps vector
775 firstSFTstartTime = 0.0;
776 UINT4 j = 0;
777 for ( UINT4 i = 0; i < list->length; i++ ) {
778 INT4 numThisSeg = 0;
779 REAL8 analysisStartTime, analysisEndTime;
780 if ( adjustSegExtraTime && !synchronize ) {
781 REAL8 segStartTime = XLALGPSGetREAL8( &( list->segs[i].start ) );
782 REAL8 segEndTime = XLALGPSGetREAL8( &( list->segs[i].end ) );
784 if ( overlapFraction != 0.0 ) {
785 if ( ( segEndTime - segStartTime ) > Tsft ) {
786 segExtraTime = fmod( ( segEndTime - segStartTime - Tsft ), ( ( 1.0 - overlapFraction ) * Tsft ) );
787 }
788 } else {
789 segExtraTime = fmod( ( segEndTime - segStartTime ), Tsft );
790 }
793 analysisStartTime = segStartTime + segExtraStart;
794 if ( analysisStartTime > segEndTime ) {
795 analysisStartTime = segEndTime;
796 }
797 analysisEndTime = segEndTime - segExtraEnd;
798 if ( analysisEndTime < segStartTime ) {
799 analysisEndTime = segStartTime;
800 }
801 } // if adjustSegExtraTime && !synchronize
802 else if ( synchronize ) {
803 REAL8 segStartTime = XLALGPSGetREAL8( &( list->segs[i].start ) );
804 REAL8 segEndTime = XLALGPSGetREAL8( &( list->segs[i].end ) );
805 if ( firstSFTstartTime == 0.0 ) {
807 }
808 analysisStartTime = round( ceil( ( segStartTime - firstSFTstartTime ) / ( ( 1.0 - overlapFraction ) * Tsft ) ) * ( 1.0 - overlapFraction ) * Tsft ) + firstSFTstartTime;
809 if ( analysisStartTime > segEndTime ) {
810 analysisStartTime = segEndTime;
811 }
812 analysisEndTime = round( floor( ( segEndTime - analysisStartTime - Tsft ) / ( ( 1.0 - overlapFraction ) * Tsft ) ) * ( 1.0 - overlapFraction ) * Tsft ) + Tsft + analysisStartTime;
813 if ( analysisEndTime < segStartTime ) {
814 analysisEndTime = segStartTime;
815 }
816 } else {
817 analysisStartTime = XLALGPSGetREAL8( &( list->segs[i].start ) );
818 analysisEndTime = XLALGPSGetREAL8( &( list->segs[i].end ) );
819 }
820
821 REAL8 endTime = analysisStartTime;
822 while ( endTime < analysisEndTime ) {
823 if ( numThisSeg == 0 ) {
824 endTime += Tsft;
825 } else {
826 endTime += ( 1.0 - overlapFraction ) * Tsft;
827 }
828 if ( endTime <= analysisEndTime ) {
829 numThisSeg++;
830 LIGOTimeGPS sftStart;
831 XLALGPSSetREAL8( &sftStart, endTime - Tsft );
832 ret->data[j] = sftStart;
833 j++;
834 }
835 } // while ( endTime < analysisEndTime )
836 } // for i < length
837
838 XLALSegListFree( list );
839
840 /* done: return Ts-vector */
841 return ret;
842
843} // XLALTimestampsFromSegmentFile()
844
845/// @}
#define __func__
log an I/O error, i.e.
int j
Internal SFT types and functions.
static const REAL8 fudge_down
Definition: SFTinternal.h:64
int XLALReadSegmentsFromFile_support_4column_format
Definition: SFTtimestamps.c:38
LIGOTimeGPSVector * timestamps
int XLALParseDataFile(LALParsedDataFile **cfgdata, const CHAR *fname)
void XLALDestroyParsedDataFile(LALParsedDataFile *cfgdata)
#define LAL_GPS_FORMAT
char * XLALGPSToStr(char *s, const LIGOTimeGPS *t)
#define LAL_GPS_PRINT(gps)
#define LAL_REAL8_EPS
unsigned char BOOLEAN
double REAL8
char CHAR
uint32_t UINT4
int32_t INT4
void * XLALMalloc(size_t n)
void * XLALCalloc(size_t m, size_t n)
void * XLALRealloc(void *p, size_t n)
void XLALFree(void *p)
#define LAL_INT4_FORMAT
LIGOTimeGPSVector * XLALMakeTimestamps(LIGOTimeGPS tStart, REAL8 Tspan, REAL8 Tsft, REAL8 Toverlap)
Given a start-time, Tspan, Tsft and Toverlap, returns a list of timestamps covering this time-stretch...
LIGOTimeGPSVector * XLALExtractTimestampsFromSFTs(const SFTVector *sfts)
Extract timstamps-vector from the given SFTVector.
MultiLIGOTimeGPSVector * XLALReadMultiTimestampsFilesConstrained(const LALStringVector *fnames, const LIGOTimeGPS *minGPS, const LIGOTimeGPS *maxGPS)
Load several timestamps files, return a MultiLIGOTimeGPSVector struct, allocated here.
MultiLIGOTimeGPSVector * XLALMakeMultiTimestamps(LIGOTimeGPS tStart, REAL8 Tspan, REAL8 Tsft, REAL8 Toverlap, UINT4 numDet)
Same as XLALMakeTimestamps() just for several detectors, additionally specify the number of detectors...
REAL8 TSFTfromDFreq(REAL8 dFreq)
Definition: SFTtypes.c:1144
int XLALFindTimesliceBounds(UINT4 *iStart, UINT4 *iEnd, const LIGOTimeGPSVector *timestamps, const LIGOTimeGPS *minStartGPS, const LIGOTimeGPS *maxStartGPS)
MultiLIGOTimeGPSVector * XLALTimestampsFromMultiSFTCatalogView(const MultiSFTCatalogView *multiView)
Given a multi-SFTCatalogView, return a MultiLIGOTimeGPSVector holding the SFT timestamps.
LALSegList * XLALReadSegmentsFromFile(const char *fname)
Function to read a segment list from given filename, returns a sorted LALSegList.
LIGOTimeGPSVector * XLALCreateTimestampVector(UINT4 len)
Allocate a LIGOTimeGPSVector.
Definition: SFTtimestamps.c:47
LIGOTimeGPSVector * XLALResizeTimestampVector(LIGOTimeGPSVector *vector, UINT4 length)
Resize a LIGOTimeGPSVector.
Definition: SFTtimestamps.c:85
LIGOTimeGPSVector * XLALTimestampsFromSegmentFile(const char *filename, REAL8 Tsft, REAL8 Toverlap, BOOLEAN adjustSegExtraTime, BOOLEAN synchronize)
Extract timestamps-vector from a segment file, with functionality based on MakeSFTDAG The filename sh...
MultiLIGOTimeGPSVector * XLALExtractMultiTimestampsFromSFTs(const MultiSFTVector *multiSFTs)
Given a multi-SFT vector, return a MultiLIGOTimeGPSVector holding the SFT timestamps.
LIGOTimeGPSVector * XLALReadTimestampsFile(const CHAR *fname)
backwards compatible wrapper to XLALReadTimestampsFileConstrained() without GPS-time constraints
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
void XLALDestroyMultiTimestamps(MultiLIGOTimeGPSVector *multiTS)
Destroy a MultiLIGOTimeGPSVector timestamps vector.
MultiLIGOTimeGPSVector * XLALCreateMultiLIGOTimeGPSVector(UINT4 numDetectors)
Simple creator function for MultiLIGOTimeGPSVector with numDetectors entries.
void XLALDestroyTimestampVector(LIGOTimeGPSVector *vect)
De-allocate a LIGOTimeGPSVector.
Definition: SFTtimestamps.c:69
MultiLIGOTimeGPSVector * XLALReadMultiTimestampsFiles(const LALStringVector *fnames)
backwards compatible wrapper to XLALReadMultiTimestampsFilesConstrained() without GPS-time constraint...
LIGOTimeGPSVector * XLALReadTimestampsFileConstrained(const CHAR *fname, const LIGOTimeGPS *minGPS, const LIGOTimeGPS *maxGPS)
Load timestamps file 'fname' into LIGOTimeGPSVector struct, allocated here.
LIGOTimeGPSVector * XLALTimestampsFromSFTCatalog(const SFTCatalog *catalog)
Extract timestamps-vector of unique timestamps from the given SFTCatalog.
int XLALSegListInit(LALSegList *seglist)
int XLALSegListSort(LALSegList *seglist)
int XLALSegListFree(LALSegList *seglist)
int XLALSegListAppend(LALSegList *seglist, const LALSeg *seg)
int XLALSegSet(LALSeg *seg, const LIGOTimeGPS *start, const LIGOTimeGPS *end, const INT4 id)
int XLALParseStringValueAsEPOCH(LIGOTimeGPS *gps, const char *valString)
#define XLAL_ERROR_NULL(...)
int int int XLALPrintInfo(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_CHECK(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
int int XLALPrintWarning(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_CHECK_NULL(assertion,...)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
XLAL_EIO
XLAL_EINVAL
XLAL_EFAILED
LIGOTimeGPS * XLALGPSSetREAL8(LIGOTimeGPS *epoch, REAL8 t)
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
int XLALGPSCmp(const LIGOTimeGPS *t0, const LIGOTimeGPS *t1)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
end
out
fnames
int N
size_t numDetectors
A vector of COMPLEX8FrequencySeries.
COMPLEX8FrequencySeries * data
Pointer to the data array.
UINT4 length
Number of elements in array.
TokenList * lines
LIGOTimeGPS end
LIGOTimeGPS start
UINT4 length
LALSeg * segs
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
UINT4 length
number of timestamps vectors or ifos
Definition: SFTfileIO.h:202
LIGOTimeGPSVector ** data
timestamps vector for each ifo
Definition: SFTfileIO.h:203
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
A collection of SFT vectors – one for each IFO in a multi-IFO search.
Definition: SFTfileIO.h:179
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
SFTtype header
SFT-header info.
Definition: SFTfileIO.h:228
CHAR ** tokens
UINT4 nTokens