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
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 */
52int 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 */
105int
106XLALFindCoveringSFTBins( 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 */
151SFTtype *
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 */
175void
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 */
201int
202XLALCopySFT( 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 */
229SFTVector *
230XLALCreateSFTVector( 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 */
275SFTVector *
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 */
299void
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 */
327SFTVector *
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 */
423void
424XLALDestroyMultiSFTVector( 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 */
455int
456XLALExtractBandFromSFT( 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;
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 */
526SFTVector *
527XLALExtractBandFromSFTVector( 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 */
572XLALExtractBandFromMultiSFTVector( 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 */
600int
601XLALExtractStrictBandFromSFT( 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
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 */
657SFTVector *
658XLALExtractStrictBandFromSFTVector( 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!) */
716int 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
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 */
774int
775XLALSFTAdd( 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 */
810int
811XLALSFTVectorAdd( 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 */
841int
842XLALMultiSFTVectorAdd( 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 */
877int
878XLALSFTResizeBand( 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 */
916int
917XLALSFTVectorResizeBand( 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 */
945int
946XLALMultiSFTVectorResizeBand( 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 */
967int
968XLALEarliestMultiSFTsample( 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 */
1015int
1016XLALLatestMultiSFTsample( 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 */
1075SFTVector *
1076XLALExtractSFTVectorWithTimestamps( 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)
1143REAL8
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 */
1160int
1161compareSFTdesc( 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) */
1181int
1182compareSFTloc( 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 */
1207int
1208compareDetNameCatalogs( 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 */
1231int 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
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)
float data[BLOCKSIZE]
Definition: hwinject.c:360
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