LALPulsar  6.1.0.1-b72065a
SFTtypes.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019, 2020 David Keitel
3  * Copyright (C) 2019 Pep Covas
4  * Copyright (C) 2010, 2013--2016, 2022 Karl Wette
5  * Copyright (C) 2010 Chris Messenger
6  * Copyright (C) 2004--2009, 2013, 2014 Reinhard Prix
7  * Copyright (C) 2004--2006, 2010 Bernd Machenschalk
8  * Copyright (C) 2004, 2005 Alicia Sintes
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with with program; see the file COPYING. If not, write to the
22  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23  * MA 02110-1301 USA
24  */
25 
26 /*---------- includes ----------*/
27 
28 #include <gsl/gsl_math.h>
29 
30 #include <lal/Units.h>
31 #include <lal/FrequencySeries.h>
32 
33 #include "SFTinternal.h"
34 
35 /*========== function definitions ==========*/
36 
37 /// \addtogroup SFTfileIO_h
38 /// @{
39 
40 /**
41  * Defines the official CW convention for whether a GPS time is 'within' a given range, defined
42  * as the half-open interval [minGPS, maxGPS)
43  *
44  * This function should be used when dealing with SFTs, segment lists, etc. It returns:
45  *
46  * - -1 if \f$ \mathtt{gps} < \mathtt{minGPS} \f$ , i.e. GPS time is 'below' the range;
47  * - 0 if \f$ \mathtt{minGPS} \le \mathtt{gps} < \mathtt{maxGPS} \f$ , i.e. GPS time is 'within' the range;
48  * - 1 if \f$ \mathtt{maxGPS} \le \mathtt{gos} \f$ , i.e. GPS time is 'above' the range;
49  *
50  * If either \c minGPS or \c maxGPS are \c NULL, there are treated as \f$ -\infty \f$ or \f$ +\infty \f$ respectively.
51  */
52 int XLALCWGPSinRange( const LIGOTimeGPS gps, const LIGOTimeGPS *minGPS, const LIGOTimeGPS *maxGPS )
53 {
54  if ( minGPS != NULL && GPS2REAL8( gps ) < GPS2REAL8( *minGPS ) ) {
55  return -1;
56  }
57  if ( maxGPS != NULL && GPS2REAL8( gps ) >= GPS2REAL8( *maxGPS ) ) {
58  return 1;
59  }
60  return 0;
61 } /* XLALCWGPSinRange() */
62 
63 
64 /**
65  * Round a REAL8 frequency down to the nearest integer SFT bin number.
66  *
67  * This function provides an official rounding convention,
68  * including a "fudge" factor.
69  */
71 {
72  return ( UINT4 ) floor( freq / df * fudge_up );
73 } /* XLALRoundFrequencyDownToSFTBin() */
74 
75 
76 /**
77  * Round a REAL8 frequency up to the nearest integer SFT bin number.
78  *
79  * This function provides an official rounding convention,
80  * including a "fudge" factor.
81  */
83 {
84  return ( UINT4 ) ceil( freq / df * fudge_down );
85 } /* XLALRoundFrequencyUpToSFTBin() */
86 
87 
88 /**
89  * Return the 'effective' frequency-band [fMinEff, fMaxEff] = [firstBin, lastBin] * 1/Tsft,
90  * with numBins = lastBin - firstBin + 1
91  * which is the smallest band of SFT-bins that fully covers a given band [fMin, fMin+Band]
92  *
93  * ==> calculate "effective" fMinEff by rounding down from fMin to closest (firstBin/Tsft)
94  * and rounds up in the same way to fMaxEff = (lastBin/Tsft).
95  *
96  * The 'fudge region' allowing for numerical noise is eps= 10*LAL_REAL8_EPS ~2e-15
97  * relative deviation: ie if the SFT contains a bin at 'fi', then we consider for example
98  * "fMin == fi" if fabs(fi - fMin)/fi < eps.
99  *
100  * Note: this function is most useful for internal operations, e.g. where a generated
101  * time series needs to be over-sampled to cover the SFT frequency band of interest.
102  * Ultimately SFTs covering a half-open interval [fMinIn,BandIn) should be returned to
103  * the user using XLALExtractStrictBandFromSFTVector().
104  */
105 int
106 XLALFindCoveringSFTBins( UINT4 *firstBin, ///< [out] effective lower frequency-bin fMinEff = firstBin/Tsft
107  UINT4 *numBins, ///< [out] effective Band of SFT-bins, such that BandEff = (numBins-1)/Tsft
108  REAL8 fMinIn, ///< [in] input lower frequency
109  REAL8 BandIn, ///< [in] input frequency band
110  REAL8 Tsft ///< [in] SFT duration 'Tsft'
111  )
112 {
113  XLAL_CHECK( firstBin != NULL, XLAL_EINVAL );
114  XLAL_CHECK( numBins != NULL, XLAL_EINVAL );
115  XLAL_CHECK( fMinIn >= 0, XLAL_EDOM );
116  XLAL_CHECK( BandIn >= 0, XLAL_EDOM );
117  XLAL_CHECK( Tsft > 0, XLAL_EDOM );
118 
119  volatile REAL8 dFreq = 1.0 / Tsft;
120  volatile REAL8 tmp;
121  // NOTE: don't "simplify" this: we try to make sure
122  // the result of this will be guaranteed to be IEEE-compliant,
123  // and identical to other locations, such as in SFT-IO
124 
125  // ----- lower effective frequency
126  tmp = fMinIn / dFreq;
127  UINT4 imin = ( UINT4 ) floor( tmp * fudge_up ); // round *down*, allowing for eps 'fudge'
128 
129  // ----- upper effective frequency
130  REAL8 fMaxIn = fMinIn + BandIn;
131  tmp = fMaxIn / dFreq;
132  UINT4 imax = ( UINT4 ) ceil( tmp * fudge_down ); // round *up*, allowing for eps fudge
133 
134  // ----- effective band
135  UINT4 num_bins = ( UINT4 )( imax - imin + 1 );
136 
137  // ----- return these
138  ( *firstBin ) = imin;
139  ( *numBins ) = num_bins;
140 
141  return XLAL_SUCCESS;
142 
143 } // XLALFindCoveringSFTBins()
144 
145 
146 /**
147  * XLAL function to create one SFT-struct.
148  * Note: Allows for numBins == 0, in which case only the header is
149  * allocated, with a NULL data pointer.
150  */
151 SFTtype *
153 {
154  SFTtype *sft;
155 
156  if ( ( sft = XLALCalloc( 1, sizeof( *sft ) ) ) == NULL ) {
157  XLAL_ERROR_NULL( XLAL_ENOMEM, "XLALCalloc (1, %zu) failed.\n", sizeof( *sft ) );
158  }
159 
160  if ( numBins ) {
161  if ( ( sft->data = XLALCreateCOMPLEX8Vector( numBins ) ) == NULL ) {
162  XLALFree( sft );
163  XLAL_ERROR_NULL( XLAL_EFUNC, "XLALCreateCOMPLEX8Vector ( %d ) failed. xlalErrno = %d\n", numBins, xlalErrno );
164  }
165  } else {
166  sft->data = NULL; /* no data, just header */
167  }
168 
169  return sft;
170 
171 } /* XLALCreateSFT() */
172 
173 
174 /** Destructor for one SFT */
175 void
177 {
178  if ( !sft ) {
179  return;
180  }
181 
182  if ( sft->data ) {
184  }
185 
186  XLALFree( sft );
187 
188  return;
189 
190 } /* XLALDestroySFT() */
191 
192 
193 /**
194  * Copy an entire SFT-type into another.
195  * We require the destination-SFT to have a NULL data-entry, as the
196  * corresponding data-vector will be allocated here and copied into
197  *
198  * Note: the source-SFT is allowed to have a NULL data-entry,
199  * in which case only the header is copied.
200  */
201 int
202 XLALCopySFT( SFTtype *dest, /**< [out] copied SFT (needs to be allocated already) */
203  const SFTtype *src /**< input-SFT to be copied */
204  )
205 {
206  // check input sanity
207  XLAL_CHECK( dest != NULL, XLAL_EINVAL );
208  XLAL_CHECK( dest->data == NULL, XLAL_EINVAL );
209  XLAL_CHECK( src != NULL, XLAL_EINVAL );
210 
211  /* copy complete head (including data-pointer, but this will be separately alloc'ed and copied in the next step) */
212  ( *dest ) = ( *src ); // struct copy
213 
214  /* copy data (if there's any )*/
215  if ( src->data ) {
216  UINT4 numBins = src->data->length;
217  XLAL_CHECK( ( dest->data = XLALCreateCOMPLEX8Vector( numBins ) ) != NULL, XLAL_EFUNC );
218  memcpy( dest->data->data, src->data->data, numBins * sizeof( dest->data->data[0] ) );
219  }
220 
221  return XLAL_SUCCESS;
222 
223 } // XLALCopySFT()
224 
225 
226 /**
227  * XLAL function to create an SFTVector of \c numSFT SFTs with \c SFTlen frequency-bins (which will be allocated too).
228  */
229 SFTVector *
230 XLALCreateSFTVector( UINT4 numSFTs, /**< number of SFTs */
231  UINT4 numBins /**< number of frequency-bins per SFT */
232  )
233 {
234  UINT4 iSFT;
235  SFTVector *vect;
236 
237  if ( ( vect = XLALCalloc( 1, sizeof( *vect ) ) ) == NULL ) {
239  }
240 
241  vect->length = numSFTs;
242  if ( ( vect->data = XLALCalloc( 1, numSFTs * sizeof( *vect->data ) ) ) == NULL ) {
243  XLALFree( vect );
245  }
246 
247  for ( iSFT = 0; iSFT < numSFTs; iSFT ++ ) {
248  COMPLEX8Vector *data = NULL;
249 
250  /* allow SFTs with 0 bins: only header */
251  if ( numBins ) {
252  if ( ( data = XLALCreateCOMPLEX8Vector( numBins ) ) == NULL ) {
253  UINT4 j;
254  for ( j = 0; j < iSFT; j++ ) {
256  }
257  XLALFree( vect->data );
258  XLALFree( vect );
260  }
261  }
262 
263  vect->data[iSFT].data = data;
264 
265  } /* for iSFT < numSFTs */
266 
267  return vect;
268 
269 } /* XLALCreateSFTVector() */
270 
271 
272 /**
273  * XLAL function to create an SFTVector of \c numSFT SFTs (which are not allocated).
274  */
275 SFTVector *
276 XLALCreateEmptySFTVector( UINT4 numSFTs /**< number of SFTs */
277  )
278 {
279  SFTVector *vect;
280 
281  if ( ( vect = XLALCalloc( 1, sizeof( *vect ) ) ) == NULL ) {
283  }
284 
285  vect->length = numSFTs;
286  if ( ( vect->data = XLALCalloc( 1, numSFTs * sizeof( *vect->data ) ) ) == NULL ) {
287  XLALFree( vect );
289  }
290 
291  return vect;
292 
293 } /* XLALCreateEmptySFTVector() */
294 
295 
296 /**
297  * XLAL interface to destroy an SFTVector
298  */
299 void
301 {
302  if ( !vect ) {
303  return;
304  }
305 
306  for ( UINT4 i = 0; i < vect->length; i++ ) {
307  SFTtype *sft = &( vect->data[i] );
308  if ( sft->data ) {
309  if ( sft->data->data ) {
310  XLALFree( sft->data->data );
311  }
312  XLALFree( sft->data );
313  }
314  } // for i < numSFTs
315 
316  XLALFree( vect->data );
317  XLALFree( vect );
318 
319  return;
320 
321 } /* XLALDestroySFTVector() */
322 
323 
324 /**
325  * Create a complete copy of an SFT vector
326  */
327 SFTVector *
329 {
330  XLAL_CHECK_NULL( ( sftsIn != NULL ) && ( sftsIn->length > 0 ), XLAL_EINVAL );
331 
332  UINT4 numSFTs = sftsIn->length;
333  UINT4 numBins = sftsIn->data[0].data->length;
334 
335  SFTVector *sftsOut;
336  XLAL_CHECK_NULL( ( sftsOut = XLALCreateSFTVector( numSFTs, numBins ) ) != NULL, XLAL_EFUNC );
337 
338  for ( UINT4 alpha = 0; alpha < numSFTs; alpha++ ) {
339  SFTtype *thisSFTIn = &sftsIn->data[alpha];
340  SFTtype *thisSFTOut = &sftsOut->data[alpha];
341 
342  COMPLEX8Vector *tmp = thisSFTOut->data;
343  memcpy( thisSFTOut, thisSFTIn, sizeof( *thisSFTOut ) );
344  thisSFTOut->data = tmp;
345  thisSFTOut->data->length = numBins;
346  memcpy( thisSFTOut->data->data, thisSFTIn->data->data, numBins * sizeof( thisSFTOut->data->data[0] ) );
347 
348  } // for alpha < numSFTs
349 
350  return sftsOut;
351 
352 } // XLALDuplicateSFTVector()
353 
354 
355 /**
356  * Create a multi-IFO SFT vector with a given number of bins per SFT and number of SFTs per IFO (which will be allocated too).
357  *
358  * Note that the input argument "length" refers to the number of frequency bins in each SFT.
359  * The length of the returned MultiSFTVector (i.e. the number of IFOs)
360  * is set from the length of the input numsft vector instead.
361  */
363  UINT4 length, /**< number of SFT data points (frequency bins) */
364  UINT4Vector *numsft /**< number of SFTs in each per-detector SFTVector */
365 )
366 {
367 
368  XLAL_CHECK_NULL( length > 0, XLAL_EINVAL );
369  XLAL_CHECK_NULL( numsft != NULL, XLAL_EFAULT );
370  XLAL_CHECK_NULL( numsft->length > 0, XLAL_EINVAL );
371  XLAL_CHECK_NULL( numsft->data != NULL, XLAL_EFAULT );
372 
373  MultiSFTVector *multSFTVec = NULL;
374 
375  XLAL_CHECK_NULL( ( multSFTVec = XLALCalloc( 1, sizeof( *multSFTVec ) ) ) != NULL, XLAL_ENOMEM );
376 
377  const UINT4 numifo = numsft->length;
378  multSFTVec->length = numifo;
379 
380  XLAL_CHECK_NULL( ( multSFTVec->data = XLALCalloc( numifo, sizeof( *multSFTVec->data ) ) ) != NULL, XLAL_ENOMEM );
381 
382  for ( UINT4 k = 0; k < numifo; k++ ) {
383  XLAL_CHECK_NULL( ( multSFTVec->data[k] = XLALCreateSFTVector( numsft->data[k], length ) ) != NULL, XLAL_ENOMEM );
384  } /* loop over ifos */
385 
386  return multSFTVec;
387 
388 } /* XLALCreateMultiSFTVector() */
389 
390 
391 /**
392  * Create an empty multi-IFO SFT vector with a given number of SFTs per IFO (which are not allocated).
393  */
395  UINT4Vector *numsft /**< number of SFTs in each per-detector SFTVector */
396 )
397 {
398  XLAL_CHECK_NULL( numsft != NULL, XLAL_EFAULT );
399  XLAL_CHECK_NULL( numsft->length > 0, XLAL_EINVAL );
400  XLAL_CHECK_NULL( numsft->data != NULL, XLAL_EFAULT );
401 
402  MultiSFTVector *multSFTVec = NULL;
403 
404  XLAL_CHECK_NULL( ( multSFTVec = XLALCalloc( 1, sizeof( *multSFTVec ) ) ) != NULL, XLAL_ENOMEM );
405 
406  const UINT4 numifo = numsft->length;
407  multSFTVec->length = numifo;
408 
409  XLAL_CHECK_NULL( ( multSFTVec->data = XLALCalloc( numifo, sizeof( *multSFTVec->data ) ) ) != NULL, XLAL_ENOMEM );
410 
411  for ( UINT4 k = 0; k < numifo; k++ ) {
412  XLAL_CHECK_NULL( ( multSFTVec->data[k] = XLALCreateEmptySFTVector( numsft->data[k] ) ) != NULL, XLAL_ENOMEM );
413  } /* loop over ifos */
414 
415  return multSFTVec;
416 
417 } /* XLALCreateEmptyMultiSFTVector() */
418 
419 
420 /**
421  * Destroy a multi SFT-vector
422  */
423 void
424 XLALDestroyMultiSFTVector( MultiSFTVector *multvect ) /**< the SFT-vector to free */
425 {
426  if ( multvect == NULL ) { /* nothing to be done */
427  return;
428  }
429 
430  for ( UINT4 i = 0; i < multvect->length; i++ ) {
431  XLALDestroySFTVector( multvect->data[i] );
432  }
433 
434  XLALFree( multvect->data );
435  XLALFree( multvect );
436 
437  return;
438 
439 } /* XLALDestroyMultiSFTVector() */
440 
441 
442 /**
443  * Return an SFTs containing only the bins in [fMin, fMin+Band].
444  * Note: the output SFT is guaranteed to "cover" the input boundaries 'fMin'
445  * and 'fMin+Band', ie if necessary the output SFT contains one additional
446  * bin on either end of the interval.
447  *
448  * This uses the conventions in XLALFindCoveringSFTBins() to determine
449  * the 'effective' frequency-band to extract.
450  *
451  * \warning This convention is deprecated. Please use either
452  * XLALExtractStrictBandFromSFT(), or else XLALSFTResizeBand()
453  * if you really need a covering frequency band.
454  */
455 int
456 XLALExtractBandFromSFT( SFTtype **outSFT, ///< [out] output SFT (alloc'ed or re-alloced as required)
457  const SFTtype *inSFT, ///< [in] input SFT
458  REAL8 fMin, ///< [in] lower end of frequency interval to return
459  REAL8 Band ///< [in] band width of frequency interval to return
460  )
461 {
462  XLAL_PRINT_DEPRECATION_WARNING( "XLALExtractStrictBandFromSFT" );
463 
464  XLAL_CHECK( outSFT != NULL, XLAL_EINVAL );
465  XLAL_CHECK( inSFT != NULL, XLAL_EINVAL );
466  XLAL_CHECK( inSFT->data != NULL, XLAL_EINVAL );
467  XLAL_CHECK( fMin >= 0, XLAL_EDOM, "Invalid negative frequency fMin = %g\n", fMin );
468  XLAL_CHECK( Band > 0, XLAL_EDOM, "Invalid non-positive Band = %g\n", Band );
469 
470  REAL8 df = inSFT->deltaF;
471  REAL8 Tsft = TSFTfromDFreq( df );
472 
473  REAL8 fMinSFT = inSFT->f0;
474  UINT4 numBinsSFT = inSFT->data->length;
475  UINT4 firstBinSFT = round( fMinSFT / df ); // round to closest bin
476  UINT4 lastBinSFT = firstBinSFT + ( numBinsSFT - 1 );
477 
478  // find 'covering' SFT-band to extract
479  UINT4 firstBinExt, numBinsExt;
480  XLAL_CHECK( XLALFindCoveringSFTBins( &firstBinExt, &numBinsExt, fMin, Band, Tsft ) == XLAL_SUCCESS, XLAL_EFUNC );
481  UINT4 lastBinExt = firstBinExt + ( numBinsExt - 1 );
482 
483  XLAL_CHECK( firstBinExt >= firstBinSFT && ( lastBinExt <= lastBinSFT ), XLAL_EINVAL,
484  "Requested frequency-bins [%f,%f]Hz = [%d, %d] not contained within SFT's [%f, %f]Hz = [%d,%d].\n",
485  fMin, fMin + Band, firstBinExt, lastBinExt, fMinSFT, fMinSFT + ( numBinsSFT - 1 ) * df, firstBinSFT, lastBinSFT );
486 
487  INT4 firstBinOffset = firstBinExt - firstBinSFT;
488 
489  if ( ( *outSFT ) == NULL ) {
490  XLAL_CHECK( ( ( *outSFT ) = XLALCalloc( 1, sizeof( *( *outSFT ) ) ) ) != NULL, XLAL_ENOMEM );
491  }
492  if ( ( *outSFT )->data == NULL ) {
493  XLAL_CHECK( ( ( *outSFT )->data = XLALCreateCOMPLEX8Vector( numBinsExt ) ) != NULL, XLAL_EFUNC );
494  }
495  if ( ( *outSFT )->data->length != numBinsExt ) {
496  XLAL_CHECK( ( ( *outSFT )->data->data = XLALRealloc( ( *outSFT )->data->data, numBinsExt * sizeof( ( *outSFT )->data->data[0] ) ) ) != NULL, XLAL_ENOMEM );
497  ( *outSFT )->data->length = numBinsExt;
498  }
499 
500  COMPLEX8Vector *ptr = ( *outSFT )->data; // keep copy to data-pointer
501  ( *( *outSFT ) ) = ( *inSFT ); // copy complete header
502  ( *outSFT )->data = ptr; // restore data-pointer
503  ( *outSFT )->f0 = firstBinExt * df ; // set correct new fMin
504 
505  /* copy the relevant part of the data */
506  memcpy( ( *outSFT )->data->data, inSFT->data->data + firstBinOffset, numBinsExt * sizeof( ( *outSFT )->data->data[0] ) );
507 
508  return XLAL_SUCCESS;
509 
510 } // XLALExtractBandFromSFT()
511 
512 
513 /**
514  * Return a vector of SFTs containing only the bins in [fMin, fMin+Band].
515  * Note: the output SFT is guaranteed to "cover" the input boundaries 'fMin'
516  * and 'fMin+Band', ie if necessary the output SFT contains one additional
517  * bin on either end of the interval.
518  *
519  * This uses the conventions in XLALFindCoveringSFTBins() to determine
520  * the 'effective' frequency-band to extract.
521  *
522  * \warning This convention is deprecated. Please use either
523  * XLALExtractStrictBandFromSFTVector(), or else XLALSFTVectorResizeBand()
524  * if you really need a covering frequency band.
525  */
526 SFTVector *
527 XLALExtractBandFromSFTVector( const SFTVector *inSFTs, ///< [in] input SFTs
528  REAL8 fMin, ///< [in] lower end of frequency interval to return
529  REAL8 Band ///< [in] band width of frequency interval to return
530  )
531 {
532  XLAL_PRINT_DEPRECATION_WARNING( "XLALExtractStrictBandFromSFTVector" );
533 
534  XLAL_CHECK_NULL( inSFTs != NULL, XLAL_EINVAL, "Invalid NULL input SFT vector 'inSFTs'\n" );
535  XLAL_CHECK_NULL( inSFTs->length > 0, XLAL_EINVAL, "Invalid zero-length input SFT vector 'inSFTs'\n" );
536  XLAL_CHECK_NULL( fMin >= 0, XLAL_EDOM, "Invalid negative frequency fMin = %g\n", fMin );
537  XLAL_CHECK_NULL( Band > 0, XLAL_EDOM, "Invalid non-positive Band = %g\n", Band );
538 
539  UINT4 numSFTs = inSFTs->length;
540 
541  SFTVector *ret;
542  XLAL_CHECK_NULL( ( ret = XLALCreateSFTVector( numSFTs, 0 ) ) != NULL, XLAL_EFUNC );
543 
544  for ( UINT4 i = 0; i < numSFTs; i ++ ) {
545  SFTtype *dest = &( ret->data[i] );
546  SFTtype *src = &( inSFTs->data[i] );
547 
549 
550  } /* for i < numSFTs */
551 
552  /* return final SFT-vector */
553  return ret;
554 
555 } /* XLALExtractBandFromSFTVector() */
556 
557 
558 /**
559  * Return a MultiSFT vector containing only the bins in [fMin, fMin+Band].
560  * Note: the output MultiSFT is guaranteed to "cover" the input boundaries 'fMin'
561  * and 'fMin+Band', ie if necessary the output SFT contains one additional
562  * bin on either end of the interval.
563  *
564  * This uses the conventions in XLALFindCoveringSFTBins() to determine
565  * the 'effective' frequency-band to extract.
566  *
567  * \warning This convention is deprecated. Please use either
568  * XLALExtractStrictBandFromMultiSFTVector(), or else XLALMultiSFTVectorResizeBand()
569  * if you really need a covering frequency band.
570  */
572 XLALExtractBandFromMultiSFTVector( const MultiSFTVector *inSFTs, ///< [in] input MultiSFTs
573  REAL8 fMin, ///< [in] lower end of frequency interval to return
574  REAL8 Band ///< [in] band width of frequency interval to return
575  )
576 {
577  XLAL_PRINT_DEPRECATION_WARNING( "XLALExtractStrictBandFromMultiSFTVector" );
578 
579  XLAL_CHECK_NULL( inSFTs != NULL, XLAL_EINVAL, "Invalid NULL input MultiSFT vector 'inSFTs'\n" );
580  XLAL_CHECK_NULL( inSFTs->length > 0, XLAL_EINVAL, "Invalid zero-length input MultiSFT vector 'inSFTs'\n" );
581  XLAL_CHECK_NULL( fMin >= 0, XLAL_EDOM, "Invalid negative frequency fMin = %g\n", fMin );
582  XLAL_CHECK_NULL( Band > 0, XLAL_EDOM, "Invalid non-positive Band = %g\n", Band );
583 
584  MultiSFTVector *ret = NULL;
585  XLAL_CHECK_NULL( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_ENOMEM );
586  XLAL_CHECK_NULL( ( ret->data = XLALCalloc( inSFTs->length, sizeof( ret->data[0] ) ) ) != NULL, XLAL_ENOMEM );
587  ret->length = inSFTs->length;
588 
589  for ( UINT4 X = 0; X < inSFTs->length; X++ ) {
590  XLAL_CHECK_NULL( ( ret->data[X] = XLALExtractBandFromSFTVector( inSFTs->data[X], fMin, Band ) ) != NULL, XLAL_EFUNC );
591  }
592 
593  return ret;
594 } //XLALExtractBandFromMultiSFTVector()
595 
596 
597 /**
598  * Return a copy of an SFT containing only the bins in [fMin, fMin+Band).
599  */
600 int
601 XLALExtractStrictBandFromSFT( SFTtype **outSFT, ///< [out] output SFT (alloc'ed or re-alloced as required)
602  const SFTtype *inSFT, ///< [in] input SFT
603  REAL8 fMin, ///< [in] lower end of frequency interval to return
604  REAL8 Band ///< [in] band width of frequency interval to return
605  )
606 {
607  XLAL_CHECK( outSFT != NULL, XLAL_EINVAL );
608  XLAL_CHECK( inSFT != NULL, XLAL_EINVAL );
609  XLAL_CHECK( inSFT->data != NULL, XLAL_EINVAL );
610  XLAL_CHECK( fMin >= 0, XLAL_EDOM, "Invalid negative frequency fMin = %g\n", fMin );
611  XLAL_CHECK( Band > 0, XLAL_EDOM, "Invalid non-positive Band = %g\n", Band );
612 
613  REAL8 df = inSFT->deltaF;
614 
615  REAL8 fMinSFT = inSFT->f0;
616  UINT4 numBinsSFT = inSFT->data->length;
617  UINT4 firstBinSFT = round( fMinSFT / df ); // round to closest bin
618  UINT4 lastBinSFT = firstBinSFT + ( numBinsSFT - 1 );
619 
620  UINT4 firstBinExt = XLALRoundFrequencyDownToSFTBin( fMin, df );
621  UINT4 lastBinExt = XLALRoundFrequencyUpToSFTBin( fMin + Band, df ) - 1;
622  UINT4 numBinsExt = lastBinExt - firstBinExt + 1;
623 
624  XLAL_CHECK( firstBinExt >= firstBinSFT && ( lastBinExt <= lastBinSFT ), XLAL_EINVAL,
625  "Requested frequency-bins [%f,%f)Hz = [%d, %d] not contained within SFT's [%f, %f)Hz = [%d,%d].\n",
626  fMin, fMin + Band, firstBinExt, lastBinExt, fMinSFT, fMinSFT + ( numBinsSFT - 1 ) * df, firstBinSFT, lastBinSFT );
627 
628  INT4 firstBinOffset = firstBinExt - firstBinSFT;
629 
630  if ( ( *outSFT ) == NULL ) {
631  XLAL_CHECK( ( ( *outSFT ) = XLALCalloc( 1, sizeof( *( *outSFT ) ) ) ) != NULL, XLAL_ENOMEM );
632  }
633  if ( ( *outSFT )->data == NULL ) {
634  XLAL_CHECK( ( ( *outSFT )->data = XLALCreateCOMPLEX8Vector( numBinsExt ) ) != NULL, XLAL_EFUNC );
635  }
636  if ( ( *outSFT )->data->length != numBinsExt ) {
637  XLAL_CHECK( ( ( *outSFT )->data->data = XLALRealloc( ( *outSFT )->data->data, numBinsExt * sizeof( ( *outSFT )->data->data[0] ) ) ) != NULL, XLAL_ENOMEM );
638  ( *outSFT )->data->length = numBinsExt;
639  }
640 
641  COMPLEX8Vector *ptr = ( *outSFT )->data; // keep copy to data-pointer
642  ( *( *outSFT ) ) = ( *inSFT ); // copy complete header
643  ( *outSFT )->data = ptr; // restore data-pointer
644  ( *outSFT )->f0 = firstBinExt * df ; // set correct new fMin
645 
646  /* copy the relevant part of the data */
647  memcpy( ( *outSFT )->data->data, inSFT->data->data + firstBinOffset, numBinsExt * sizeof( ( *outSFT )->data->data[0] ) );
648 
649  return XLAL_SUCCESS;
650 
651 } // XLALExtractStrictBandFromSFT()
652 
653 
654 /**
655  * Return a copy of a vector of SFTs containing only the bins in [fMin, fMin+Band).
656  */
657 SFTVector *
658 XLALExtractStrictBandFromSFTVector( const SFTVector *inSFTs, ///< [in] input SFTs
659  REAL8 fMin, ///< [in] lower end of frequency interval to return
660  REAL8 Band ///< [in] band width of frequency interval to return
661  )
662 {
663  XLAL_CHECK_NULL( inSFTs != NULL, XLAL_EINVAL, "Invalid NULL input SFT vector 'inSFTs'\n" );
664  XLAL_CHECK_NULL( inSFTs->length > 0, XLAL_EINVAL, "Invalid zero-length input SFT vector 'inSFTs'\n" );
665  XLAL_CHECK_NULL( fMin >= 0, XLAL_EDOM, "Invalid negative frequency fMin = %g\n", fMin );
666  XLAL_CHECK_NULL( Band > 0, XLAL_EDOM, "Invalid non-positive Band = %g\n", Band );
667 
668  UINT4 numSFTs = inSFTs->length;
669 
670  SFTVector *ret;
671  XLAL_CHECK_NULL( ( ret = XLALCreateSFTVector( numSFTs, 0 ) ) != NULL, XLAL_EFUNC );
672 
673  for ( UINT4 i = 0; i < numSFTs; i ++ ) {
674  SFTtype *dest = &( ret->data[i] );
675  SFTtype *src = &( inSFTs->data[i] );
676 
678 
679  } /* for i < numSFTs */
680 
681  /* return final SFT-vector */
682  return ret;
683 
684 } /* XLALExtractStrictBandFromSFTVector() */
685 
686 
687 /**
688  * Return a copy of a MultiSFT vector containing only the bins in [fMin, fMin+Band).
689  */
692  const MultiSFTVector *inSFTs, ///< [in] input MultiSFTs
693  REAL8 fMin, ///< [in] lower end of frequency interval to return
694  REAL8 Band ///< [in] band width of frequency interval to return
695 )
696 {
697  XLAL_CHECK_NULL( inSFTs != NULL, XLAL_EINVAL, "Invalid NULL input MultiSFT vector 'inSFTs'\n" );
698  XLAL_CHECK_NULL( inSFTs->length > 0, XLAL_EINVAL, "Invalid zero-length input MultiSFT vector 'inSFTs'\n" );
699  XLAL_CHECK_NULL( fMin >= 0, XLAL_EDOM, "Invalid negative frequency fMin = %g\n", fMin );
700  XLAL_CHECK_NULL( Band > 0, XLAL_EDOM, "Invalid non-positive Band = %g\n", Band );
701 
702  MultiSFTVector *ret = NULL;
703  XLAL_CHECK_NULL( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_ENOMEM );
704  XLAL_CHECK_NULL( ( ret->data = XLALCalloc( inSFTs->length, sizeof( ret->data[0] ) ) ) != NULL, XLAL_ENOMEM );
705  ret->length = inSFTs->length;
706 
707  for ( UINT4 X = 0; X < inSFTs->length; X++ ) {
708  XLAL_CHECK_NULL( ( ret->data[X] = XLALExtractStrictBandFromSFTVector( inSFTs->data[X], fMin, Band ) ) != NULL, XLAL_EFUNC );
709  }
710 
711  return ret;
712 } //XLALExtractStrictBandFromMultiSFTVector()
713 
714 
715 /** Append the given SFTtype to the SFT-vector (no SFT-specific checks are done!) */
716 int XLALAppendSFT2Vector( SFTVector *vect, /**< destinatino SFTVector to append to */
717  const SFTtype *sft /**< the SFT to append */
718  )
719 {
720  UINT4 oldlen = vect->length;
721 
722  if ( ( vect->data = LALRealloc( vect->data, ( oldlen + 1 ) * sizeof( *vect->data ) ) ) == NULL ) {
724  }
725  memset( &( vect->data[oldlen] ), 0, sizeof( vect->data[0] ) );
726  vect->length ++;
727 
728  XLALCopySFT( &vect->data[oldlen], sft );
729 
730  return XLAL_SUCCESS;
731 
732 } /* XLALAppendSFT2Vector() */
733 
734 
735 /**
736  * Reorder the MultiSFTVector with specified list of IFOs
737  */
739 {
740  XLAL_CHECK( multiSFTs != NULL && IFOs != NULL && multiSFTs->length == IFOs->length && multiSFTs->length <= PULSAR_MAX_DETECTORS, XLAL_EINVAL );
741 
742  // Initialize array of reordered SFTVector pointers
743  SFTVector *reordered[PULSAR_MAX_DETECTORS];
744  XLAL_INIT_MEM( reordered );
745 
746  // Loop through IFO list and reorder if necessary
747  for ( UINT4 i = 0; i < IFOs->length; i ++ ) {
748  UINT4 j = 0;
749  while ( ( j < IFOs->length ) && ( strncmp( IFOs->data[i], multiSFTs->data[j]->data[0].name, 2 ) != 0 ) ) {
750  j++;
751  }
752  XLAL_CHECK( j < IFOs->length, XLAL_EINVAL, "IFO %c%c not found", IFOs->data[i][0], IFOs->data[i][1] );
753  reordered[i] = multiSFTs->data[j]; // copy the SFTVector pointer
754  }
755 
756  // Replace the old pointers with the new values
757  for ( UINT4 i = 0; i < multiSFTs->length; i ++ ) {
758  multiSFTs->data[i] = reordered[i];
759  }
760 
761  return XLAL_SUCCESS;
762 
763 } // XLALReorderMultiSFTVector()
764 
765 
766 /**
767  * Adds SFT-data from SFT 'b' to SFT 'a'
768  *
769  * NOTE: the inputs 'a' and 'b' must have consistent
770  * start-frequency, frequency-spacing, timestamps, units and number of bins.
771  *
772  * The 'name' field of input/output SFTs in 'a' is not modified!
773  */
774 int
775 XLALSFTAdd( SFTtype *a, /**< [in/out] SFT to be added to */
776  const SFTtype *b /**< [in] SFT data to be added */
777  )
778 {
779  XLAL_CHECK( a != NULL, XLAL_EINVAL );
780  XLAL_CHECK( b != NULL, XLAL_EINVAL );
781  XLAL_CHECK( a->data != NULL, XLAL_EINVAL );
782  XLAL_CHECK( b->data != NULL, XLAL_EINVAL );
783 
784  XLAL_CHECK( XLALGPSDiff( &( a->epoch ), &( b->epoch ) ) == 0, XLAL_EINVAL, "SFT epochs differ %"LAL_INT8_FORMAT" != %"LAL_INT8_FORMAT" ns\n", XLALGPSToINT8NS( &( a->epoch ) ), XLALGPSToINT8NS( &( b->epoch ) ) );
785 
786  REAL8 tol = 10 * LAL_REAL8_EPS; // generously allow up to 10*eps tolerance
787  XLAL_CHECK( gsl_fcmp( a->f0, b->f0, tol ) == 0, XLAL_ETOL, "SFT frequencies relative deviation exceeds %g: %.16g != %.16g\n", tol, a->f0, b->f0 );
788  XLAL_CHECK( gsl_fcmp( a->deltaF, b->deltaF, tol ) == 0, XLAL_ETOL, "SFT frequency-steps relative deviation exceeds %g: %.16g != %.16g\n", tol, a->deltaF, b->deltaF );
789  XLAL_CHECK( XLALUnitCompare( &( a->sampleUnits ), &( b->sampleUnits ) ) == 0, XLAL_EINVAL, "SFT sample units differ\n" );
790  XLAL_CHECK( a->data->length == b->data->length, XLAL_EINVAL, "SFT lengths differ: %d != %d\n", a->data->length, b->data->length );
791 
792  UINT4 numBins = a->data->length;
793  for ( UINT4 k = 0; k < numBins; k ++ ) {
794  a->data->data[k] += b->data->data[k];
795  }
796 
797  return XLAL_SUCCESS;
798 
799 } /* XLALSFTAdd() */
800 
801 
802 /**
803  * Adds SFT-data from SFTvector 'b' to elements of SFTVector 'a'
804  *
805  * NOTE: the inputs 'a' and 'b' must have consistent number of SFTs,
806  * start-frequency, frequency-spacing, timestamps, units and number of bins.
807  *
808  * The 'name' field of input/output SFTs in 'a' is not modified!
809  */
810 int
811 XLALSFTVectorAdd( SFTVector *a, /**< [in/out] SFTVector to be added to */
812  const SFTVector *b /**< [in] SFTVector data to be added */
813  )
814 {
815  XLAL_CHECK( a != NULL, XLAL_EINVAL );
816  XLAL_CHECK( b != NULL, XLAL_EINVAL );
817 
818  XLAL_CHECK( a->length == b->length, XLAL_EINVAL );
819  UINT4 numSFTs = a->length;
820 
821  for ( UINT4 k = 0; k < numSFTs; k ++ ) {
822  SFTtype *sft1 = &( a->data[k] );
823  SFTtype *sft2 = &( b->data[k] );
824 
825  XLAL_CHECK( XLALSFTAdd( sft1, sft2 ) == XLAL_SUCCESS, XLAL_EFUNC, "XLALSFTAdd() failed for SFTs k = %d out of %d SFTs\n", k, numSFTs );
826 
827  } // for k < numSFTs
828 
829  return XLAL_SUCCESS;
830 } /* XLALSFTVectorAdd() */
831 
832 
833 /**
834  * Adds SFT-data from MultiSFTvector 'b' to elements of MultiSFTVector 'a'
835  *
836  * NOTE: the inputs 'a' and 'b' must have consistent number of IFO, number of SFTs,
837  * IFO-names, start-frequency, frequency-spacing, timestamps, units and number of bins.
838  *
839  * The 'name' field of input/output SFTs in 'a' is not modified!
840  */
841 int
842 XLALMultiSFTVectorAdd( MultiSFTVector *a, /**< [in/out] MultiSFTVector to be added to */
843  const MultiSFTVector *b /**< [in] MultiSFTVector data to be added */
844  )
845 {
846  XLAL_CHECK( a != NULL, XLAL_EINVAL );
847  XLAL_CHECK( b != NULL, XLAL_EINVAL );
848 
849  XLAL_CHECK( a->length == b->length, XLAL_EINVAL );
850  UINT4 numIFOs = a->length;
851 
852  for ( UINT4 X = 0; X < numIFOs; X ++ ) {
853  SFTVector *vect1 = a->data[X];
854  SFTVector *vect2 = b->data[X];
855 
856  XLAL_CHECK( strncmp( vect1->data[0].name, vect2->data[0].name, 2 ) == 0, XLAL_EINVAL, "SFT detectors differ '%c%c' != '%c%c'\n", vect1->data[0].name[0], vect1->data[0].name[1], vect2->data[0].name[0], vect2->data[0].name[1] );
857 
858  XLAL_CHECK( XLALSFTVectorAdd( vect1, vect2 ) == XLAL_SUCCESS, XLAL_EFUNC, "XLALSFTVectorAdd() failed for SFTVector %d out of %d\n", X + 1, numIFOs );
859 
860  } // for X < numIFOs
861 
862  return XLAL_SUCCESS;
863 
864 } /* XLALMultiSFTVectorAdd() */
865 
866 
867 /**
868  * Resize the frequency-band of a given SFT to [f0, f0+Band].
869  *
870  * NOTE: If the frequency band is extended in any direction, the corresponding bins
871  * will be set to zero
872  *
873  * NOTE2: This uses the conventions in XLALFindCoveringSFTBins() to determine
874  * the 'effective' frequency-band to resize to, in order to coincide with SFT frequency bins.
875  *
876  */
877 int
878 XLALSFTResizeBand( SFTtype *SFT, ///< [in/out] SFT to resize
879  REAL8 f0, ///< [in] new start frequency
880  REAL8 Band ///< [in] new frequency Band
881  )
882 {
883  XLAL_CHECK( SFT != NULL, XLAL_EINVAL );
884  XLAL_CHECK( f0 >= 0, XLAL_EINVAL );
885  XLAL_CHECK( Band >= 0, XLAL_EINVAL );
886 
887 
888  REAL8 Tsft = TSFTfromDFreq( SFT->deltaF );
889  REAL8 f0In = SFT->f0;
890 
891  UINT4 firstBinIn = ( UINT4 ) lround( f0In / SFT->deltaF );
892 
893  UINT4 firstBinOut;
894  UINT4 numBinsOut;
895  XLAL_CHECK( XLALFindCoveringSFTBins( &firstBinOut, &numBinsOut, f0, Band, Tsft ) == XLAL_SUCCESS, XLAL_EFUNC );
896 
897  int firstRelative = firstBinOut - firstBinIn;
898 
899  XLAL_CHECK( ( SFT = XLALResizeCOMPLEX8FrequencySeries( SFT, firstRelative, numBinsOut ) ) != NULL, XLAL_EFUNC );
900 
901  return XLAL_SUCCESS;
902 
903 } // XLALSFTResizeBand()
904 
905 
906 /**
907  * Resize the frequency-band of a given SFT vector to [f0, f0+Band].
908  *
909  * NOTE: If the frequency band is extended in any direction, the corresponding bins
910  * will be set to zero
911  *
912  * NOTE2: This uses the conventions in XLALFindCoveringSFTBins() to determine
913  * the 'effective' frequency-band to resize to, in order to coincide with SFT frequency bins.
914  *
915  */
916 int
917 XLALSFTVectorResizeBand( SFTVector *SFTs, ///< [in/out] SFT vector to resize
918  REAL8 f0, ///< [in] new start frequency
919  REAL8 Band ///< [in] new frequency Band
920  )
921 {
922  XLAL_CHECK( SFTs != NULL, XLAL_EINVAL );
923  XLAL_CHECK( f0 >= 0, XLAL_EINVAL );
924  XLAL_CHECK( Band >= 0, XLAL_EINVAL );
925 
926  for ( UINT4 alpha = 0; alpha < SFTs->length; alpha ++ ) {
928  }
929 
930  return XLAL_SUCCESS;
931 
932 } // XLALSFTVectorResizeBand()
933 
934 
935 /**
936  * Resize the frequency-band of a given multi-SFT vector to [f0, f0+Band].
937  *
938  * NOTE: If the frequency band is extended in any direction, the corresponding bins
939  * will be set to zero
940  *
941  * NOTE2: This uses the conventions in XLALFindCoveringSFTBins() to determine
942  * the 'effective' frequency-band to resize to, in order to coincide with SFT frequency bins.
943  *
944  */
945 int
946 XLALMultiSFTVectorResizeBand( MultiSFTVector *multiSFTs, ///< [in/out] multi-SFT vector to resize
947  REAL8 f0, ///< [in] new start frequency
948  REAL8 Band ///< [in] new frequency Band
949  )
950 {
951  XLAL_CHECK( multiSFTs != NULL, XLAL_EINVAL );
952  XLAL_CHECK( f0 >= 0, XLAL_EINVAL );
953  XLAL_CHECK( Band >= 0, XLAL_EINVAL );
954 
955  for ( UINT4 X = 0; X < multiSFTs->length; X ++ ) {
957  }
958 
959  return XLAL_SUCCESS;
960 
961 } // XLALMultiSFTVectorResizeBand()
962 
963 
964 /**
965  * Finds the earliest timestamp in a multi-SFT data structure
966  */
967 int
968 XLALEarliestMultiSFTsample( LIGOTimeGPS *out, /**< [out] earliest GPS time */
969  const MultiSFTVector *multisfts /**< [in] multi SFT vector */
970  )
971 {
972  UINT4 i, j;
973 
974  /* check sanity of input */
975  if ( !multisfts || ( multisfts->length == 0 ) ) {
976  XLALPrintError( "%s: empty multiSFT input!\n", __func__ );
978  }
979  for ( i = 0; i < multisfts->length; i++ ) {
980  if ( !multisfts->data[i] || ( multisfts->data[i]->length == 0 ) ) {
981  XLALPrintError( "%s: empty multiSFT->data[%d] input!\n", __func__, i );
983  }
984  }
985 
986  /* initialise the earliest sample value */
987  out->gpsSeconds = multisfts->data[0]->data[0].epoch.gpsSeconds;
988  out->gpsNanoSeconds = multisfts->data[0]->data[0].epoch.gpsNanoSeconds;
989 
990  /* loop over detectors */
991  for ( i = 0; i < multisfts->length; i++ ) {
992 
993  /* loop over all SFTs to determine the earliest SFT epoch */
994  for ( j = 0; j < multisfts->data[i]->length; j++ ) {
995 
996  /* compare current SFT epoch with current earliest */
997  if ( ( XLALGPSCmp( out, &multisfts->data[i]->data[j].epoch ) == 1 ) ) {
998  out->gpsSeconds = multisfts->data[i]->data[j].epoch.gpsSeconds;
999  out->gpsNanoSeconds = multisfts->data[i]->data[j].epoch.gpsNanoSeconds;
1000  }
1001 
1002  }
1003 
1004  }
1005 
1006  /* success */
1007  return XLAL_SUCCESS;
1008 
1009 } /* XLALEarliestMultiSFTsample() */
1010 
1011 
1012 /**
1013  * Find the time of the end of the latest SFT in a multi-SFT data structure
1014  */
1015 int
1016 XLALLatestMultiSFTsample( LIGOTimeGPS *out, /**< [out] latest GPS time */
1017  const MultiSFTVector *multisfts /**< [in] multi SFT vector */
1018  )
1019 {
1020  UINT4 i, j;
1021  SFTtype *firstSFT;
1022 
1023  /* check sanity of input */
1024  if ( !multisfts || ( multisfts->length == 0 ) ) {
1025  XLALPrintError( "%s: empty multiSFT input!\n", __func__ );
1027  }
1028  for ( i = 0; i < multisfts->length; i++ ) {
1029  if ( !multisfts->data[i] || ( multisfts->data[i]->length == 0 ) ) {
1030  XLALPrintError( "%s: empty multiSFT->data[%d] input!\n", __func__, i );
1032  }
1033  }
1034 
1035  /* define some useful quantities */
1036  firstSFT = ( multisfts->data[0]->data ); /* a pointer to the first SFT of the first detector */
1037  REAL8 Tsft = TSFTfromDFreq( firstSFT->deltaF ); /* the length of the SFTs in seconds assuming 1/T freq resolution */
1038 
1039  /* initialise the latest sample value */
1040  out->gpsSeconds = firstSFT->epoch.gpsSeconds;
1041  out->gpsNanoSeconds = firstSFT->epoch.gpsNanoSeconds;
1042 
1043  /* loop over detectors */
1044  for ( i = 0; i < multisfts->length; i++ ) {
1045 
1046  /* loop over all SFTs to determine the earliest SFT midpoint of the input data in the SSB frame */
1047  for ( j = 0; j < multisfts->data[i]->length; j++ ) {
1048 
1049  /* compare current SFT epoch with current earliest */
1050  if ( ( XLALGPSCmp( out, &multisfts->data[i]->data[j].epoch ) == -1 ) ) {
1051  out->gpsSeconds = multisfts->data[i]->data[j].epoch.gpsSeconds;
1052  out->gpsNanoSeconds = multisfts->data[i]->data[j].epoch.gpsNanoSeconds;
1053  }
1054  }
1055 
1056  }
1057 
1058  /* add length of SFT to the result so that we output the end of the SFT */
1059  if ( XLALGPSAdd( out, Tsft ) == NULL ) {
1060  XLALPrintError( "%s: NULL pointer returned from XLALGPSAdd()!\n", __func__ );
1062  }
1063 
1064  /* success */
1065  return XLAL_SUCCESS;
1066 
1067 } /* XLALLatestMultiSFTsample() */
1068 
1069 
1070 /**
1071  * Extract an SFTVector from another SFTVector but only those timestamps matching
1072  *
1073  * Timestamps must be a subset of those sfts in the SFTVector or an error occurs
1074  */
1075 SFTVector *
1076 XLALExtractSFTVectorWithTimestamps( const SFTVector *sfts, /**< input SFTs */
1077  const LIGOTimeGPSVector *timestamps /**< timestamps */
1078  )
1079 {
1080  // check input sanity
1081  XLAL_CHECK_NULL( sfts != NULL, XLAL_EINVAL );
1084 
1085  SFTVector *ret = NULL;
1086  XLAL_CHECK_NULL( ( ret = XLALCreateSFTVector( timestamps->length, 0 ) ) != NULL, XLAL_EFUNC );
1087 
1088  UINT4 indexOfInputSFTVector = 0;
1089  UINT4 numberOfSFTsLoadedIntoOutputVector = 0;
1090  for ( UINT4 ii = 0; ii < timestamps->length; ii++ ) {
1091  XLAL_CHECK_NULL( indexOfInputSFTVector < sfts->length, XLAL_FAILURE, "At least one timestamp is not in the range specified by the SFT vector" );
1092 
1093  for ( UINT4 jj = indexOfInputSFTVector; jj < sfts->length; jj++ ) {
1094  if ( XLALGPSCmp( &( sfts->data[jj].epoch ), &( timestamps->data[ii] ) ) == 0 ) {
1095  indexOfInputSFTVector = jj + 1;
1096  XLAL_CHECK_NULL( XLALCopySFT( &( ret->data[ii] ), &( sfts->data[jj] ) ) == XLAL_SUCCESS, XLAL_EFUNC );
1097  numberOfSFTsLoadedIntoOutputVector++;
1098  break;
1099  } // if SFT epoch matches timestamp epoch
1100  } // for jj < sfts->length
1101  } // for ii < timestamps->length
1102 
1103  XLAL_CHECK_NULL( numberOfSFTsLoadedIntoOutputVector == ret->length, XLAL_FAILURE, "Not all timestamps were found in the input SFT vector" );
1104 
1105  return ret;
1106 
1107 } // XLALExtractSFTVectorWithTimestamps
1108 
1109 
1110 /**
1111  * Extract a MultiSFTVector from another MultiSFTVector but only those timestamps matching
1112  *
1113  * Timestamps in each LIGOTimeGPSVector must be a subset of those sfts in each SFTVector or an error occurs
1114  */
1117  const MultiSFTVector *multiSFTs, /**< input SFTs */
1118  const MultiLIGOTimeGPSVector *multiTimestamps /**< timestamps */
1119 )
1120 {
1121  // check input sanity
1124 
1125  MultiSFTVector *ret = NULL;
1126  XLAL_CHECK_NULL( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_ENOMEM );
1127  XLAL_CHECK_NULL( ( ret->data = XLALCalloc( multiSFTs->length, sizeof( *ret->data ) ) ) != NULL, XLAL_ENOMEM );
1128  ret->length = multiSFTs->length;
1129 
1130  for ( UINT4 X = 0; X < multiSFTs->length; X++ ) {
1131  XLAL_CHECK_NULL( ( ret->data[X] = XLALExtractSFTVectorWithTimestamps( multiSFTs->data[X], multiTimestamps->data[X] ) ) != NULL, XLAL_EFUNC );
1132  }
1133 
1134  return ret;
1135 
1136 } // XLALExtractMultiSFTVectorWithMultiTimestamps
1137 
1138 
1139 // Function to 'safely' invert Tsft=1/dFreq to avoid roundoff error for close-but-not-quite integers after inversion
1140 // policy: if (1/dFreq) is within 10 * eps of an integer, round, otherwise leave as a fractional number
1141 // comment: unfortunately Tsft is allowed by spec to be a double, but really should be limited to integer seconds,
1142 // however with this function we should be able to safely work with integer-valued Tsft without leaving spec (yet)
1143 REAL8
1145 {
1146  REAL8 Tsft0 = 1.0 / dFreq;
1147  REAL8 Tsft;
1148  if ( fabs( ( Tsft0 - round( Tsft0 ) ) ) / Tsft0 < 10 * LAL_REAL8_EPS ) {
1149  Tsft = round( Tsft0 );
1150  } else {
1151  Tsft = Tsft0;
1152  }
1153 
1154  return Tsft;
1155 
1156 } // TSFTfromDFreq()
1157 
1158 
1159 /* compare two SFT-descriptors by their GPS-epoch, then starting frequency */
1160 int
1161 compareSFTdesc( const void *ptr1, const void *ptr2 )
1162 {
1163  const SFTDescriptor *desc1 = ptr1;
1164  const SFTDescriptor *desc2 = ptr2;
1165 
1166  if ( GPS2REAL8( desc1->header.epoch ) < GPS2REAL8( desc2->header.epoch ) ) {
1167  return -1;
1168  } else if ( GPS2REAL8( desc1->header.epoch ) > GPS2REAL8( desc2->header.epoch ) ) {
1169  return 1;
1170  } else if ( desc1->header.f0 < desc2->header.f0 ) {
1171  return -1;
1172  } else if ( desc1->header.f0 > desc2->header.f0 ) {
1173  return 1;
1174  } else {
1175  return 0;
1176  }
1177 } /* compareSFTdesc() */
1178 
1179 
1180 /* compare two SFT-descriptors by their locator (f0, file, position) */
1181 int
1182 compareSFTloc( const void *ptr1, const void *ptr2 )
1183 {
1184  const SFTDescriptor *desc1 = ptr1;
1185  const SFTDescriptor *desc2 = ptr2;
1186  int s;
1187  if ( desc1->header.f0 < desc2->header.f0 ) {
1188  return -1;
1189  } else if ( desc1->header.f0 > desc2->header.f0 ) {
1190  return 1;
1191  }
1192  s = strcmp( desc1->locator->fname, desc2->locator->fname );
1193  if ( !s ) {
1194  if ( desc1->locator->offset < desc2->locator->offset ) {
1195  return ( -1 );
1196  } else if ( desc1->locator->offset > desc2->locator->offset ) {
1197  return ( 1 );
1198  } else {
1199  return ( 0 );
1200  }
1201  }
1202  return ( s );
1203 } /* compareSFTloc() */
1204 
1205 
1206 /* compare two SFT-catalog by detector name in alphabetic order */
1207 int
1208 compareDetNameCatalogs( const void *ptr1, const void *ptr2 )
1209 {
1210  SFTCatalog const *cat1 = ( SFTCatalog const * )ptr1;
1211  SFTCatalog const *cat2 = ( SFTCatalog const * )ptr2;
1212  const char *name1 = cat1->data[0].header.name;
1213  const char *name2 = cat2->data[0].header.name;
1214 
1215  if ( name1[0] < name2[0] ) {
1216  return -1;
1217  } else if ( name1[0] > name2[0] ) {
1218  return 1;
1219  } else if ( name1[1] < name2[1] ) {
1220  return -1;
1221  } else if ( name1[1] > name2[1] ) {
1222  return 1;
1223  } else {
1224  return 0;
1225  }
1226 
1227 } /* compareDetNameCatalogs() */
1228 
1229 
1230 /* compare two SFT-descriptors by their GPS-epoch, then starting frequency */
1231 int compareSFTepoch( const void *ptr1, const void *ptr2 )
1232 {
1233  const SFTtype *desc1 = ptr1;
1234  const SFTtype *desc2 = ptr2;
1235 
1236  if ( XLALGPSGetREAL8( &desc1->epoch ) < XLALGPSGetREAL8( &desc2->epoch ) ) {
1237  return -1;
1238  } else if ( XLALGPSGetREAL8( &desc1->epoch ) > XLALGPSGetREAL8( &desc2->epoch ) ) {
1239  return 1;
1240  } else if ( desc1->f0 < desc2->f0 ) {
1241  return -1;
1242  } else if ( desc1->f0 > desc2->f0 ) {
1243  return 1;
1244  } else {
1245  return 0;
1246  }
1247 } /* compareSFTepoch() */
1248 
1249 /// @}
#define __func__
log an I/O error, i.e.
#define GPS2REAL8(gps)
convert GPS-time to REAL8
int j
ProcessParamsTable * ptr
int k
#define LALRealloc(p, n)
REAL8 tol
Internal SFT types and functions.
static const REAL8 fudge_up
Definition: SFTinternal.h:63
static const REAL8 fudge_down
Definition: SFTinternal.h:64
LIGOTimeGPSVector * timestamps
int s
COMPLEX8FrequencySeries * XLALResizeCOMPLEX8FrequencySeries(COMPLEX8FrequencySeries *series, int first, size_t length)
#define LAL_REAL8_EPS
#define XLAL_INIT_MEM(x)
double REAL8
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)
#define LAL_INT8_FORMAT
#define PULSAR_MAX_DETECTORS
maximal number of detectors we can handle (for static arrays of detector quantities)
static const INT4 a
int XLALSFTVectorResizeBand(SFTVector *SFTs, REAL8 f0, REAL8 Band)
Resize the frequency-band of a given SFT vector to [f0, f0+Band].
Definition: SFTtypes.c:917
SFTtype * XLALCreateSFT(UINT4 numBins)
XLAL function to create one SFT-struct.
Definition: SFTtypes.c:152
SFTVector * XLALDuplicateSFTVector(const SFTVector *sftsIn)
Create a complete copy of an SFT vector.
Definition: SFTtypes.c:328
void XLALDestroySFTVector(SFTVector *vect)
XLAL interface to destroy an SFTVector.
Definition: SFTtypes.c:300
int XLALSFTVectorAdd(SFTVector *a, const SFTVector *b)
Adds SFT-data from SFTvector 'b' to elements of SFTVector 'a'.
Definition: SFTtypes.c:811
void XLALDestroyMultiSFTVector(MultiSFTVector *multvect)
Destroy a multi SFT-vector.
Definition: SFTtypes.c:424
MultiSFTVector * XLALExtractStrictBandFromMultiSFTVector(const MultiSFTVector *inSFTs, REAL8 fMin, REAL8 Band)
Return a copy of a MultiSFT vector containing only the bins in [fMin, fMin+Band).
Definition: SFTtypes.c:691
int XLALExtractBandFromSFT(SFTtype **outSFT, const SFTtype *inSFT, REAL8 fMin, REAL8 Band)
Return an SFTs containing only the bins in [fMin, fMin+Band].
Definition: SFTtypes.c:456
MultiSFTVector * XLALExtractBandFromMultiSFTVector(const MultiSFTVector *inSFTs, REAL8 fMin, REAL8 Band)
Return a MultiSFT vector containing only the bins in [fMin, fMin+Band].
Definition: SFTtypes.c:572
int XLALExtractStrictBandFromSFT(SFTtype **outSFT, const SFTtype *inSFT, REAL8 fMin, REAL8 Band)
Return a copy of an SFT containing only the bins in [fMin, fMin+Band).
Definition: SFTtypes.c:601
REAL8 TSFTfromDFreq(REAL8 dFreq)
Definition: SFTtypes.c:1144
int XLALFindCoveringSFTBins(UINT4 *firstBin, UINT4 *numBins, REAL8 fMinIn, REAL8 BandIn, REAL8 Tsft)
Return the 'effective' frequency-band [fMinEff, fMaxEff] = [firstBin, lastBin] * 1/Tsft,...
Definition: SFTtypes.c:106
int XLALMultiSFTVectorResizeBand(MultiSFTVector *multiSFTs, REAL8 f0, REAL8 Band)
Resize the frequency-band of a given multi-SFT vector to [f0, f0+Band].
Definition: SFTtypes.c:946
MultiSFTVector * XLALCreateMultiSFTVector(UINT4 length, UINT4Vector *numsft)
Create a multi-IFO SFT vector with a given number of bins per SFT and number of SFTs per IFO (which w...
Definition: SFTtypes.c:362
int XLALSFTResizeBand(SFTtype *SFT, REAL8 f0, REAL8 Band)
Resize the frequency-band of a given SFT to [f0, f0+Band].
Definition: SFTtypes.c:878
int XLALAppendSFT2Vector(SFTVector *vect, const SFTtype *sft)
Append the given SFTtype to the SFT-vector (no SFT-specific checks are done!)
Definition: SFTtypes.c:716
SFTVector * XLALCreateEmptySFTVector(UINT4 numSFTs)
XLAL function to create an SFTVector of numSFT SFTs (which are not allocated).
Definition: SFTtypes.c:276
MultiSFTVector * XLALExtractMultiSFTVectorWithMultiTimestamps(const MultiSFTVector *multiSFTs, const MultiLIGOTimeGPSVector *multiTimestamps)
Extract a MultiSFTVector from another MultiSFTVector but only those timestamps matching.
Definition: SFTtypes.c:1116
int XLALSFTAdd(SFTtype *a, const SFTtype *b)
Adds SFT-data from SFT 'b' to SFT 'a'.
Definition: SFTtypes.c:775
int XLALCopySFT(SFTtype *dest, const SFTtype *src)
Copy an entire SFT-type into another.
Definition: SFTtypes.c:202
UINT4 XLALRoundFrequencyUpToSFTBin(const REAL8 freq, const REAL8 df)
Round a REAL8 frequency up to the nearest integer SFT bin number.
Definition: SFTtypes.c:82
MultiSFTVector * XLALCreateEmptyMultiSFTVector(UINT4Vector *numsft)
Create an empty multi-IFO SFT vector with a given number of SFTs per IFO (which are not allocated).
Definition: SFTtypes.c:394
int XLALLatestMultiSFTsample(LIGOTimeGPS *out, const MultiSFTVector *multisfts)
Find the time of the end of the latest SFT in a multi-SFT data structure.
Definition: SFTtypes.c:1016
UINT4 XLALRoundFrequencyDownToSFTBin(const REAL8 freq, const REAL8 df)
Round a REAL8 frequency down to the nearest integer SFT bin number.
Definition: SFTtypes.c:70
void XLALDestroySFT(SFTtype *sft)
Destructor for one SFT.
Definition: SFTtypes.c:176
int XLALReorderMultiSFTVector(MultiSFTVector *multiSFTs, const LALStringVector *IFOs)
Reorder the MultiSFTVector with specified list of IFOs.
Definition: SFTtypes.c:738
int XLALMultiSFTVectorAdd(MultiSFTVector *a, const MultiSFTVector *b)
Adds SFT-data from MultiSFTvector 'b' to elements of MultiSFTVector 'a'.
Definition: SFTtypes.c:842
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 compareSFTloc(const void *ptr1, const void *ptr2)
Definition: SFTtypes.c:1182
int compareDetNameCatalogs(const void *ptr1, const void *ptr2)
Definition: SFTtypes.c:1208
SFTVector * XLALCreateSFTVector(UINT4 numSFTs, UINT4 numBins)
XLAL function to create an SFTVector of numSFT SFTs with SFTlen frequency-bins (which will be allocat...
Definition: SFTtypes.c:230
SFTVector * XLALExtractBandFromSFTVector(const SFTVector *inSFTs, REAL8 fMin, REAL8 Band)
Return a vector of SFTs containing only the bins in [fMin, fMin+Band].
Definition: SFTtypes.c:527
SFTVector * XLALExtractStrictBandFromSFTVector(const SFTVector *inSFTs, REAL8 fMin, REAL8 Band)
Return a copy of a vector of SFTs containing only the bins in [fMin, fMin+Band).
Definition: SFTtypes.c:658
int compareSFTdesc(const void *ptr1, const void *ptr2)
Definition: SFTtypes.c:1161
int XLALEarliestMultiSFTsample(LIGOTimeGPS *out, const MultiSFTVector *multisfts)
Finds the earliest timestamp in a multi-SFT data structure.
Definition: SFTtypes.c:968
int compareSFTepoch(const void *ptr1, const void *ptr2)
Definition: SFTtypes.c:1231
SFTVector * XLALExtractSFTVectorWithTimestamps(const SFTVector *sfts, const LIGOTimeGPSVector *timestamps)
Extract an SFTVector from another SFTVector but only those timestamps matching.
Definition: SFTtypes.c:1076
int XLALUnitCompare(const LALUnit *unit1, const LALUnit *unit2)
COMPLEX8Vector * XLALCreateCOMPLEX8Vector(UINT4 length)
void XLALDestroyCOMPLEX8Vector(COMPLEX8Vector *vector)
#define XLAL_ERROR_NULL(...)
#define xlalErrno
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_CHECK_NULL(assertion,...)
#define XLAL_PRINT_DEPRECATION_WARNING(replacement)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_ETOL
XLAL_EDOM
XLAL_EINVAL
XLAL_FAILURE
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
int XLALGPSCmp(const LIGOTimeGPS *t0, const LIGOTimeGPS *t1)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
REAL8 XLALGPSDiff(const LIGOTimeGPS *t1, const LIGOTimeGPS *t0)
INT8 XLALGPSToINT8NS(const LIGOTimeGPS *epoch)
src
out
double alpha
CHAR name[LALNameLength]
COMPLEX8Sequence * data
A vector of COMPLEX8FrequencySeries.
COMPLEX8FrequencySeries * data
Pointer to the data array.
UINT4 length
Number of elements in array.
COMPLEX8 * data
INT4 gpsNanoSeconds
A vector of 'timestamps' of type LIGOTimeGPS.
Definition: SFTfileIO.h:188
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 collection of SFT vectors – one for each IFO in a multi-IFO search.
Definition: SFTfileIO.h:179
UINT4 length
number of ifos
Definition: SFTfileIO.h:183
SFTVector ** data
sftvector for each ifo
Definition: SFTfileIO.h:184
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
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
UINT4 * data
CHAR * fname
Definition: SFTinternal.h:90
double df