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
PulsarCrossCorr_v2.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012, 2013 John Whelan, Shane Larson and Badri Krishnan
3 * Copyright (C) 2013, 2014 Badri Krishnan, John Whelan, Yuanhao Zhang
4 * Copyright (C) 2016, 2017 Grant David Meadors
5 * Copyright (C) 2023, 2024 John Whelan
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with with program; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301 USA
21 */
22
23#include <lal/PulsarCrossCorr_v2.h>
24
25#define SQUARE(x) ((x)*(x))
26#define QUAD(x) ((x)*(x)*(x)*(x))
27#define GPSDIFF(x,y) (1.0*((x).gpsSeconds - (y).gpsSeconds) + ((x).gpsNanoSeconds - (y).gpsNanoSeconds)*1e-9)
28#define MYMAX(x,y) ( (x) > (y) ? (x) : (y) )
29#define MYMIN(x,y) ( (x) < (y) ? (x) : (y) )
30#define USE_ALIGNED_MEMORY_ROUTINES
31#define TRUE (1==1)
32#define FALSE (1==0)
33
34
35// ----- local prototypes ----------
36static int
38(
39 COMPLEX8 *restrict xOut,
40 const COMPLEX8TimeSeries *restrict xIn,
41 const PulsarDopplerParams *restrict doppler,
42 const REAL8 freqShift,
43 const UINT4 indexStartResamp,
44 const UINT4 indexEndResamp,
45 const UINT4 numSamplesIn,
46 const UINT4 insertPoint
47);
48
49static int
51 ResampCrossCorrWorkspace *restrict ws2L,
52 COMPLEX8 *restrict wsFaX_k,
53 COMPLEX8 *restrict wsFbX_k,
54 const MultiResampSFTPairMultiIndexList *restrict resampMultiPairs,
55 const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_a,
56 const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_b,
57 const PulsarDopplerParams *restrict dopplerpos,
58 const PulsarDopplerParams *restrict binaryTemplateSpacings,
59 const REAL8 SRCsampPerTcoh,
60 const UINT4 detX,
61 const UINT4 sftK,
62 const UINT4 detY,
63 const BOOLEAN isL
64);
65// ==================== function definitions ====================
66
67/// \addtogroup PulsarCrossCorr_v2_h
68/// @{
69
70
71/** Calculate the Doppler-shifted frequency associated with each SFT in a list */
72/* This is according to Eqns 2.11 and 2.12 of Dhurandhar et al 2008 */
73/* Also returns the signal phase according to eqn 2.4 */
75(
76 REAL8Vector *shiftedFreqs, /**< Output list of shifted frequencies */
77 UINT4Vector *lowestBins, /**< Output list of bin indices */
78 COMPLEX8Vector *expSignalPhases, /**< Output list of signal phases */
79 REAL8VectorSequence *sincList, /**< Output list of sinc factors */
80 UINT4 numBins, /**< Number of frequency bins to use */
81 PulsarDopplerParams *dopp, /**< Doppler parameters for signal */
82 SFTIndexList *sftIndices, /**< List of indices for SFTs */
83 MultiSFTVector *inputSFTs, /**< SFT data (needed for f0) */
84 MultiSSBtimes *multiTimes, /**< SSB or Binary times */
85 MultiUINT4Vector *badBins, /**< List of bin indices contaminated by known lines */
86 REAL8 Tsft /**< SFT duration */
87)
88{
89 UINT4 numSFTs = sftIndices->length;
90 if ( expSignalPhases->length != numSFTs
91 || shiftedFreqs->length != numSFTs
92 || lowestBins->length != numSFTs
93 || sincList->length != numSFTs ) {
94 XLALPrintError( "Lengths of SFT-indexed lists don't match!" );
96 }
97
98 UINT4 numDets = inputSFTs->length;
99 if ( multiTimes->length != numDets
100 || ( badBins && badBins->length != numDets )
101 ) {
102 XLALPrintError( "Lengths of detector-indexed lists don't match!" );
104 }
105
106 if ( numBins < 1 ) {
107 XLALPrintError( "Must specify a positive number of bins to use!" );
109 }
110
111 /* now calculate the intrinsic signal frequency in the SFT */
112 /* fhat = f_0 + f_1(t-t0) + f_2(t-t0)^2/2 + ... */
113
114 /* this is the sft reference time - the pulsar reference time */
115 for ( UINT4 sftNum = 0; sftNum < numSFTs; sftNum++ ) {
116 UINT4 detInd = sftIndices->data[sftNum].detInd;
117 XLAL_CHECK( ( detInd < inputSFTs->length ),
119 "SFT asked for detector index off end of list:\n sftNum=%"LAL_UINT4_FORMAT", detInd=%"LAL_UINT4_FORMAT", inputSFTs->length=%d\n",
120 sftNum, detInd, inputSFTs->length );
121
122 UINT4 numSFTsDet = inputSFTs->data[detInd]->length;
123 SSBtimes *times;
124 times = multiTimes->data[detInd];
125 XLAL_CHECK( ( times->DeltaT->length == numSFTsDet )
126 && ( times->Tdot->length == numSFTsDet ),
128 "Lengths of multilists don't match!" );
129
130 UINT4 sftInd = sftIndices->data[sftNum].sftInd;
131 XLAL_CHECK( ( sftInd < numSFTsDet ),
133 "SFT asked for SFT index off end of list:\n sftNum=%"LAL_UINT4_FORMAT", detInd=%"LAL_UINT4_FORMAT", sftInd=%"LAL_UINT4_FORMAT", numSFTsDet=%"LAL_UINT4_FORMAT"\n",
134 sftNum, detInd, sftInd, numSFTsDet );
135 REAL8 timeDiff = times->DeltaT->data[sftInd]
136 + XLALGPSDiff( &( times->refTime ), &( dopp->refTime ) );
137 REAL8 fhat = dopp->fkdot[0]; /* initialization */
138 REAL8 phiByTwoPi = fmod( fhat * timeDiff, 1.0 );
139 REAL8 factor = timeDiff;
140
141 for ( UINT4 k = 1; k < PULSAR_MAX_SPINS; k++ ) {
142 fhat += dopp->fkdot[k] * factor;
143 factor *= timeDiff / ( k + 1 );
144 phiByTwoPi += dopp->fkdot[k] * factor;
145 }
146 REAL4 sinPhi, cosPhi; /*Phi -> Phase of each SFT*/
147 if ( XLALSinCos2PiLUT( &sinPhi, &cosPhi, phiByTwoPi ) != XLAL_SUCCESS ) {
148 LogPrintf( LOG_CRITICAL, "%s: XLALSinCos2PiLUT() failed with errno=%d in XLALGetDopplerShiftedFrequencyInfo\n", __func__, xlalErrno );
150 }
151 expSignalPhases->data[sftNum] = cosPhi + I * sinPhi;
152 shiftedFreqs->data[sftNum] = fhat * times->Tdot->data[sftInd];
153 REAL8 fminusf0 = shiftedFreqs->data[sftNum] - inputSFTs->data[detInd]->data[sftInd].f0;
154 lowestBins->data[sftNum] = ceil( fminusf0 * Tsft - 0.5 * numBins );
155#define SINC_SAFETY 1e-5
156 for ( UINT4 l = 0; l < numBins; l++ ) {
157 sincList->data[sftNum * numBins + l] = 1.0;
158 if ( badBins && badBins->data[detInd] ) {
159 for ( UINT4 j = 0;
160 sincList->data[sftNum * numBins + l] != 0.0
161 && j < badBins->data[detInd]->length;
162 j++ ) {
163 if ( lowestBins->data[sftNum] + l
164 == badBins->data[detInd]->data[j] ) {
165 sincList->data[sftNum * numBins + l] = 0.0;
166 }
167 }
168 }
169
170 if ( !badBins || !( badBins->data[detInd] )
171 || sincList->data[sftNum * numBins + l] != 0.0 ) {
172 /* Calculate normalized sinc, i.e., sin(pi*x)/(pi*x) */
173 REAL4 sinPiX, cosPiX;
174 REAL8 X = lowestBins->data[sftNum] - fminusf0 * Tsft + l;
175 if ( X > SINC_SAFETY || ( X < - SINC_SAFETY ) ) {
176 XLAL_CHECK( XLALSinCos2PiLUT( &sinPiX, &cosPiX, 0.5 * X ) == XLAL_SUCCESS, XLAL_EFUNC ); /*sin(2*pi*0.5*x)=sin(pi*x)*/
177 sincList->data[sftNum * numBins + l] = LAL_1_PI * sinPiX / X; /*1/(pi*x) =1/pi*1/x*/
178 }
179 }
180 }
181
182 /* printf("f=%.7f, f0=%.7f, Tsft=%g, numbins=%d, lowestbin=%d, kappa=%g\n",
183 shiftedFreqs->data[sftNum],
184 inputSFTs->data[detInd]->data[sftInd].f0,
185 Tsft, numBins, lowestBins->data[sftNum],
186 kappaValues->data[sftNum]); */
187
188 }
189
190 return XLAL_SUCCESS;
191
192}
193
194
195/** Construct flat SFTIndexList out of a MultiSFTVector */
196/* Allocates memory as well */
198(
199 SFTIndexList **indexList, /**< Output: flat list of indices to locate SFTs */
200 MultiSFTVector *sfts /**< Input: set of per-detector SFT vectors */
201)
202{
203 SFTIndexList *ret = NULL;
204
205 UINT4 numDets = numDets = sfts->length;
206 UINT4 numSFTs = 0;
207 UINT4 j = 0;
208
209 for ( UINT4 k = 0; k < numDets; k++ ) {
210 numSFTs += sfts->data[k]->length;
211 }
212
213 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
215 }
216 ret->length = numSFTs;
217 if ( ( ret->data = XLALCalloc( numSFTs, sizeof( *ret->data ) ) ) == NULL ) {
218 XLALFree( ret );
220 }
221
222 for ( UINT4 k = 0; k < numDets; k++ ) {
223 UINT4 numForDet = sfts->data[k]->length;
224 for ( UINT4 l = 0; l < numForDet; l++ ) {
225 ret->data[j].detInd = k;
226 ret->data[j].sftInd = l;
227 ++j;
228 }
229 }
230 /* should sort list by GPS time if possible */
231 /* qsort(ret->data, ret->length, sizeof(ret->data[0]), CompareGPSTime ) */
232
233 ( *indexList ) = ret;
234
235 return XLAL_SUCCESS;
236}
237
238
239/** Construct list of SFT pairs for inclusion in statistic */
240/* Allocates memory as well */
242(
243 SFTPairIndexList **pairIndexList, /**< Output: list of SFT pairs */
244 SFTIndexList *indexList, /**< Input: list of indices to locate SFTs */
245 MultiSFTVector *sfts, /**< Input: set of per-detector SFT vectors */
246 REAL8 maxLag, /**< Maximum allowed lag time */
247 BOOLEAN inclAutoCorr /**< Flag indicating whether a "pair" of an SFT with itself is allowed */
248)
249{
250 SFTPairIndexList *ret = NULL;
251
252 UINT4 numSFTs = indexList->length;
253 UINT4 j = 0;
254
255 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
257 }
258
259 /* do two passes, one to count the number of pairs so the list can be allocated, and one to actually populate the list. */
260
261 /* maximum possible number of pairs */
262
263 for ( UINT4 k = 0; k < numSFTs; k++ ) {
264 UINT4 lMin;
265 if ( inclAutoCorr ) {
266 lMin = k;
267 } else {
268 lMin = k + 1;
269 }
270 LIGOTimeGPS gps1 = sfts->data[indexList->data[k].detInd]->data[indexList->data[k].sftInd].epoch;
271 for ( UINT4 l = lMin; l < numSFTs; l++ ) {
272 LIGOTimeGPS gps2 = sfts->data[indexList->data[l].detInd]->data[indexList->data[l].sftInd].epoch;
273 REAL8 timeDiff = XLALGPSDiff( &gps1, &gps2 );
274 if ( fabs( timeDiff ) <= maxLag ) {
275 ++j;
276 }
277 }
278 }
279 ret->length = j;
280 if ( ( ret->data = XLALCalloc( ret->length, sizeof( *ret->data ) ) ) == NULL ) {
281 XLALFree( ret );
283 }
284 j = 0;
285 for ( UINT4 k = 0; k < numSFTs; k++ ) {
286 UINT4 lMin;
287 if ( inclAutoCorr ) {
288 lMin = k;
289 } else {
290 lMin = k + 1;
291 }
292 LIGOTimeGPS gps1 = sfts->data[indexList->data[k].detInd]->data[indexList->data[k].sftInd].epoch;
293 for ( UINT4 l = lMin; l < numSFTs; l++ ) {
294 LIGOTimeGPS gps2 = sfts->data[indexList->data[l].detInd]->data[indexList->data[l].sftInd].epoch;
295 REAL8 timeDiff = XLALGPSDiff( &gps1, &gps2 );
296 if ( fabs( timeDiff ) <= maxLag ) {
297 ret->data[j].sftNum[0] = k;
298 ret->data[j].sftNum[1] = l;
299 ++j;
300 }
301 }
302 }
303
304
305 ( *pairIndexList ) = ret;
306
307 return XLAL_SUCCESS;
308}
309
310
311/** Construct list of SFT pairs corresponding to a list of tShort pairs */
312/* Allocates memory as well */
314(
315 SFTPairIndexList **pairIndexList, /**< Output: list of SFT pairs */
316 UINT4VectorSequence **sftPairForTshortPair, /**< Output: list of SFT pairs corresponding to each Tshort pair */
317 SFTIndexList *indexList, /**< Input: list of indices to locate SFTs */
318 MultiResampSFTPairMultiIndexList *resampPairs, /**< Input: pairs of tShort segments for resampling */
319 const MultiLIGOTimeGPSVector *restrict multiTimes, /**< Input: timestamps containing SFT times for each detector */
320 const MultiLIGOTimeGPSVector *restrict resampMultiTimes /**< Input: timestamps containing Tshort times for each detector */
321
322)
323{
324 /* printf("Inside XLALCreateSFTPairIndexListAccurateResamp\n"); */
325
326 UINT4 numSFTs = indexList->length;
327 REAL8 Tsft = resampPairs->Tsft;
328 REAL8 Tshort = resampPairs->Tshort;
329 UINT4 TsftsPerTshort = ( UINT4 )ceil( Tshort / Tsft );
330 UINT4 numTshorts = resampPairs->indexList->length;
331
332 SFTPairIndexList *ret = NULL;
333 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
335 }
336
337 /* Assemble list of SFTs corresponding to each Tshort */
338 UINT4VectorSequence *SFTIndsForTshort = NULL;
339 XLAL_CHECK( ( SFTIndsForTshort = XLALCreateUINT4VectorSequence( numTshorts, TsftsPerTshort ) ) != NULL, XLAL_EFUNC, "XLALCreateUINT4VectorSequence ( %"LAL_UINT4_FORMAT", %"LAL_UINT4_FORMAT" ) failed.", numTshorts, TsftsPerTshort );
340
341 for ( UINT4 reK = 0; reK < numTshorts; reK++ ) {
342 UINT4 ifoK = resampPairs->indexList->data[reK].detInd;
343 UINT4 reIndK = resampPairs->indexList->data[reK].sftInd;
344 LIGOTimeGPS reTimeK = resampMultiTimes->data[ifoK]->data[reIndK];
345 UINT4 kInShort = 0;
346 for ( UINT4 K = 0; K < numSFTs; K++ ) {
347 if ( indexList->data[K].detInd == ifoK ) {
348 UINT4 indK = indexList->data[K].sftInd;
349 LIGOTimeGPS timeK = multiTimes->data[ifoK]->data[indK];
350 REAL8 SFTMidOff = XLALGPSDiff( &timeK, &reTimeK ) + ( 0.5 * Tsft );
351 if ( SFTMidOff >= 0 && SFTMidOff < Tshort ) {
352 /* printf("SFTMidOff=%.0f, Tshort=%.0f; timeK=%d, reTimeK=%d\n", */
353 /* SFTMidOff, Tshort, timeK.gpsSeconds, reTimeK.gpsSeconds); */
354 /* Midpoint of SFT lies within this Tshort */
355 XLAL_CHECK( kInShort < TsftsPerTshort, XLAL_EINVAL,
356 "Unexpectedly too many SFTs within Tshort:\n kInShort=%"LAL_UINT4_FORMAT", TsftsPerTshort=%"LAL_UINT4_FORMAT"\n",
357 kInShort, TsftsPerTshort );
358 SFTIndsForTshort->data[reK * TsftsPerTshort + kInShort] = K;
359 kInShort++;
360 }
361 }
362 }
363 /* printf("reK=%d; kInShort=%d; TsftsPerTshort=%d\n", reK, kInShort, TsftsPerTshort); */
364 for ( UINT4 k = kInShort; k < TsftsPerTshort; k++ ) {
365 SFTIndsForTshort->data[reK * TsftsPerTshort + k] = LAL_UINT4_MAX;
366 }
367 }
368
369 /* Allocate maximum possible size of pair list; will reallocate after construction */
370 UINT4 numTshortPairs = resampPairs->pairIndexList->length;
371 UINT4 maxAlphaInReAlpha = SQUARE( TsftsPerTshort );
372 UINT4 maxNumSFTPairs = numTshortPairs * maxAlphaInReAlpha;
373
374 ret->length = maxNumSFTPairs;
375 /* printf("About to calloc\n"); */
376 if ( ( ret->data = XLALCalloc( ret->length, sizeof( *ret->data ) ) ) == NULL ) {
377 XLALFree( ret );
379 }
380 /* printf("Calloc worked\n"); */
381
382 /* Assemble list of SFT pairs corresponding to each Tshort pair */
383 UINT4VectorSequence *ret2 = NULL;
384 XLAL_CHECK( ( ret2 = XLALCreateUINT4VectorSequence( numTshortPairs, maxAlphaInReAlpha ) ) != NULL, XLAL_EFUNC, "XLALCreateUINT4VectorSequence ( %"LAL_UINT4_FORMAT", %"LAL_UINT4_FORMAT" ) failed.", numTshortPairs, maxAlphaInReAlpha );
385
386 /* Loop over pairs of Tshorts */
387 UINT4 alpha = 0;
388 for ( UINT4 reAlpha = 0; reAlpha < numTshortPairs; reAlpha++ ) {
389 UINT4 alphaInReAlpha = 0;
390 UINT4 reK = resampPairs->pairIndexList->data[reAlpha].sftNum[0];
391 UINT4 reL = resampPairs->pairIndexList->data[reAlpha].sftNum[1];
392 /* printf("alpha=%d, reK=%d, reL=%d\n", reAlpha, reK, reL); */
393 for ( UINT4 kInShort = 0; kInShort < TsftsPerTshort; kInShort++ ) {
394 UINT4 K = SFTIndsForTshort->data[reK * TsftsPerTshort + kInShort];
395 if ( K == LAL_UINT4_MAX ) {
396 break;
397 }
398 for ( UINT4 lInShort = 0; lInShort < TsftsPerTshort; lInShort++ ) {
399 UINT4 L = SFTIndsForTshort->data[reL * TsftsPerTshort + lInShort];
400 if ( L == LAL_UINT4_MAX ) {
401 break;
402 }
403 XLAL_CHECK( alpha < maxNumSFTPairs, XLAL_EINVAL,
404 "Unexpectedly too many SFT pairs:\n kInShort=%"LAL_UINT4_FORMAT", TsftsPerTshort=%"LAL_UINT4_FORMAT"\n",
405 alpha, maxNumSFTPairs );
406 ret->data[alpha].sftNum[0] = K;
407 ret->data[alpha].sftNum[1] = L;
408 ret2->data[reAlpha * maxAlphaInReAlpha + alphaInReAlpha] = alpha;
409 alpha++;
410 alphaInReAlpha++;
411 }
412 }
413 for ( ; alphaInReAlpha < maxAlphaInReAlpha; alphaInReAlpha++ ) {
414 ret2->data[reAlpha * maxAlphaInReAlpha + alphaInReAlpha] = LAL_UINT4_MAX;
415 }
416 }
417 ret->length = alpha;
418 /* printf("About to realloc\n"); */
419 if ( ( ret->data = XLALRealloc( ret->data, ( ret->length ) * sizeof( *ret->data ) ) ) == NULL ) {
420 XLALFree( ret );
423 }
424 /* printf("Realloc worked\n"); */
425
426 ( *pairIndexList ) = ret;
427 ( *sftPairForTshortPair ) = ret2;
428 XLALDestroyUINT4VectorSequence( SFTIndsForTshort );
429
430 return XLAL_SUCCESS;
431}
432
433
434/** Resampling-modified: construct list of SFT pairs for inclusion in statistic */
435/* Allocates memory as well */
437(
438 MultiResampSFTPairMultiIndexList **resampMultiPairIndexList, /**< [out] resamp list of SFT pairs */
439 SFTPairIndexList **pairIndexList, /**< [out] list of SFT pairs */
440 SFTIndexList *indexList, /**< [in] list of indices to locate SFTs */
441 MultiSFTVector *sfts, /**< [in] set of per-detector SFT vectors */
442 REAL8 maxLag, /**< [in] Maximum allowed lag time */
443 BOOLEAN inclAutoCorr, /**< [in] Flag indicating whether a "pair" of an SFT with itself is allowed */
444 BOOLEAN inclSameDetector, /**< [in] Flag indicating whether a "pair" of a detector with itself is allowed */
445 REAL8 Tsft, /**< [in] duration of a single SFT */
446 REAL8 Tshort /**< [in] resampling Tshort */
447)
448{
449 /* Note, inclSameDetect not same as inclAutoCorr; is effectively "Yes" in demod search;
450 * should make user variable*/
451
452 SFTPairIndexList *ret = NULL;
453 MultiResampSFTPairMultiIndexList *resampMultiRet = NULL;
454
455 UINT4 numSFTs = indexList->length;
456 UINT4 numDets = sfts->length;
457 UINT4 j = 0;
458
459 fprintf( stdout, "Number of detectors in SFT list: %u\n", numDets );
460 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
462 }
463 if ( ( resampMultiRet = XLALCalloc( 1, sizeof( *resampMultiRet ) ) ) == NULL ) {
465 }
466
467 /* Resamp block: */
468 /* first, make an array to store the number of matching L */
469 MultiResampSFTMultiCountList *MultiListOfLmatchingGivenMultiK;
470 if ( ( MultiListOfLmatchingGivenMultiK = XLALCalloc( 1, sizeof( *MultiListOfLmatchingGivenMultiK ) ) ) == NULL ) {
472 }
473 MultiListOfLmatchingGivenMultiK->length = numDets; /* Because it is a multi-multi-list */
474 /* next, Allocate detectors X*/
475 if ( ( MultiListOfLmatchingGivenMultiK->data = XLALCalloc( MultiListOfLmatchingGivenMultiK->length, sizeof( *MultiListOfLmatchingGivenMultiK->data ) ) ) == NULL ) {
476 XLALFree( MultiListOfLmatchingGivenMultiK );
478 }
479 /* furthermore, scroll through each detector X to read how many SFTs K_X it has */
480 for ( UINT4 detX = 0; detX < numDets; detX++ ) {
481 MultiListOfLmatchingGivenMultiK->data[detX].length = sfts->data[detX]->length;
482 if ( ( MultiListOfLmatchingGivenMultiK->data[detX].data = XLALCalloc( MultiListOfLmatchingGivenMultiK->data[detX].length, sizeof( *MultiListOfLmatchingGivenMultiK->data[detX].data ) ) ) == NULL ) {
483 XLALFree( MultiListOfLmatchingGivenMultiK->data[detX].data );
485 }
486 /* Now we can count how many matching detectors Y are available to K_X*/
487 /* Go through all possible Y given K_X */
488 for ( UINT4 k = 0; k < MultiListOfLmatchingGivenMultiK->data[detX].length; k++ ) {
489 /* Note that we may have to adjust this to handle gaps in the data */
490 MultiListOfLmatchingGivenMultiK->data[detX].data[k].length = numDets;
491 if ( ( MultiListOfLmatchingGivenMultiK->data[detX].data[k].data = XLALCalloc( MultiListOfLmatchingGivenMultiK->data[detX].data[k].length, sizeof( *MultiListOfLmatchingGivenMultiK->data[detX].data[k].data ) ) ) == NULL ) {
492 XLALFree( MultiListOfLmatchingGivenMultiK->data[detX].data[k].data );
494 }
495 }
496 }
497 /* end resamp block */
498
499 /* do two passes, one to count the number of pairs so the list can be allocated, and one to actually populate the list. */
500 /* maximum possible number of pairs */
501 for ( UINT4 k = 0; k < numSFTs; k++ ) {
502 UINT4 lMin;
503 if ( inclAutoCorr ) {
504 lMin = k;
505 } else {
506 lMin = k + 1;
507 }
508 LIGOTimeGPS gps1 = sfts->data[indexList->data[k].detInd]->data[indexList->data[k].sftInd].epoch;
509 for ( UINT4 l = lMin; l < numSFTs; l++ ) {
510 LIGOTimeGPS gps2 = sfts->data[indexList->data[l].detInd]->data[indexList->data[l].sftInd].epoch;
511 REAL8 timeDiff = XLALGPSDiff( &gps1, &gps2 );
512 if ( fabs( timeDiff ) <= maxLag ) {
513 ++j;
514 }
515 }
516 /* Assign the number of matching L to the list */
517 }
518 /* MULTI-RESAMPLING maximum possible number of pairs */
519 UINT4 lMinMulti;
520 for ( UINT4 detX = 0; detX < numDets; detX++ ) {
521 MultiListOfLmatchingGivenMultiK->data[detX].detInd = detX;
522 for ( UINT4 k = 0; k < MultiListOfLmatchingGivenMultiK->data[detX].length; k++ ) {
523 MultiListOfLmatchingGivenMultiK->data[detX].data[k].sftInd = k;
524 for ( UINT4 detY = 0; detY < numDets; detY++ ) {
525 UINT4 LmatchingGivenKMulti = 0;
526 if ( ( ( detY == detX ) && inclSameDetector ) || ( detY > detX ) ) {
527 if ( detY == detX ) {
528 if ( inclAutoCorr ) {
529 lMinMulti = k;
530 } else {
531 lMinMulti = k + 1;
532 }
533 } else {
534 lMinMulti = 0;
535 }
536 LIGOTimeGPS gps1 = sfts->data[detX]->data[k].epoch;
537 for ( UINT4 l = lMinMulti; l < sfts->data[detY]->length; l++ ) {
538 LIGOTimeGPS gps2 = sfts->data[detY]->data[l].epoch;
539 REAL8 timeDiff = XLALGPSDiff( &gps1, &gps2 );
540 if ( fabs( timeDiff ) <= maxLag ) {
541 ++LmatchingGivenKMulti;
542 }
543 }
544 MultiListOfLmatchingGivenMultiK->data[detX].data[k].data[detY].detInd = detY;
545 MultiListOfLmatchingGivenMultiK->data[detX].data[k].data[detY].sftCount = LmatchingGivenKMulti;
546 }
547 }
548 }
549 }
550
551 ret->length = j;
552 if ( ( ret->data = XLALCalloc( ret->length, sizeof( *ret->data ) ) ) == NULL ) {
553 XLALFree( ret );
555 }
556 j = 0;
557 /* Now assign the lists of lists */
558
559 /* Assign memory to the return structure based on what we found about how
560 * many matching indices exist for the multi-multi struct */
561 /* first, tell the resampling-return how many detectors there are */
562 resampMultiRet->length = numDets;
563 resampMultiRet->maxLag = maxLag;
564 resampMultiRet->Tsft = Tsft;
565 resampMultiRet->Tshort = Tshort;
566 resampMultiRet->inclAutoCorr = inclAutoCorr;
567 resampMultiRet->inclSameDetector = inclSameDetector;
568 if ( ( resampMultiRet->data = XLALCalloc( resampMultiRet->length, sizeof( *resampMultiRet->data ) ) ) == NULL ) {
569 XLALFree( resampMultiRet );
571 }
572 /* Now assign the multi-list of multi-lists */
573 for ( UINT4 detX = 0; detX < resampMultiRet->length; detX++ ) {
574 resampMultiRet->data[detX].length = MultiListOfLmatchingGivenMultiK->data[detX].length;
575 /* Explicitly save detX index. Likely safe regardless because detX loops over numDets; could use detX */
576 resampMultiRet->data[detX].detInd = MultiListOfLmatchingGivenMultiK->data[detX].detInd;
577 if ( ( resampMultiRet->data[detX].data = XLALCalloc( resampMultiRet->data[detX].length, sizeof( *resampMultiRet->data[detX].data ) ) ) == NULL ) {
578 XLALFree( resampMultiRet->data[detX].data );
580 }
581 for ( UINT4 k = 0; k < resampMultiRet->data[detX].length; k++ ) {
582 resampMultiRet->data[detX].data[k].length = MultiListOfLmatchingGivenMultiK->data[detX].data[k].length;
583 /* Explicitly save K_X index. Likely safe regardless because K_X loops over all SFTs in X; could use k */
584 resampMultiRet->data[detX].data[k].sftInd = MultiListOfLmatchingGivenMultiK->data[detX].data[k].sftInd;
585 if ( ( resampMultiRet->data[detX].data[k].data = XLALCalloc( resampMultiRet->data[detX].data[k].length, sizeof( *resampMultiRet->data[detX].data[k].data ) ) ) == NULL ) {
586 XLALFree( resampMultiRet->data[detX].data[k].data );
588 }
589 for ( UINT4 detY = 0; detY < resampMultiRet->data[detX].data[k].length; detY++ ) {
590 resampMultiRet->data[detX].data[k].data[detY].length = MultiListOfLmatchingGivenMultiK->data[detX].data[k].data[detY].sftCount;
591 /* Explicitly save L_K_X index. Needs explicit safety because not all detectors may be online */
592 resampMultiRet->data[detX].data[k].data[detY].detInd = MultiListOfLmatchingGivenMultiK->data[detX].data[k].data[detY].detInd;
593 if ( ( resampMultiRet->data[detX].data[k].data[detY].data = XLALCalloc( resampMultiRet->data[detX].data[k].data[detY].length, sizeof( *resampMultiRet->data[detX].data[k].data[detY].data ) ) ) == NULL ) {
594 XLALFree( resampMultiRet->data[detX].data[k].data[detY].data );
596 }
597 }
598 }
599 }
600
601 XLALDestroyMultiMatchList( MultiListOfLmatchingGivenMultiK );
602
603 /* Ascertain and transcribe the matches into the return structure*/
604 for ( UINT4 k = 0; k < numSFTs; k++ ) {
605 UINT4 lMin;
606 if ( inclAutoCorr ) {
607 lMin = k;
608 } else {
609 lMin = k + 1;
610 }
611 LIGOTimeGPS gps1 = sfts->data[indexList->data[k].detInd]->data[indexList->data[k].sftInd].epoch;
612 for ( UINT4 l = lMin; l < numSFTs; l++ ) {
613 LIGOTimeGPS gps2 = sfts->data[indexList->data[l].detInd]->data[indexList->data[l].sftInd].epoch;
614 REAL8 timeDiff = XLALGPSDiff( &gps1, &gps2 );
615 if ( fabs( timeDiff ) <= maxLag ) {
616 ret->data[j].sftNum[0] = k;
617 ret->data[j].sftNum[1] = l;
618 ++j;
619 }
620 }
621 }
622
623 /* Multi-Ascertain and transcribe the matches into the return structure for resampling*/
624 UINT4 allPairCounter = 0;
625 UINT4 kFlatCounter = 0;
626 UINT4 lFlatCounter = 0;
627 for ( UINT4 detX = 0; detX < resampMultiRet->length; detX++ ) {
628 for ( UINT4 k = 0; k < resampMultiRet->data[detX].length; k++ ) {
629 /* Reinitialize the l-flat counter because now we are
630 * searching against the OTHER SFTs, with their own count */
631 if ( inclAutoCorr ) {
632 lFlatCounter = kFlatCounter;
633 } else {
634 lFlatCounter = kFlatCounter + 1;
635 }
636 for ( UINT4 detY = 0; detY < resampMultiRet->data[detX].data[k].length; detY++ ) {
637 /* note that naively, resampMultiRet->data[detX].data[k].length = numDets,
638 * so we search all detectors. This choice may need to be revisited when
639 * we have gaps in the data */
640 UINT4 outLmatchingGivenKMulti = 0;
641 /* Repeating the following check is necessary, because in general
642 * our index "l" is not the internal SFT vector index for detector Y.
643 * This is in constrast to k, which is (because it is the first index).
644 */
645 if ( ( ( detY == detX ) && inclSameDetector ) || ( detY > detX ) ) {
646 if ( detY == detX ) {
647 if ( inclAutoCorr ) {
648 lMinMulti = k;
649 } else {
650 lMinMulti = k + 1;
651 }
652 } else {
653 lMinMulti = 0;
654 }
655 LIGOTimeGPS gps1 = sfts->data[detX]->data[k].epoch;
656 for ( UINT4 l = lMinMulti; l < sfts->data[detY]->length; l++ ) {
657 LIGOTimeGPS gps2 = sfts->data[detY]->data[l].epoch;
658 REAL8 timeDiff = XLALGPSDiff( &gps1, &gps2 );
659 if ( fabs( timeDiff ) <= maxLag ) {
660 /* Must refer to sft vectors, not the flat index*/
661 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].sftInd = l;
662 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].detInd = detY;
663 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].flatInd = lFlatCounter;
664 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].pairInd = allPairCounter;
665 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].sciFlag = 1.0;
666 ++outLmatchingGivenKMulti;
667 ++allPairCounter;
668 }
669 ++lFlatCounter;
670 } // end l
671 } // similarity check: end
672 } // end detY
673 resampMultiRet->data[detX].data[k].flatInd = kFlatCounter;
674 resampMultiRet->data[detX].data[k].sciFlag = 1.0;
675 ++kFlatCounter;
676 } // end k
677 } // end detX
678 resampMultiRet->oldPairCount = ret->length;
679 resampMultiRet->allPairCount = allPairCounter;
680
681 ( *pairIndexList ) = ret;
682 ( *resampMultiPairIndexList ) = resampMultiRet;
683
684 return XLAL_SUCCESS;
685} // end XLALCreateSFTPairIndexListResamp
686
687
688/** With Tshort, and Resampling-modified: construct list of SFT pairs for inclusion in statistic */
689/* Allocates memory as well, with Tshort */
691(
692 MultiResampSFTPairMultiIndexList **resampMultiPairIndexList, /**< [out] resamp list of SFT pairs */
693 const REAL8 maxLag, /**< [in] Maximum allowed lag time */
694 const BOOLEAN inclAutoCorr, /**< [in] Flag indicating whether a "pair" of an SFT with itself is allowed */
695 const BOOLEAN inclSameDetector, /**< [in] Flag indicating whether a "pair" of a detector with itself is allowed */
696 const REAL8 Tsft, /**< [in] duration of a single SFT */
697 const MultiLIGOTimeGPSVector *restrict multiTimes /**< [in] timestamps containing Tshort times for each detector */
698)
699{
700 /* Note, inclSameDetector not same as inclAutoCorr; is effectively "Yes" in demod search;
701 * have made user variable*/
702
703 XLAL_CHECK( multiTimes != NULL, XLAL_EINVAL );
704 MultiResampSFTPairMultiIndexList *restrict resampMultiRet = NULL;
705
706 const UINT4 numDets = multiTimes->length;
707 const UINT4 numShortPerDet = multiTimes->data[0]->length;
708 const UINT4 numSFTs = numShortPerDet * numDets;
709 const REAL8 Tshort = multiTimes->data[0]->deltaT;
710
711 if ( ( resampMultiRet = XLALCalloc( 1, sizeof( *resampMultiRet ) ) ) == NULL ) {
713 }
714
715 /* First, let us provide a consistent zero-padded length to all
716 * detectors for their time series of Tshorts. We will then add
717 * supplementary information to indicate was is and is not in science */
718
719 /* Resamp block: */
720 /* first, make an array to store the number of matching L */
721 MultiResampSFTMultiCountList *restrict MultiListOfLmatchingGivenMultiK;
722 if ( ( MultiListOfLmatchingGivenMultiK = XLALCalloc( 1, sizeof( *MultiListOfLmatchingGivenMultiK ) ) ) == NULL ) {
724 }
725 MultiListOfLmatchingGivenMultiK->length = numDets; /* Because it is a multi-multi-list */
726 /* next, Allocate detectors X*/
727 if ( ( MultiListOfLmatchingGivenMultiK->data = XLALCalloc( MultiListOfLmatchingGivenMultiK->length, sizeof( *MultiListOfLmatchingGivenMultiK->data ) ) ) == NULL ) {
728 XLALFree( MultiListOfLmatchingGivenMultiK );
730 }
731 /* furthermore, scroll through each detector X to read how many SFTs K_X it has */
732 for ( UINT4 detX = 0; detX < numDets; detX++ ) {
733 MultiListOfLmatchingGivenMultiK->data[detX].length = numShortPerDet;
734 if ( ( MultiListOfLmatchingGivenMultiK->data[detX].data = XLALCalloc( MultiListOfLmatchingGivenMultiK->data[detX].length, sizeof( *MultiListOfLmatchingGivenMultiK->data[detX].data ) ) ) == NULL ) {
735 XLALFree( MultiListOfLmatchingGivenMultiK->data[detX].data );
737 }
738 /* Now we can count how many matching detectors Y are available to K_X*/
739 /* Go through all possible Y given K_X */
740 for ( UINT4 k = 0; k < MultiListOfLmatchingGivenMultiK->data[detX].length; k++ ) {
741 /* Note that we may have to adjust this to handle gaps in the data */
742 MultiListOfLmatchingGivenMultiK->data[detX].data[k].length = numDets;
743 if ( ( MultiListOfLmatchingGivenMultiK->data[detX].data[k].data = XLALCalloc( MultiListOfLmatchingGivenMultiK->data[detX].data[k].length, sizeof( *MultiListOfLmatchingGivenMultiK->data[detX].data[k].data ) ) ) == NULL ) {
744 XLALFree( MultiListOfLmatchingGivenMultiK->data[detX].data[k].data );
746 }
747 }
748 }
749 /* end resamp block */
750
751 /* do two passes, one to count the number of pairs so the list can be allocated, and one to actually populate the list. */
752 /* maximum possible number of pairs */
753 /* MULTI-RESAMPLING maximum possible number of pairs */
754 UINT4 lMinMulti;
755 UINT4 lMaxMulti = 0;
756 for ( UINT4 detX = 0; detX < numDets; detX++ ) {
757 MultiListOfLmatchingGivenMultiK->data[detX].detInd = detX;
758 for ( UINT4 k = 0; k < MultiListOfLmatchingGivenMultiK->data[detX].length; k++ ) {
759 MultiListOfLmatchingGivenMultiK->data[detX].data[k].sftInd = k;
760 for ( UINT4 detY = 0; detY < numDets; detY++ ) {
761 UINT4 LmatchingGivenKMulti = 0;
762 if ( ( ( detY == detX ) && inclSameDetector ) || ( detY > detX ) ) {
763 if ( detY == detX ) {
764 if ( inclAutoCorr ) {
765 lMinMulti = k;
766 } else {
767 lMinMulti = k + 1;
768 }
769 } else {
770 lMinMulti = ( UINT4 )MYMAX( 0, k - round( 2 * maxLag / Tshort ) - 2 );
771 }
772 /* new style, for Tshort */
773 LIGOTimeGPS gps1 = multiTimes->data[detX]->data[k];
774 /* For speed */
775 lMaxMulti = ( UINT4 )MYMIN( numShortPerDet, lMinMulti + round( 4 * maxLag / Tshort ) + 4 );
776 for ( UINT4 l = lMinMulti; l < lMaxMulti; l++ ) {
777 LIGOTimeGPS gps2 = multiTimes->data[detY]->data[l];
778 REAL8 timeDiff = XLALGPSDiff( &gps1, &gps2 );
779 if ( fabs( timeDiff ) <= maxLag ) {
780 ++LmatchingGivenKMulti;
781 }
782 }
783 MultiListOfLmatchingGivenMultiK->data[detX].data[k].data[detY].detInd = detY;
784 MultiListOfLmatchingGivenMultiK->data[detX].data[k].data[detY].sftCount = LmatchingGivenKMulti;
785 }
786 }
787 }
788 }
789
790 /* Now assign the lists of lists */
791
792 /* Assign memory to the return structure based on what we found about how
793 * many matching indices exist for the multi-multi struct */
794 /* first, tell the resampling-return how many detectors there are */
795 resampMultiRet->length = numDets;
796 resampMultiRet->maxLag = maxLag;
797 resampMultiRet->Tsft = Tsft;
798 resampMultiRet->Tshort = Tshort;
799 resampMultiRet->inclAutoCorr = inclAutoCorr;
800 resampMultiRet->inclSameDetector = inclSameDetector;
801 if ( ( resampMultiRet->data = XLALCalloc( resampMultiRet->length, sizeof( *resampMultiRet->data ) ) ) == NULL ) {
802 XLALFree( resampMultiRet );
804 }
805 /* Now assign the multi-list of multi-lists */
806 for ( UINT4 detX = 0; detX < resampMultiRet->length; detX++ ) {
807 resampMultiRet->data[detX].length = MultiListOfLmatchingGivenMultiK->data[detX].length;
808 /* Explicitly save detX index. Likely safe regardless because detX loops over numDets; could use detX */
809 resampMultiRet->data[detX].detInd = MultiListOfLmatchingGivenMultiK->data[detX].detInd;
810 if ( ( resampMultiRet->data[detX].data = XLALCalloc( resampMultiRet->data[detX].length, sizeof( *resampMultiRet->data[detX].data ) ) ) == NULL ) {
811 XLALFree( resampMultiRet->data[detX].data );
813 }
814 for ( UINT4 k = 0; k < resampMultiRet->data[detX].length; k++ ) {
815 resampMultiRet->data[detX].data[k].length = MultiListOfLmatchingGivenMultiK->data[detX].data[k].length;
816 /* Explicitly save K_X index. Likely safe regardless because K_X loops over all SFTs in X; could use k */
817 resampMultiRet->data[detX].data[k].sftInd = MultiListOfLmatchingGivenMultiK->data[detX].data[k].sftInd;
818 if ( ( resampMultiRet->data[detX].data[k].data = XLALCalloc( resampMultiRet->data[detX].data[k].length, sizeof( *resampMultiRet->data[detX].data[k].data ) ) ) == NULL ) {
819 XLALFree( resampMultiRet->data[detX].data[k].data );
821 }
822 for ( UINT4 detY = 0; detY < resampMultiRet->data[detX].data[k].length; detY++ ) {
823 resampMultiRet->data[detX].data[k].data[detY].length = MultiListOfLmatchingGivenMultiK->data[detX].data[k].data[detY].sftCount;
824 /* Explicitly save L_K_X index. Needs explicit safety because not all detectors may be online */
825 resampMultiRet->data[detX].data[k].data[detY].detInd = MultiListOfLmatchingGivenMultiK->data[detX].data[k].data[detY].detInd;
826 if ( ( resampMultiRet->data[detX].data[k].data[detY].data = XLALCalloc( resampMultiRet->data[detX].data[k].data[detY].length, sizeof( *resampMultiRet->data[detX].data[k].data[detY].data ) ) ) == NULL ) {
827 XLALFree( resampMultiRet->data[detX].data[k].data[detY].data );
829 }
830 }
831 }
832 }
833
834 XLALDestroyMultiMatchList( MultiListOfLmatchingGivenMultiK );
835
836 /* Prepare the outer, flat list as well */
837 SFTIndexList *restrict flatIndexList = NULL;
838 if ( ( flatIndexList = XLALCalloc( 1, sizeof( *flatIndexList ) ) ) == NULL ) {
840 }
841 flatIndexList->length = numSFTs;
842 if ( ( flatIndexList->data = XLALCalloc( numSFTs, sizeof( *flatIndexList->data ) ) ) == NULL ) {
843 XLALFree( flatIndexList );
845 }
846
847 /* Multi-Ascertain and transcribe the matches into the return structure for resampling*/
848 UINT4 allPairCounter = 0;
849 UINT4 kFlatCounter = 0;
850 UINT4 lFlatCounter = 0;
851 for ( UINT4 detX = 0; detX < resampMultiRet->length; detX++ ) {
852 for ( UINT4 k = 0; k < resampMultiRet->data[detX].length; k++ ) {
853 kFlatCounter = numShortPerDet * detX + k;
854 /* Reinitialize the l-flat counter because now we are
855 searching against the OTHER SFTs, with their own count */
856 for ( UINT4 detY = 0; detY < resampMultiRet->data[detX].data[k].length; detY++ ) {
857 /* note that naively, resampMultiRet->data[detX].data[k].length = numDets,
858 * so we search all detectors. This choice may need to be revisited when
859 * we have gaps in the data */
860 UINT4 outLmatchingGivenKMulti = 0;
861 /* Repeating the following check is necessary, because in general
862 * our index "l" is not the internal SFT vector index for detector Y.
863 * This is in contrast to k, which is (because it is the first index).
864 */
865 if ( ( ( detY == detX ) && inclSameDetector ) || ( detY > detX ) ) {
866 if ( detY == detX ) {
867 if ( inclAutoCorr ) {
868 lMinMulti = k;
869 } else {
870 lMinMulti = k + 1;
871 }
872 } else {
873 lMinMulti = ( UINT4 )MYMAX( 0, k - round( 2 * maxLag / Tshort ) - 2 );
874 }
875 /* new style, for Tshort */
876 LIGOTimeGPS gps1 = multiTimes->data[detX]->data[k];
877 lMaxMulti = ( UINT4 )MYMIN( numShortPerDet, lMinMulti + round( 4 * maxLag / Tshort ) + 4 );
878 for ( UINT4 l = lMinMulti; l < lMaxMulti; l++ ) {
879 LIGOTimeGPS gps2 = multiTimes->data[detY]->data[l];
880 REAL8 timeDiff = XLALGPSDiff( &gps1, &gps2 );
881 if ( fabs( timeDiff ) <= maxLag ) {
882 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].sftInd = l;
883 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].detInd = detY;
884 lFlatCounter = numShortPerDet * detY + l;
885 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].flatInd = lFlatCounter;
886 /* note that pairInd = alpha in the Whelan et al 2015 paper's notation */
887 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].pairInd = allPairCounter;
888 resampMultiRet->data[detX].data[k].data[detY].data[outLmatchingGivenKMulti].sciFlag = 1.0;
889 ++outLmatchingGivenKMulti;
890 ++allPairCounter;
891 }
892 } // end l
893 } // similarity check: end
894 } // end detY
895 resampMultiRet->data[detX].data[k].flatInd = kFlatCounter;
896 resampMultiRet->data[detX].data[k].sciFlag = 1.0;
897 flatIndexList->data[kFlatCounter].detInd = detX;
898 /* Note, the SFT index is probably just k, but best to be safe */
899 flatIndexList->data[kFlatCounter].sftInd = resampMultiRet->data[detX].data[k].sftInd;
900 /* kFlatCounter should serve as a flat index of all SFTs, or Shorts,
901 * because k passes through all, for all detectors, even if a given
902 * one does not match anything (perhaps b/c it was already assigned
903 * to all appropriate pairs */
904 } // end k
905 } // end detX
906 resampMultiRet->allPairCount = allPairCounter;
907 /* Add one to counts because this is C, with 0-indexing;
908 * remember we assigned kFlatCounter not incrementally but directly */
909 resampMultiRet->sftTotalCount = 1 + kFlatCounter;
910 resampMultiRet->indexList = flatIndexList;
911
912 /* Prepare the standard, old-school pair list too */
913 SFTPairIndexList *restrict standardPairIndexList = NULL;
914 if ( ( standardPairIndexList = XLALCalloc( 1, sizeof( *standardPairIndexList ) ) ) == NULL ) {
916 }
917 standardPairIndexList->length = resampMultiRet->allPairCount;
918 if ( ( standardPairIndexList->data = XLALCalloc( standardPairIndexList->length, sizeof( *standardPairIndexList->data ) ) ) == NULL ) {
919 XLALFree( standardPairIndexList );
921 }
922
923 UINT4 sftNum1;
924 UINT4 sftNum2;
925
926 UINT4 standardPairCount = 0;
927 for ( UINT4 detX = 0; detX < resampMultiRet->length; detX++ ) {
928 for ( UINT4 k = 0; k < resampMultiRet->data[detX].length; k++ ) {
929 for ( UINT4 detY = 0; detY < resampMultiRet->data[detX].data[k].length; detY++ ) {
930 for ( UINT4 l = 0; l < resampMultiRet->data[detX].data[k].data[detY].length; l++ ) {
931 /* Here we must us the flat SFT number */
932 sftNum1 = numShortPerDet * detX + resampMultiRet->data[detX].data[k].sftInd;
933 sftNum2 = numShortPerDet * detY + resampMultiRet->data[detX].data[k].data[detY].data[l].sftInd;
934 standardPairIndexList->data[standardPairCount].sftNum[0] = sftNum1;
935 standardPairIndexList->data[standardPairCount].sftNum[1] = sftNum2;
936 ++standardPairCount;
937 }
938 }
939 }
940 }
941 resampMultiRet->pairIndexList = standardPairIndexList;
942 resampMultiRet->oldPairCount = standardPairCount;
943 ( *resampMultiPairIndexList ) = resampMultiRet;
944
945 return XLAL_SUCCESS;
946} // end XLALCreateSFTPairIndexListShortResamp
947
948
949/** Check that the contents of a resampling multi-pair index list are sensible by inspection */
951(
952 MultiResampSFTPairMultiIndexList *resampMultiPairIndexList /**< [in] resamp list of SFT pairs */
953)
954{
955 MultiResampSFTPairMultiIndexList *resampMultiRet = resampMultiPairIndexList;
956 /* SANITY CHECK */
957 UINT4 grandTotalCounter = 0;
958 for ( UINT4 detX = 0; detX < resampMultiRet->length; detX++ ) {
959 for ( UINT4 k = 0; k < resampMultiRet->data[detX].length; k++ ) {
960 for ( UINT4 detY = 0; detY < resampMultiRet->data[detX].data[k].length; detY++ ) {
961 for ( UINT4 l = 0; l < resampMultiRet->data[detX].data[k].data[detY].length; l++ ) {
962 ++grandTotalCounter;
963 fprintf( stdout, "SFT INDEX: %u\n", resampMultiRet->data[detX].data[k].data[detY].data[l].sftInd );
964 fprintf( stdout, "det INDEX: %u\n", resampMultiRet->data[detX].data[k].data[detY].data[l].detInd );
965 fprintf( stdout, "pair INDEX: %u\n", resampMultiRet->data[detX].data[k].data[detY].data[l].pairInd );
966 }
967 }
968 }
969 }
970 fprintf( stdout, "Sanity check: GRAND TOTAL of passes through loop: %u\n", grandTotalCounter );
971 fprintf( stdout, "Pairing completed\n" );
972 /* SANITY CHECK 2 */
973 UINT4 newKFlatCounter = 0;
974 for ( UINT4 detX = 0; detX < resampMultiRet->length; detX++ ) {
975 for ( UINT4 k = 0; k < resampMultiRet->data[detX].length; k++ ) {
976 printf( "detInd: %u\n", resampMultiRet->indexList->data[newKFlatCounter].detInd );
977 printf( "sftInd: %u\n", resampMultiRet->indexList->data[newKFlatCounter].sftInd );
978 newKFlatCounter++;
979 }
980 }
981 printf( "newKFlatCounter: %u\n", newKFlatCounter );
982 return XLAL_SUCCESS;
983} // end XLALTestResampPairIndexList
984
985
986/** Construct vector of G_alpha amplitudes for each SFT pair */
987/* This is averaged over unknown cosi and psi */
988/* Allocates memory as well */
990(
991 REAL8Vector **Gamma_ave, /**< Output: vector of aa+bb values */
992 REAL8Vector **Gamma_circ, /**< Output: vector of ab-ba values */
993 SFTPairIndexList *pairIndexList, /**< Input: list of SFT pairs */
994 SFTIndexList *indexList, /**< Input: list of SFTs */
995 MultiAMCoeffs *multiCoeffs /**< Input: AM coefficients */
996)
997{
998
999 UINT4 numPairs = pairIndexList->length;
1000
1001 REAL8Vector *ret1 = NULL;
1002 XLAL_CHECK( ( ret1 = XLALCreateREAL8Vector( numPairs ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector ( %"LAL_UINT4_FORMAT" ) failed.", numPairs );
1003 REAL8Vector *ret2 = NULL;
1004 XLAL_CHECK( ( ret2 = XLALCreateREAL8Vector( numPairs ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector ( %"LAL_UINT4_FORMAT" ) failed.", numPairs );
1005
1006 for ( UINT4 j = 0; j < numPairs; j++ ) {
1007 UINT4 sftNum1 = pairIndexList->data[j].sftNum[0];
1008 UINT4 sftNum2 = pairIndexList->data[j].sftNum[1];
1009 UINT4 detInd1 = indexList->data[sftNum1].detInd;
1010 UINT4 detInd2 = indexList->data[sftNum2].detInd;
1011 UINT4 sftInd1 = indexList->data[sftNum1].sftInd;
1012 UINT4 sftInd2 = indexList->data[sftNum2].sftInd;
1013 ret1->data[j] = 0.1 * ( multiCoeffs->data[detInd1]->a->data[sftInd1]
1014 * multiCoeffs->data[detInd2]->a->data[sftInd2]
1015 + multiCoeffs->data[detInd1]->b->data[sftInd1]
1016 * multiCoeffs->data[detInd2]->b->data[sftInd2] );
1017 ret2->data[j] = 0.1 * ( multiCoeffs->data[detInd1]->a->data[sftInd1]
1018 * multiCoeffs->data[detInd2]->b->data[sftInd2]
1019 - multiCoeffs->data[detInd1]->b->data[sftInd1]
1020 * multiCoeffs->data[detInd2]->a->data[sftInd2] );
1021 }
1022
1023 ( *Gamma_ave ) = ret1;
1024 ( *Gamma_circ ) = ret2;
1025 return XLAL_SUCCESS;
1026}
1027
1028
1029/** test function for RESAMPLING */
1030
1031/** Construct multi-dimensional array of G_L_Y_K_X amplitudes for each SFT pair */
1032/* This is averaged over unknwon cosi and psi */
1033/* Allocates memory as well */
1035(
1036 REAL8Vector **Gamma_ave, /**< Output: vector of aa+bb values */
1037 REAL8Vector **Gamma_circ, /**< Output: vector of ab-ba values */
1038 MultiResampSFTPairMultiIndexList *resampMultiPairIndexList, /**< Input: resamp list of SFT pairs */
1039 MultiAMCoeffs *multiCoeffs /**< Input: AM coefficients */
1040)
1041{
1042 UINT4 numPairs = resampMultiPairIndexList->allPairCount;
1043
1044 REAL8Vector *ret1 = NULL;
1045 XLAL_CHECK( ( ret1 = XLALCreateREAL8Vector( numPairs ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector ( %"LAL_UINT4_FORMAT" ) failed.", numPairs );
1046 REAL8Vector *ret2 = NULL;
1047 XLAL_CHECK( ( ret2 = XLALCreateREAL8Vector( numPairs ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector ( %"LAL_UINT4_FORMAT" ) failed.", numPairs );
1048
1049
1050 /* beware segfault from stack overflow here for large numPairs */
1051 UINT4 detInd1[numPairs];
1052 UINT4 detInd2[numPairs];
1053 UINT4 sftInd1[numPairs];
1054 UINT4 sftInd2[numPairs];
1055
1056 UINT4 pairCount = 0;
1057 for ( UINT4 detX = 0; detX < resampMultiPairIndexList->length; detX++ ) {
1058 for ( UINT4 k = 0; k < resampMultiPairIndexList->data[detX].length; k++ ) {
1059 for ( UINT4 detY = 0; detY < resampMultiPairIndexList->data[detX].data[k].length; detY++ ) {
1060 for ( UINT4 l = 0; l < resampMultiPairIndexList->data[detX].data[k].data[detY].length; l++ ) {
1061 /* This way works if multiCoeffs is allocated for SFTs wrt original
1062 * vector (as is the case) */
1063 detInd1[pairCount] = resampMultiPairIndexList->data[detX].detInd;
1064 detInd2[pairCount] = resampMultiPairIndexList->data[detX].data[k].data[detY].detInd;
1065 sftInd1[pairCount] = resampMultiPairIndexList->data[detX].data[k].sftInd;
1066 sftInd2[pairCount] = resampMultiPairIndexList->data[detX].data[k].data[detY].data[l].sftInd;
1067 ++pairCount;
1068 }
1069 }
1070 }
1071 }
1072 for ( UINT4 j = 0; j < numPairs; j++ ) {
1073 ret1->data[j] = 0.1 * ( multiCoeffs->data[detInd1[j]]->a->data[sftInd1[j]]
1074 * multiCoeffs->data[detInd2[j]]->a->data[sftInd2[j]]
1075 + multiCoeffs->data[detInd1[j]]->b->data[sftInd1[j]]
1076 * multiCoeffs->data[detInd2[j]]->b->data[sftInd2[j]] );
1077 ret2->data[j] = 0.1 * ( multiCoeffs->data[detInd1[j]]->a->data[sftInd1[j]]
1078 * multiCoeffs->data[detInd2[j]]->b->data[sftInd2[j]]
1079 - multiCoeffs->data[detInd1[j]]->b->data[sftInd1[j]]
1080 * multiCoeffs->data[detInd2[j]]->a->data[sftInd2[j]] );
1081 }
1082
1083 ( *Gamma_ave ) = ret1;
1084 ( *Gamma_circ ) = ret2;
1085 return XLAL_SUCCESS;
1086} // end XLALCalculateCrossCorrGammasResamp
1087
1088
1089/** test function for RESAMPLING with tShort*/
1090/** Construct multi-dimensional array of G_L_Y_K_X amplitudes for each SFT pair */
1091/* This is averaged over unknwon cosi and psi */
1092/* Allocates memory as well */
1094(
1095 REAL8Vector **Gamma_ave, /**< Output: vector of aa+bb values */
1096 REAL8Vector **Gamma_circ, /**< Output: vector of ab-ba values */
1097 MultiResampSFTPairMultiIndexList *resampMultiPairIndexList, /**< Input: resamp list of SFT pairs */
1098 MultiAMCoeffs *multiCoeffs /**< Input: AM coefficients */
1099)
1100{
1101 UINT4 numPairs = resampMultiPairIndexList->allPairCount;
1102
1103 REAL8Vector *ret1 = NULL;
1104 XLAL_CHECK( ( ret1 = XLALCreateREAL8Vector( numPairs ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector ( %"LAL_UINT4_FORMAT" ) failed.", numPairs );
1105 REAL8Vector *ret2 = NULL;
1106 XLAL_CHECK( ( ret2 = XLALCreateREAL8Vector( numPairs ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector ( %"LAL_UINT4_FORMAT" ) failed.", numPairs );
1107
1108 REAL4 eleMultiCoeffs1a = 0;
1109 REAL4 eleMultiCoeffs2a = 0;
1110 REAL4 eleMultiCoeffs1b = 0;
1111 REAL4 eleMultiCoeffs2b = 0;
1112
1113 REAL4 sciMultiCoeffs1a = 0;
1114 REAL4 sciMultiCoeffs2a = 0;
1115 REAL4 sciMultiCoeffs1b = 0;
1116 REAL4 sciMultiCoeffs2b = 0;
1117
1118 /* beware segfault from stack overflow here for large numPairs */
1119 REAL4 castSciFlag1[numPairs];
1120 REAL4 castSciFlag2[numPairs];
1121
1122 UINT4 detInd1[numPairs];
1123 UINT4 detInd2[numPairs];
1124 UINT4 sftInd1[numPairs];
1125 UINT4 sftInd2[numPairs];
1126
1127 UINT4 pairCount = 0;
1128 for ( UINT4 detX = 0; detX < resampMultiPairIndexList->length; detX++ ) {
1129 for ( UINT4 k = 0; k < resampMultiPairIndexList->data[detX].length; k++ ) {
1130 for ( UINT4 detY = 0; detY < resampMultiPairIndexList->data[detX].data[k].length; detY++ ) {
1131 for ( UINT4 l = 0; l < resampMultiPairIndexList->data[detX].data[k].data[detY].length; l++ ) {
1132 /* This way works if multiCoeffs is allocated for SFTs wrt original
1133 * vector (as is the case) */
1134 detInd1[pairCount] = resampMultiPairIndexList->data[detX].detInd;
1135 detInd2[pairCount] = resampMultiPairIndexList->data[detX].data[k].data[detY].detInd;
1136 sftInd1[pairCount] = resampMultiPairIndexList->data[detX].data[k].sftInd;
1137 sftInd2[pairCount] = resampMultiPairIndexList->data[detX].data[k].data[detY].data[l].sftInd;
1138 /* Can use the science flags; will produce slightly different
1139 * results due to sharper edges than A and B time series;
1140 * however, by themselves, A and B are zero-padded and so
1141 * can handle gaps. */
1142 //castSciFlag1[pairCount] = resampMultiPairIndexList->data[detX].data[k].sciFlag;
1143 //castSciFlag2[pairCount] = resampMultiPairIndexList->data[detX].data[k].data[detY].data[l].sciFlag;
1144 castSciFlag1[pairCount] = 1.0;
1145 castSciFlag2[pairCount] = 1.0;
1146 ++pairCount;
1147 }
1148 }
1149 }
1150 }
1151 for ( UINT4 j = 0; j < numPairs; j++ ) {
1152 eleMultiCoeffs1a = multiCoeffs->data[detInd1[j]]->a->data[sftInd1[j]];
1153 eleMultiCoeffs2a = multiCoeffs->data[detInd2[j]]->a->data[sftInd2[j]];
1154 eleMultiCoeffs1b = multiCoeffs->data[detInd1[j]]->b->data[sftInd1[j]];
1155 eleMultiCoeffs2b = multiCoeffs->data[detInd2[j]]->b->data[sftInd2[j]];
1156
1157 sciMultiCoeffs1a = eleMultiCoeffs1a * castSciFlag1[j];
1158 sciMultiCoeffs2a = eleMultiCoeffs2a * castSciFlag2[j];
1159 sciMultiCoeffs1b = eleMultiCoeffs1b * castSciFlag1[j];
1160 sciMultiCoeffs2b = eleMultiCoeffs2b * castSciFlag2[j];
1161 ret1->data[j] = 0.1 * ( sciMultiCoeffs1a
1162 * sciMultiCoeffs2a
1163 + sciMultiCoeffs1b
1164 * sciMultiCoeffs2b );
1165 ret2->data[j] = 0.1 * ( sciMultiCoeffs1a
1166 * sciMultiCoeffs2b
1167 - sciMultiCoeffs1b
1168 * sciMultiCoeffs2a );
1169 }
1170
1171 ( *Gamma_ave ) = ret1;
1172 ( *Gamma_circ ) = ret2;
1173 return XLAL_SUCCESS;
1174} // end XLALCalculateCrossCorrGammasResampShort
1175
1176
1177/** Combine G_alpha amplitudes for SFT pairs into amplitudes for Tshort pairs */
1178/* Allocates memory as well */
1180(
1181 REAL8Vector **resampGamma, /**< Output: vector of combined values, one per Tshort pair */
1182 REAL8Vector *Gamma, /**< Input: vector of values, on per SFT pair */
1183 UINT4VectorSequence *sftPairForTshortPair, /**< Input: list of SFT pair indices for each Tshort pair */
1184 REAL8 Tsft, /**< [in] duration of a single SFT */
1185 REAL8 Tshort /**< [in] resampling Tshort */
1186)
1187{
1188
1189 UINT4 numTshortPairs = sftPairForTshortPair->length;
1190 UINT4 maxAlphaInReAlpha = sftPairForTshortPair->vectorLength;
1191 REAL8Vector *ret = NULL;
1192 XLAL_CHECK( ( ret = XLALCreateREAL8Vector( numTshortPairs ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector ( %"LAL_UINT4_FORMAT" ) failed.", numTshortPairs ) ;
1193 XLAL_CHECK( Gamma->length <= ( numTshortPairs * maxAlphaInReAlpha ),
1195 "Too many values in Gamma vector: numGammas=%"LAL_UINT4_FORMAT", numTshortPairs==%"LAL_UINT4_FORMAT", maxAlphaInReAlpha==%"LAL_UINT4_FORMAT"\n",
1196 Gamma->length, numTshortPairs, maxAlphaInReAlpha );
1197
1198 /* We assume these are Gamma-hats, which include a factor of Tsft or Tshort from the normalized antenna patterns */
1199 REAL8 normFactor = ( Tsft / Tshort );
1200
1201 for ( UINT4 reAlpha = 0; reAlpha < numTshortPairs; reAlpha++ ) {
1202 REAL8 thisGammaSq = 0.;
1203 for ( UINT4 alphaInReAlpha = 0; alphaInReAlpha < maxAlphaInReAlpha; alphaInReAlpha++ ) {
1204 UINT4 alpha = sftPairForTshortPair->data[reAlpha * maxAlphaInReAlpha + alphaInReAlpha];
1205 if ( alpha == LAL_UINT4_MAX ) {
1206 break;
1207 }
1208 thisGammaSq += SQUARE( ( Gamma->data[alpha] ) );
1209 }
1210 thisGammaSq *= SQUARE( normFactor );
1211 ret->data[reAlpha] = sqrt( thisGammaSq );
1212 }
1213
1214 ( *resampGamma ) = ret;
1215 return XLAL_SUCCESS;
1216}
1217
1218
1219/** Calculate multi-bin cross-correlation statistic */
1220/* This assumes rectangular or nearly-rectangular windowing */
1222(
1223 REAL8 *ccStat, /**< Output: cross-correlation statistic rho */
1224 REAL8 *evSquared, /**< Output: (E[rho]/h0^2)^2 */
1225 REAL8Vector *curlyGAmp, /**< Input: Amplitude of curly G for each pair */
1226 COMPLEX8Vector *expSignalPhases, /**< Input: Phase of signal for each SFT */
1227 UINT4Vector *lowestBins, /**< Input: Bin index to start with for each SFT */
1228 REAL8VectorSequence *sincList, /**< Input: input the sinc factors*/
1229 SFTPairIndexList *sftPairs, /**< Input: flat list of SFT pairs */
1230 SFTIndexList *sftIndices, /**< Input: flat list of SFTs */
1231 MultiSFTVector *inputSFTs, /**< Input: SFT data */
1232 MultiNoiseWeights *multiWeights, /**< Input: nomalizeation factor S^-1 & weights for each SFT */
1233 UINT4 numBins /**< Input Number of frequency bins to be taken into calc */
1234)
1235{
1236
1237 UINT4 numSFTs = sftIndices->length;
1238 if ( expSignalPhases->length != numSFTs
1239 || lowestBins->length != numSFTs
1240 || sincList->length != numSFTs ) {
1241 XLALPrintError( "Lengths of SFT-indexed lists don't match!" );
1243 }
1244
1245 UINT4 numPairs = sftPairs->length;
1246 if ( curlyGAmp->length != numPairs ) {
1247 XLALPrintError( "Lengths of pair-indexed lists don't match!" );
1249 }
1250 REAL8 nume = 0;
1251 REAL8 curlyGSqr = 0;
1252 *ccStat = 0.0;
1253 *evSquared = 0.0;
1254 for ( UINT4 alpha = 0; alpha < numPairs; alpha++ ) {
1255 UINT4 sftNum1 = sftPairs->data[alpha].sftNum[0];
1256 UINT4 sftNum2 = sftPairs->data[alpha].sftNum[1];
1257
1258 XLAL_CHECK( ( sftNum1 < numSFTs ) && ( sftNum2 < numSFTs ),
1260 "SFT pair asked for SFT index off end of list:\n alpha=%"LAL_UINT4_FORMAT", sftNum1=%"LAL_UINT4_FORMAT", sftNum2=%"LAL_UINT4_FORMAT", numSFTs=%"LAL_UINT4_FORMAT"\n",
1261 alpha, sftNum1, sftNum2, numSFTs );
1262
1263 UINT4 detInd1 = sftIndices->data[sftNum1].detInd;
1264 UINT4 detInd2 = sftIndices->data[sftNum2].detInd;
1265
1266 XLAL_CHECK( ( detInd1 < inputSFTs->length )
1267 && ( detInd2 < inputSFTs->length ),
1269 "SFT asked for detector index off end of list:\n sftNum1=%"LAL_UINT4_FORMAT", sftNum2=%"LAL_UINT4_FORMAT", detInd1=%"LAL_UINT4_FORMAT", detInd2=%"LAL_UINT4_FORMAT", inputSFTs->length=%d\n",
1270 sftNum1, sftNum2, detInd1, detInd2, inputSFTs->length );
1271
1272 UINT4 sftInd1 = sftIndices->data[sftNum1].sftInd;
1273 UINT4 sftInd2 = sftIndices->data[sftNum2].sftInd;
1274
1275 XLAL_CHECK( ( sftInd1 < inputSFTs->data[detInd1]->length )
1276 && ( sftInd2 < inputSFTs->data[detInd2]->length ),
1278 "SFT asked for SFT index off end of list:\n sftNum1=%"LAL_UINT4_FORMAT", sftNum2=%"LAL_UINT4_FORMAT", detInd1=%"LAL_UINT4_FORMAT", detInd2=%"LAL_UINT4_FORMAT", sftInd1=%"LAL_UINT4_FORMAT", sftInd2=%"LAL_UINT4_FORMAT", inputSFTs->data[detInd1]->length=%d, inputSFTs->data[detInd2]->length=%d\n",
1279 sftNum1, sftNum2, detInd1, detInd2, sftInd1, sftInd2,
1280 inputSFTs->data[detInd1]->length,
1281 inputSFTs->data[detInd2]->length );
1282
1283 COMPLEX8 *dataArray1 = inputSFTs->data[detInd1]->data[sftInd1].data->data;
1284 COMPLEX8 *dataArray2 = inputSFTs->data[detInd2]->data[sftInd2].data->data;
1285 UINT4 lenDataArray1 = inputSFTs->data[detInd1]->data[sftInd1].data->length;
1286 UINT4 lenDataArray2 = inputSFTs->data[detInd2]->data[sftInd2].data->length;
1287 COMPLEX8 GalphaCC = curlyGAmp->data[alpha]
1288 * expSignalPhases->data[sftNum1]
1289 * conj( expSignalPhases->data[sftNum2] );
1290 INT4 baseCCSign = 1; /* Alternating sign is (-1)**(k1-k2) */
1291 if ( ( ( lowestBins->data[sftNum1] - lowestBins->data[sftNum2] ) % 2 ) != 0 ) {
1292 baseCCSign = -1;
1293 }
1294
1295 UINT4 lowestBin1 = lowestBins->data[sftNum1];
1296 XLAL_CHECK( ( ( lowestBin1 + numBins - 1 ) < lenDataArray1 ),
1298 "Loop would run off end of array:\n lowestBin1=%d, numBins=%d, len(dataArray1)=%d\n",
1299 lowestBin1, numBins, lenDataArray1 );
1300 for ( UINT4 j = 0; j < numBins; j++ ) {
1301 COMPLEX8 data1 = dataArray1[lowestBin1 + j];
1302
1303 INT4 ccSign = baseCCSign;
1304 UINT4 lowestBin2 = lowestBins->data[sftNum2];
1305 XLAL_CHECK( ( ( lowestBin2 + numBins - 1 ) < lenDataArray2 ),
1307 "Loop would run off end of array:\n lowestBin2=%d, numBins=%d, len(dataArray2)=%d\n",
1308 lowestBin2, numBins, lenDataArray2 );
1309 for ( UINT4 k = 0; k < numBins; k++ ) {
1310 COMPLEX8 data2 = dataArray2[lowestBins->data[sftNum2] + k];
1311 REAL8 sincFactor = 1;
1312
1313 sincFactor = sincList->data[sftNum1 * numBins + j] * sincList->data[sftNum2 * numBins + k];
1314 nume += ccSign * sincFactor * creal( GalphaCC * conj( data1 ) * data2 );
1315 /*nume += creal ( GalphaCC * ccSign * sincFactor * conj(data1) * data2 );=> abs(GalphaCC)*abs(data1)*abs(data2) * cos(arg(GalphaCC)-arg(data1)+arg(data2))*/
1316 /*multiWeights->data[detInd1]->data[sftNum1] * multiWeights->data[detInd2]->data[sftNum2] **/
1317 REAL8 GalphaAmp = curlyGAmp->data[alpha] * sincFactor ;
1318 /** multiWeights->data[detInd1]->data[sftNum1] * multiWeights->data[detInd2]->data[sftNum2]*/
1319 curlyGSqr += SQUARE( GalphaAmp );
1320 ccSign *= -1;
1321 }
1322 baseCCSign *= -1;
1323 }
1324 }
1325 if ( curlyGSqr == 0.0 ) {
1326 *evSquared = 0.0;
1327 *ccStat = 0.0;
1328 } else {
1329 *evSquared = 8 * SQUARE( multiWeights->Sinv_Tsft ) * curlyGSqr;
1330 *ccStat = 4 * multiWeights->Sinv_Tsft * nume / sqrt( *evSquared );
1331 }
1332 return XLAL_SUCCESS;
1333}
1334
1335
1336/** Calculate multi-bin cross-correlation statistic using resampling */
1337/* This assumes rectangular or nearly-rectangular windowing */
1339(
1340 REAL8Vector *restrict ccStatVector, /**< [out] vector cross-correlation statistic rho */
1341 REAL8Vector *restrict evSquaredVector, /**< [out] vector (E[rho]/h0^2) */
1342 REAL8Vector *restrict numeEquivAve, /**< [out] vector for intermediate average statistic */
1343 REAL8Vector *restrict numeEquivCirc, /**< [out] vector for intermediate circular statistic */
1344 const REAL8Vector *restrict resampCurlyGAmp, /**< [in] amplitude of curly G for each L_Y_K_X (alpha-indexed) */
1345 const MultiResampSFTPairMultiIndexList *restrict resampMultiPairs, /**< [in] resamp multi list of SFT pairs */
1346 const MultiNoiseWeights *restrict multiWeights, /**< [in] normalization factor S^-1 & weights for each SFT */
1347 const PulsarDopplerParams *restrict binaryTemplateSpacings, /**< [in] Set of spacings for search */
1348 const PulsarDopplerParams *restrict dopplerpos, /**< [in] Doppler point to search */
1349 const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_a, /**< [in] resampled time series A */
1350 const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_b, /**< [in] resampled time series B */
1351 ResampCrossCorrWorkspace *restrict ws, /**< [in/out] first workspace */
1352 COMPLEX8 *restrict ws1KFaX_k, /**< [in/out] holder for detector 1 Fa */
1353 COMPLEX8 *restrict ws1KFbX_k, /**< [in/out] holder for detector 1 Fb */
1354 COMPLEX8 *restrict ws2LFaX_k, /**< [in/out] holder for detector 2 Fa */
1355 COMPLEX8 *restrict ws2LFbX_k /**< [in/out] holder for detector 2 Fb */
1356)
1357{
1358 XLAL_CHECK( ws != NULL, XLAL_EINVAL );
1359 XLAL_CHECK( ws1KFaX_k != NULL, XLAL_EINVAL );
1360 XLAL_CHECK( ws1KFbX_k != NULL, XLAL_EINVAL );
1361 XLAL_CHECK( ws2LFaX_k != NULL, XLAL_EINVAL );
1362 XLAL_CHECK( ws2LFbX_k != NULL, XLAL_EINVAL );
1363
1364 /* Initialize nume holders for resamp */
1365 REAL8 curlyEquivGSqrSum = 0;
1366 for ( UINT4 j = 0; j < ws->numFreqBinsOut; j++ ) {
1367 numeEquivAve->data[j] = 0;
1368 numeEquivCirc->data[j] = 0;
1369 ccStatVector->data[j] = 0;
1370 evSquaredVector->data[j] = 0;
1371 }
1372
1373 const REAL8 dt_SRC = multiTimeSeries_SRC_b->data[0]->deltaT;
1374 const REAL8 SRCsampPerTcoh = resampMultiPairs->Tshort / dt_SRC;
1375
1376 /* MAIN LOOP (RESAMPLING) */
1377 for ( UINT4 detX = 0; detX < resampMultiPairs->length; detX++ ) {
1378 for ( UINT4 sftK = 0; sftK < resampMultiPairs->data[detX].length; sftK++ ) {
1379 if ( ( XLALComputeFaFb_CrossCorrResamp( ws, ws1KFaX_k, ws1KFbX_k, resampMultiPairs, multiTimeSeries_SRC_a, multiTimeSeries_SRC_b, dopplerpos, binaryTemplateSpacings, SRCsampPerTcoh, detX, sftK, 0, FALSE ) ) != XLAL_SUCCESS ) {
1380 LogPrintf( LOG_CRITICAL, "%s: XLALComputeFaFb_CrossCorrResamp() failed with errno=%d\n", __func__, xlalErrno );
1382 }
1383 for ( UINT4 detY = 0; detY < resampMultiPairs->data[detX].data[sftK].length; detY++ ) {
1384 if ( ( XLALComputeFaFb_CrossCorrResamp( ws, ws2LFaX_k, ws2LFbX_k, resampMultiPairs, multiTimeSeries_SRC_a, multiTimeSeries_SRC_b, dopplerpos, binaryTemplateSpacings, SRCsampPerTcoh, detX, sftK, detY, TRUE ) ) != XLAL_SUCCESS ) {
1385 LogPrintf( LOG_CRITICAL, "%s: XLALComputeFaFb_CrossCorrResamp() failed with errno=%d\n", __func__, xlalErrno );
1387 }
1388 /* -...-...-...- NEW CORE -...-...-...- */
1389 for ( UINT8 j = 0; j < ws->numFreqBinsOut; j++ ) {
1390 numeEquivAve->data[j] += creal( 0.1 * ( conj( ws1KFaX_k[j] ) * ws2LFaX_k[j] + conj( ws1KFbX_k[j] ) * ws2LFbX_k[j] ) );
1391 /* Can use for circular polarization:
1392 * numeEquivCirc->data[j] += creal(0.1 * ( conj(ws1KFaX_k[j]) * ws2LFbX_k[j] - conj(ws1KFbX_k[j]) * ws2LFaX_k[j] ) ); */
1393 }
1394 /* -...-...-...- END NEW CORE -...-...-...- */
1395 } /* detY */
1396 } /* sftK */
1397 } /* detX */ /* end main loop (NOW WITH RESAMPLING) */
1398
1399 /* ENDING RESAMPLING SECTION */
1400
1401 /* Normalization factors moved outside of core: */
1402 for ( UINT4 alpha = 0; alpha < resampMultiPairs->allPairCount; alpha++ ) {
1403 REAL8 GalphaResampAmp = resampCurlyGAmp->data[alpha];
1404 curlyEquivGSqrSum += SQUARE( GalphaResampAmp );
1405 }
1406 /* Because FstatInput in the outer for-loop read in and normalized
1407 * sfts according to their original SFT length, and that determines
1408 * the scale of Fa, Fb, and therefore numeEquivAve (according to
1409 * to Wiener-Kinchine, E[|data|^2] = Tsft * Sn / 2 for spectral
1410 * noise Sn, and compare XLALNormalizeMultiSFTVect and
1411 * XLALNormalizeSFT we need to access the original
1412 * multi-weights S inverse Tsft for normalize numeEquivAve. However,
1413 * we use the modified multi-weights S inverse Tsft for curlyEquivGSqrSum,
1414 * because that was created with Tshort and the modified S inverse Tsft.
1415 * Note that
1416 * multiWeights->Sinv_Tsft =...
1417 * sum_dets(sum_sfts( length_sft/(running median_sft ) ) ),
1418 * ergo 1/Sinv_Tsft is the harmonic mean of running median noise.
1419 * Therefore this normalization should be valid even when used with
1420 * detectors with different noise levels.
1421 */
1422 const REAL8 originalMultiWeightsSinvTsft = multiWeights->Sinv_Tsft * ( resampMultiPairs->Tsft / resampMultiPairs->Tshort );
1423 for ( UINT8 j = 0; j < ws->numFreqBinsOut; j++ ) {
1424 evSquaredVector->data[j] = 8 * SQUARE( multiWeights->Sinv_Tsft ) * curlyEquivGSqrSum;
1425 ccStatVector->data[j] = 4 * originalMultiWeightsSinvTsft * numeEquivAve->data[j] / sqrt( evSquaredVector->data[j] );
1426 }
1427 return XLAL_SUCCESS;
1428} // end XLALCalculatePulsarCrossCorrStatisticResamp
1429
1430
1431/** calculate signal phase derivatives wrt Doppler coords, for each SFT */
1432/* allocates memory as well */
1434(
1435 REAL8VectorSequence **phaseDerivs, /**< Output: dPhi_K/dlambda_i; i is the "sequence" index, K is the "vector" index */
1436 const PulsarDopplerParams *dopplerPoint, /**< Input: pulsar/binary orbit paramaters */
1437 const EphemerisData *edat, /**< Input: Earth/Sun ephemeris */
1438 SFTIndexList *indexList, /**< Input: list of SFT indices */
1439 MultiSSBtimes *multiTimes, /**< Input: barycentered times of SFTs */
1440 const DopplerCoordinateSystem *coordSys /**< Input: coordinates with which to differentiate */
1441)
1442{
1443 XLAL_CHECK( dopplerPoint != NULL, XLAL_EINVAL );
1444 XLAL_CHECK( edat != NULL, XLAL_EINVAL );
1445 XLAL_CHECK( indexList != NULL, XLAL_EINVAL );
1446 XLAL_CHECK( multiTimes != NULL, XLAL_EINVAL );
1447 XLAL_CHECK( coordSys != NULL, XLAL_EINVAL );
1448
1449 const UINT4 numCoords = coordSys->dim;
1450 const UINT4 numSFTs = indexList->length;
1451
1452 REAL8VectorSequence *ret = NULL;
1453
1454 XLAL_CHECK( ( ret = XLALCreateREAL8VectorSequence( numCoords, numSFTs ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8VectorSequence ( %"LAL_UINT4_FORMAT", %"LAL_UINT4_FORMAT" ) failed.", numCoords, numSFTs );
1455
1456 for ( UINT4 coordNum = 0; coordNum < numCoords; coordNum++ ) {
1457 for ( UINT4 sftNum = 0; sftNum < numSFTs; sftNum++ ) {
1458 UINT4 detInd = indexList->data[sftNum].detInd;
1459 UINT4 sftInd = indexList->data[sftNum].sftInd;
1460 SSBtimes *times;
1461 times = multiTimes->data[detInd];
1462 REAL8 refTime8 = XLALGPSGetREAL8( &( times->refTime ) );
1463 UINT4 numSFTsDet = times->DeltaT->length;
1464 XLAL_CHECK( ( sftInd < numSFTsDet ), XLAL_EINVAL, "SFT asked for SFT index off end of list:\n sftNum=%"LAL_UINT4_FORMAT", detInd=%"LAL_UINT4_FORMAT", sftInd=%"LAL_UINT4_FORMAT", numSFTsDet=%"LAL_UINT4_FORMAT"\n", sftNum, detInd, sftInd, numSFTsDet );
1465 REAL8 tSSB = refTime8 + times->DeltaT->data[sftInd];
1466 ret->data[coordNum * numSFTs + sftNum] = XLALComputePhaseDerivative( tSSB, dopplerPoint, ( coordSys->coordIDs[coordNum] ), edat, NULL, 0 );
1467 XLAL_CHECK( xlalErrno == 0, XLAL_EFUNC, "XLALComputePhaseDerivative() failed with xlalErrno = %d\n", xlalErrno );
1468 }
1469 }
1470
1471 ( *phaseDerivs ) = ret;
1472
1473 return XLAL_SUCCESS;
1474
1475}
1476
1477
1478/** (test function) MODIFIED for Tshort */
1479/** calculate signal phase derivatives wrt Doppler coords, for each SFT */
1480/* allocates memory as well */
1482(
1483 REAL8VectorSequence **resampPhaseDerivs, /**< [out] dPhi_K/dlambda_i; i is the "sequence" index, K is the "vector" index */
1484 const PulsarDopplerParams *dopplerPoint, /**< [in] pulsar/binary orbit paramaters */
1485 const EphemerisData *edat, /**< [in Earth/Sun ephemeris */
1486 SFTIndexList *indexList, /**< [in] list of SFT indices */
1487 MultiResampSFTPairMultiIndexList *resampMultiPairs, /**< [in] resamp list of SFT pairs */
1488 MultiSSBtimes *multiTimes, /**< [in] barycentered times of SFTs */
1489 const DopplerCoordinateSystem *coordSys /**< [in] coordinates with which to differentiate */
1490)
1491{
1492 /* Note: the use of tSSBApprox rather than the true tSSB contributes
1493 * a very small but observable difference between this function and
1494 * a correctly-configured call to the normal phase derivatives function. */
1495 XLAL_CHECK( dopplerPoint != NULL, XLAL_EINVAL );
1496 XLAL_CHECK( edat != NULL, XLAL_EINVAL );
1497 XLAL_CHECK( indexList != NULL, XLAL_EINVAL );
1498 XLAL_CHECK( resampMultiPairs != NULL, XLAL_EINVAL );
1499 XLAL_CHECK( multiTimes != NULL, XLAL_EINVAL );
1500 XLAL_CHECK( coordSys != NULL, XLAL_EINVAL );
1501
1502 /* The actual SFT indices from the original catalog are no longer
1503 * relevant; in resampling, we use new SFTs. These are not evenly
1504 * spaced in the detector frame, but for the purpose of taking the
1505 * values for gamma ave that is needed for the metric, and hence
1506 * for the returned resampPhaseDerivs, this should average out. */
1507 const UINT4 numCoords = coordSys->dim;
1508 const UINT4 numShorts = resampMultiPairs->sftTotalCount;
1509 const REAL8 Tshort = resampMultiPairs->Tshort;
1510 printf( "numShorts: %u\n", numShorts );
1511
1512 REAL8VectorSequence *retNew = NULL;
1513 XLAL_CHECK( ( retNew = XLALCreateREAL8VectorSequence( numCoords, numShorts ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8VectorSequence ( %"LAL_UINT4_FORMAT", %"LAL_UINT4_FORMAT" ) failed.", numCoords, numShorts );
1514
1515 for ( UINT4 coordNum = 0; coordNum < numCoords; coordNum++ ) {
1516 for ( UINT4 detX = 0; detX < resampMultiPairs->length; detX++ ) {
1517 for ( UINT4 k = 0; k < resampMultiPairs->data[detX].length; k++ ) {
1518 /* Both detectors' resampled time series have the same start time now,
1519 * or should be aligned to be so. We just need the nominal time in SSB,
1520 * so we could probably calculate the start time of the first SFT and
1521 * add the number of Tshort segments that follow */
1522 REAL8 startTime8 = XLALGPSGetREAL8( &( multiTimes->data[0]->refTime ) ) + multiTimes->data[0]->DeltaT->data[0];
1523 /* Cannot use Tshort * shortNum -- it needs to be the number
1524 * within THAT detector */
1525 UINT4 shortSFTIndOwn = resampMultiPairs->data[detX].data[k].sftInd;
1526 UINT4 shortSFTInd = resampMultiPairs->data[detX].data[k].flatInd;
1527 REAL8 tSSBApprox = startTime8 + Tshort * shortSFTIndOwn;
1528 retNew->data[coordNum * numShorts + shortSFTInd] = XLALComputePhaseDerivative( tSSBApprox, dopplerPoint, ( coordSys->coordIDs[coordNum] ), edat, NULL, 0 );
1529 XLAL_CHECK( xlalErrno == 0, XLAL_EFUNC, "XLALComputePhaseDerivative() failed with xlalErrno = %d\n", xlalErrno );
1530 }
1531 }
1532 }
1533 ( *resampPhaseDerivs ) = retNew;
1534
1535 return XLAL_SUCCESS;
1536} /* end XLALCalculateCrossCorrPhaseDerivativesShort */
1537
1538
1539/** calculate phase metric for CW cross-correlation search, as well as vector used for parameter offsets */
1540/** This calculates the metric defined in (4.7) of Whelan et al 2015 and the parameter offset epsilon_i */
1541/** (not including the cosi-dependent prefactor) in defined in (4.8) */
1542/* allocates memory as well */
1544(
1545 gsl_matrix **g_ij, /**< Output: parameter space metric */
1546 gsl_vector **eps_i, /**< Output: parameter offset vector from (4.8) of WSZP15 */
1547 REAL8 *sumGammaSq, /**< Output: sum of (Gamma_ave)^2 for normalization and sensitivity */
1548 const REAL8VectorSequence *phaseDerivs, /**< Input: dPhi_K/dlambda_i; i is the "sequence" index, K is the "vector" */
1549 const SFTPairIndexList *pairIndexList, /**< Input: list of SFT pairs */
1550 const REAL8Vector *Gamma_ave, /**< Input: vector of aa+bb values */
1551 const REAL8Vector *Gamma_circ, /**< Input: vector of ab-ba values */
1552 const DopplerCoordinateSystem *coordSys /**< Input: coordinate directions for metric */
1553)
1554{
1555 XLAL_CHECK( sumGammaSq != NULL, XLAL_EINVAL );
1556 XLAL_CHECK( phaseDerivs != NULL, XLAL_EINVAL );
1557 XLAL_CHECK( pairIndexList != NULL, XLAL_EINVAL );
1558 XLAL_CHECK( Gamma_ave != NULL, XLAL_EINVAL );
1559 XLAL_CHECK( Gamma_circ != NULL, XLAL_EINVAL );
1560 XLAL_CHECK( coordSys != NULL, XLAL_EINVAL );
1561
1562 const UINT4 numCoords = coordSys->dim;
1563 XLAL_CHECK( ( phaseDerivs->length == numCoords ), XLAL_EINVAL, "Length mismatch: phaseDerivs->length=%"LAL_UINT4_FORMAT", numCoords=%"LAL_UINT4_FORMAT"\n", phaseDerivs->length, numCoords );
1564 const UINT4 numSFTs = phaseDerivs->vectorLength;
1565 const UINT4 numPairs = pairIndexList->length;
1566 XLAL_CHECK( ( Gamma_ave->length == numPairs ), XLAL_EINVAL, "Length mismatch: Gamma_ave->length=%"LAL_UINT4_FORMAT", numPairs=%"LAL_UINT4_FORMAT"\n", Gamma_ave->length, numPairs );
1567 XLAL_CHECK( ( Gamma_circ->length == numPairs ), XLAL_EINVAL, "Length mismatch: Gamma_circ->length=%"LAL_UINT4_FORMAT", numPairs=%"LAL_UINT4_FORMAT"\n", Gamma_circ->length, numPairs );
1568
1569 /* ---------- prepare output metric ---------- */
1570 gsl_matrix *ret_g;
1571 if ( ( ret_g = gsl_matrix_calloc( numCoords, numCoords ) ) == NULL ) {
1572 XLALPrintError( "%s: gsl_matrix_calloc(%d, %d) failed.\n\n", __func__, numCoords, numCoords );
1574
1575 }
1576 gsl_vector *ret_e;
1577 if ( ( ret_e = gsl_vector_calloc( numCoords ) ) == NULL ) {
1578 XLALPrintError( "%s: gsl_vector_calloc(%d) failed.\n\n", __func__, numCoords );
1580 }
1581
1582 REAL8Vector *dDeltaPhi_i = NULL;
1583 REAL8 denom = 0;
1584 XLAL_CHECK( ( dDeltaPhi_i = XLALCreateREAL8Vector( numCoords ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector ( %"LAL_UINT4_FORMAT" ) failed.", numCoords );
1585 for ( UINT4 pairNum = 0; pairNum < numPairs; pairNum++ ) {
1586 UINT4 sftNum1 = pairIndexList->data[pairNum].sftNum[0];
1587 UINT4 sftNum2 = pairIndexList->data[pairNum].sftNum[1];
1588 REAL8 aveWeight = SQUARE( Gamma_ave->data[pairNum] );
1589 denom += aveWeight;
1590 REAL8 circWeight = Gamma_ave->data[pairNum] * Gamma_circ->data[pairNum];
1591 for ( UINT4 i = 0; i < numCoords; i++ ) {
1592 dDeltaPhi_i->data[i] = phaseDerivs->data[i * numSFTs + sftNum1] - phaseDerivs->data[i * numSFTs + sftNum2];
1593 REAL8 epsi = gsl_vector_get( ret_e, i );
1594 epsi += circWeight * dDeltaPhi_i->data[i];
1595 gsl_vector_set( ret_e, i, epsi );
1596 for ( UINT4 j = 0; j <= i; j++ ) { /* Doing the loop this way ensures dDeltaPhi_i[j] has been set */
1597 REAL8 gij = gsl_matrix_get( ret_g, i, j );
1598 gij += aveWeight * dDeltaPhi_i->data[i] * dDeltaPhi_i->data[j];
1599 gsl_matrix_set( ret_g, i, j, gij );
1600 }
1601 }
1602 }
1603
1604 XLALDestroyREAL8Vector( dDeltaPhi_i );
1605
1606 for ( UINT4 i = 0; i < numCoords; i++ ) {
1607 REAL8 epsi = gsl_vector_get( ret_e, i );
1608 epsi /= denom;
1609 gsl_vector_set( ret_e, i, epsi );
1610 for ( UINT4 j = 0; j <= i; j++ ) { /* Doing the loop the same way as above */
1611 REAL8 gij = gsl_matrix_get( ret_g, i, j );
1612 gij /= ( 2.*denom );
1613 gsl_matrix_set( ret_g, i, j, gij );
1614 if ( i != j ) {
1615 gsl_matrix_set( ret_g, j, i, gij );
1616 }
1617 }
1618 }
1619
1620 ( *g_ij ) = ret_g;
1621 ( *eps_i ) = ret_e;
1622 ( *sumGammaSq ) = denom;
1623
1624 return XLAL_SUCCESS;
1625
1626}
1627
1628
1629/** (test function) Redesigning to use Tshort instead */
1630/** calculate phase metric for CW cross-correlation search, as well as vector used for parameter offsets */
1631/** This calculates the metric defined in (4.7) of Whelan et al 2015 and the parameter offset epsilon_i */
1632/** (not including the cosi-dependent prefactor) in defined in (4.8) */
1633/* allocates memory as well */
1635(
1636 gsl_matrix **g_ij, /**< [out] parameter space metric */
1637 gsl_vector **eps_i, /**< [out] parameter offset vector from (4.8) of WSZP15 */
1638 REAL8 *sumGammaSq, /**< [out] sum of (Gamma_ave)^2 for normalization and sensitivity */
1639 const REAL8VectorSequence *phaseDerivs, /**< [in] dPhi_K/dlambda_i; i is the "sequence" index, K is the "vector" */
1640 const MultiResampSFTPairMultiIndexList *resampMultiPairs, /**< [in] resamp multi list of SFT pairs */
1641 const REAL8Vector *Gamma_ave, /**< [in]: vector of aa+bb values */
1642 const REAL8Vector *Gamma_circ, /**< [in] vector of ab-ba values */
1643 const DopplerCoordinateSystem *coordSys /**< [in] coordinate directions for metric */
1644)
1645{
1646 XLAL_CHECK( sumGammaSq != NULL, XLAL_EINVAL );
1647 XLAL_CHECK( phaseDerivs != NULL, XLAL_EINVAL );
1648 XLAL_CHECK( Gamma_ave != NULL, XLAL_EINVAL );
1649 XLAL_CHECK( Gamma_circ != NULL, XLAL_EINVAL );
1650 XLAL_CHECK( coordSys != NULL, XLAL_EINVAL );
1651
1652 const UINT4 numCoords = coordSys->dim;
1653 XLAL_CHECK( ( phaseDerivs->length == numCoords ), XLAL_EINVAL, "Length mismatch: phaseDerivs->length=%"LAL_UINT4_FORMAT", numCoords=%"LAL_UINT4_FORMAT"\n", phaseDerivs->length, numCoords );
1654 const UINT4 numSFTs = phaseDerivs->vectorLength;
1655 const UINT4 numShorts = resampMultiPairs->sftTotalCount;
1656 XLAL_CHECK( ( numSFTs == numShorts ), XLAL_EINVAL, "Length mismatch: phaseDerivs->vectorLength=%"LAL_UINT4_FORMAT", resampMultiPairs->sftTotalCount=%"LAL_UINT4_FORMAT"\n", numSFTs, numShorts );
1657 const UINT4 numShortPairs = resampMultiPairs->allPairCount;
1658 XLAL_CHECK( ( Gamma_ave->length == numShortPairs ), XLAL_EINVAL, "Length mismatch: Gamma_ave->length=%"LAL_UINT4_FORMAT", numPairs=%"LAL_UINT4_FORMAT"\n", Gamma_ave->length, numShortPairs );
1659 XLAL_CHECK( ( Gamma_circ->length == numShortPairs ), XLAL_EINVAL, "Length mismatch: Gamma_circ->length=%"LAL_UINT4_FORMAT", numPairs=%"LAL_UINT4_FORMAT"\n", Gamma_circ->length, numShortPairs );
1660
1661 /* ---------- prepare output metric ---------- */
1662 gsl_matrix *ret_gNew;
1663 if ( ( ret_gNew = gsl_matrix_calloc( numCoords, numCoords ) ) == NULL ) {
1664 XLALPrintError( "%s: gsl_matrix_calloc(%d, %d) failed.\n\n", __func__, numCoords, numCoords );
1666
1667 }
1668 gsl_vector *ret_eNew;
1669 if ( ( ret_eNew = gsl_vector_calloc( numCoords ) ) == NULL ) {
1670 XLALPrintError( "%s: gsl_vector_calloc(%d) failed.\n\n", __func__, numCoords );
1672 }
1673
1674 REAL8Vector *dDeltaPhiNew_i = NULL;
1675 XLAL_CHECK( ( dDeltaPhiNew_i = XLALCreateREAL8Vector( numCoords ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL8Vector ( %"LAL_UINT4_FORMAT" ) failed.", numCoords );
1676
1677 /* new style, with proper sftIndices Tshort */
1678 UINT4 pairMetric = 0;
1679 UINT4 sftInd1 = 0;
1680 UINT4 sftInd2 = 0;
1681 REAL8 aveNewWeight = 0.0;
1682 REAL8 denomNew = 0.0;
1683 REAL8 circNewWeight = 0.0;
1684 for ( UINT4 detX = 0; detX < resampMultiPairs->length; detX++ ) {
1685 for ( UINT4 k = 0; k < resampMultiPairs->data[detX].length; k++ ) {
1686 for ( UINT4 detY = 0; detY < resampMultiPairs->data[detX].data[k].length; detY++ ) {
1687 for ( UINT4 l = 0; l < resampMultiPairs->data[detX].data[k].data[detY].length; l++ ) {
1688 sftInd1 = resampMultiPairs->data[detX].data[k].flatInd;
1689 sftInd2 = resampMultiPairs->data[detX].data[k].data[detY].data[l].flatInd;
1690 pairMetric = resampMultiPairs->data[detX].data[k].data[detY].data[l].pairInd;
1691 aveNewWeight = SQUARE( Gamma_ave->data[pairMetric] );
1692 denomNew += aveNewWeight;
1693 circNewWeight = Gamma_ave->data[pairMetric] * Gamma_circ->data[pairMetric];
1694 for ( UINT4 i = 0; i < numCoords; i++ ) {
1695 dDeltaPhiNew_i->data[i] = phaseDerivs->data[i * numShorts + sftInd1] - phaseDerivs->data[i * numShorts + sftInd2];
1696 REAL8 epsNewi = gsl_vector_get( ret_eNew, i );
1697 epsNewi += circNewWeight * dDeltaPhiNew_i->data[i];
1698 gsl_vector_set( ret_eNew, i, epsNewi );
1699 for ( UINT4 j = 0; j <= i; j++ ) { /* Doing the loop this way ensures dDeltaPhi_i[j] has been set */
1700 REAL8 gijNew = gsl_matrix_get( ret_gNew, i, j );
1701 gijNew += aveNewWeight * dDeltaPhiNew_i->data[i] * dDeltaPhiNew_i->data[j];
1702 gsl_matrix_set( ret_gNew, i, j, gijNew );
1703 } // end j loop
1704 } // end i loop over coords
1705 }
1706 }
1707 }
1708 }
1709
1710 XLALDestroyREAL8Vector( dDeltaPhiNew_i );
1711
1712 for ( UINT4 i = 0; i < numCoords; i++ ) {
1713 REAL8 epsNewi = gsl_vector_get( ret_eNew, i );
1714 epsNewi /= denomNew;
1715 gsl_vector_set( ret_eNew, i, epsNewi );
1716 for ( UINT4 j = 0; j <= i; j++ ) { /* Doing the loop the same way as above */
1717 REAL8 gijNew = gsl_matrix_get( ret_gNew, i, j );
1718 gijNew /= ( 2.*denomNew );
1719 gsl_matrix_set( ret_gNew, i, j, gijNew );
1720 if ( i != j ) {
1721 gsl_matrix_set( ret_gNew, j, i, gijNew );
1722 }
1723 }
1724 }
1725
1726 ( *g_ij ) = ret_gNew;
1727 ( *eps_i ) = ret_eNew;
1728 ( *sumGammaSq ) = denomNew;
1729
1730 return XLAL_SUCCESS;
1731
1732} // end XLALCalculateCrossCorrPhaseMetricShort
1733
1734/*calculate metric diagonal components, also include the estimation of sensitivity E[rho]/(h_0)^2*/
1736(
1737 REAL8 *hSens, /**< Output: sensitivity*/
1738 REAL8 *g_ff, /**< Output: Diagonal frequency metric element */
1739 REAL8 *g_aa, /**< Output: Diagonal binary projected semimajor axis metric element*/
1740 REAL8 *g_TT, /**< Output: Diagonal reference time metric element*/
1741 REAL8 *g_pp, /**< Output: Diagonal orbital period metric element */
1742 REAL8 *weightedMuTAve, /**< output: weighred T mean*/
1743 PulsarDopplerParams DopplerParams, /**< Input: pulsar/binary orbit paramaters*/
1744 REAL8Vector *G_alpha, /**< Input: vector of curlyGunshifted values */
1745 SFTPairIndexList *pairIndexList, /**< Input: list of SFT pairs */
1746 SFTIndexList *indexList, /**< Input: list of SFTs */
1747 MultiSFTVector *sfts, /**< Input: set of per-detector SFT vectors */
1748 MultiNoiseWeights *multiWeights /**< Input: nomalizeation factor S^-1 & weights for each SFT*/
1749)
1750
1751{
1752 UINT4 sftNum1 = 0;
1753 UINT4 sftNum2 = 0;
1754 REAL8 TDiff = 0;
1755 REAL8 TMean = 0;
1756 REAL8 denom = 0;
1757 REAL8 TSquaWeightedAve = 0;
1758 REAL8 SinSquaWeightedAve = 0;
1759 REAL8 muT = 0;
1760 REAL8 muTSqr = 0;
1761 REAL8 muTAve = 0;
1762 REAL8 muTAveSqr = 0;
1763 REAL8 muTSqrAve = 0;
1764 REAL8 sinSquare = 0;
1765 REAL8 tSquare = 0;
1766 REAL8 rhosum = 0;
1767 LIGOTimeGPS *T1 = NULL;
1768 LIGOTimeGPS *T2 = NULL;
1769 UINT4 numalpha = G_alpha->length;
1770
1771
1772 for ( UINT4 j = 0; j < numalpha; j++ ) {
1773 sftNum1 = pairIndexList->data[j].sftNum[0];
1774 sftNum2 = pairIndexList->data[j].sftNum[1];
1775 UINT4 detInd1 = indexList->data[sftNum1].detInd;
1776 UINT4 detInd2 = indexList->data[sftNum2].detInd;
1777 UINT4 sftInd1 = indexList->data[sftNum1].sftInd;
1778 UINT4 sftInd2 = indexList->data[sftNum2].sftInd;
1779 T1 = &( sfts->data[detInd1]->data[sftInd1].epoch );
1780 T2 = &( sfts->data[detInd2]->data[sftInd2].epoch );
1781 TDiff = XLALGPSDiff( T1, T2 );
1782 TMean = 0.5 * ( XLALGPSGetREAL8( T1 ) + XLALGPSGetREAL8( T2 ) );
1783 REAL8 sqrG_alpha = SQUARE( G_alpha->data[j] ); /*(curlyG_{\alpha})^2*/
1784 muT += sqrG_alpha * TMean; /*(curlyG_\alpha)^2 * \bar{t}_{\alpha}*/
1785 muTSqr += sqrG_alpha * SQUARE( TMean ); /*(curlyG_\alpha)^2 * (\bar{t}_{\alpha})^2*/
1786 sinSquare += sqrG_alpha * SQUARE( sin( LAL_PI * TDiff / ( DopplerParams.period ) ) ); /*(G_{\alpha})^2*(sin(\pi*T/T_orbit))^2*/
1787 tSquare += sqrG_alpha * SQUARE( TDiff ); /*(\curlyg_{\alpha}*)^2*T^2*/
1788 denom += sqrG_alpha; /*calculate the denominator*/
1789 rhosum += 2 * sqrG_alpha;
1790 }
1791
1792 muTAve = muT / denom;
1793 muTAveSqr = SQUARE( muTAve );
1794 muTSqrAve = muTSqr / denom;
1795 REAL8 sigmaTSqr = muTSqrAve - muTAveSqr;
1796 TSquaWeightedAve = tSquare / denom;
1797 SinSquaWeightedAve = sinSquare / denom;
1798 *hSens = 4 * SQUARE( multiWeights->Sinv_Tsft ) * rhosum;
1799 *g_ff = TSquaWeightedAve * 2 * SQUARE( LAL_PI );
1800 *g_aa = SinSquaWeightedAve * SQUARE( 2. * LAL_PI * DopplerParams.fkdot[0] );
1801 *g_TT = SinSquaWeightedAve * SQUARE( SQUARE( 2. * LAL_PI ) * ( DopplerParams.fkdot[0] ) * ( DopplerParams.asini ) / ( DopplerParams.period ) );
1802 *g_pp = SinSquaWeightedAve * sigmaTSqr * 16 * QUAD( LAL_PI ) * SQUARE( DopplerParams.fkdot[0] ) * SQUARE( DopplerParams.asini ) / ( QUAD( DopplerParams.period ) );
1803 *weightedMuTAve = muTAve;
1804
1805 return XLAL_SUCCESS;
1806
1807}
1808
1809
1810/** MODIFIED for Tshort:
1811 * calculate metric diagonal components, also include the estimation of sensitivity E[rho]/(h_0)^2*/
1813(
1814 REAL8 *hSens, /**< [out] sensitivity */
1815 REAL8 *g_ff, /**< [out] Diagonal frequency metric element */
1816 REAL8 *g_aa, /**< [out] Diagonal binary projected semimajor axis metric element*/
1817 REAL8 *g_TT, /**< [out] Diagonal reference time metric element */
1818 REAL8 *g_pp, /**< [out] Diagonal orbital period metric element */
1819 const PulsarDopplerParams DopplerParams, /**< [in] pulsar/binary orbit paramaters */
1820 const REAL8Vector *restrict G_alpha, /**< [in] vector of curlyGunshifted values */
1821 const MultiResampSFTPairMultiIndexList *restrict resampMultiPairIndexList, /**< [in] resamp list of SFT pairs */
1822 const MultiLIGOTimeGPSVector *restrict timestamps, /**< [in] timestamps for resampling */
1823 const MultiNoiseWeights *restrict multiWeights /**< [in] normalization factor S^-1 & weights for each SFT */
1824)
1825
1826{
1827 UINT4 sftNum1 = 0;
1828 UINT4 sftNum2 = 0;
1829 REAL8 TDiff = 0;
1830 REAL8 TMean = 0;
1831 REAL8 denom = 0;
1832 REAL8 TSquaWeightedAve = 0;
1833 REAL8 SinSquaWeightedAve = 0;
1834 REAL8 muT = 0;
1835 REAL8 muTSqr = 0;
1836 REAL8 muTAve = 0;
1837 REAL8 muTAveSqr = 0;
1838 REAL8 muTSqrAve = 0;
1839 REAL8 sinSquare = 0;
1840 REAL8 tSquare = 0;
1841 REAL8 rhosum = 0;
1842 LIGOTimeGPS *T1 = NULL;
1843 LIGOTimeGPS *T2 = NULL;
1844
1845 UINT4 numPairs = resampMultiPairIndexList->allPairCount;
1846 SFTPairIndexList *pairIndexList = resampMultiPairIndexList->pairIndexList;
1847 SFTIndexList *indexList = resampMultiPairIndexList->indexList;
1848
1849 for ( UINT4 j = 0; j < numPairs; j++ ) {
1850 sftNum1 = pairIndexList->data[j].sftNum[0];
1851 sftNum2 = pairIndexList->data[j].sftNum[1];
1852 UINT4 detInd1 = indexList->data[sftNum1].detInd;
1853 UINT4 detInd2 = indexList->data[sftNum2].detInd;
1854 UINT4 sftInd1 = indexList->data[sftNum1].sftInd;
1855 UINT4 sftInd2 = indexList->data[sftNum2].sftInd;
1856 T1 = &( timestamps->data[detInd1]->data[sftInd1] ) ;
1857 T2 = &( timestamps->data[detInd2]->data[sftInd2] ) ;
1858 TDiff = XLALGPSDiff( T1, T2 );
1859 TMean = 0.5 * ( XLALGPSGetREAL8( T1 ) + XLALGPSGetREAL8( T2 ) );
1860 REAL8 sqrG_alpha = SQUARE( G_alpha->data[j] ); /*(curlyG_{\alpha})^2*/
1861 muT += sqrG_alpha * TMean; /*(curlyG_\alpha)^2 * \bar{t}_{\alpha}*/
1862 muTSqr += sqrG_alpha * SQUARE( TMean ); /*(curlyG_\alpha)^2 * (\bar{t}_{\alpha})^2*/
1863 sinSquare += sqrG_alpha * SQUARE( sin( LAL_PI * TDiff / ( DopplerParams.period ) ) ); /*(G_{\alpha})^2*(sin(\pi*T/T_orbit))^2*/
1864 tSquare += sqrG_alpha * SQUARE( TDiff ); /*(\curlyg_{\alpha}*)^2*T^2*/
1865 denom += sqrG_alpha; /*calculate the denominator*/
1866 rhosum += 2 * sqrG_alpha;
1867 }
1868 muTAve = muT / denom;
1869 muTAveSqr = SQUARE( muTAve );
1870 muTSqrAve = muTSqr / denom;
1871 REAL8 sigmaTSqr = muTSqrAve - muTAveSqr;
1872 TSquaWeightedAve = tSquare / denom;
1873 SinSquaWeightedAve = sinSquare / denom;
1874 *hSens = 4 * SQUARE( multiWeights->Sinv_Tsft ) * rhosum;
1875 *g_ff = TSquaWeightedAve * 2 * SQUARE( LAL_PI );
1876 *g_aa = SinSquaWeightedAve * SQUARE( 2. * LAL_PI * DopplerParams.fkdot[0] );
1877 *g_TT = SinSquaWeightedAve * SQUARE( SQUARE( 2. * LAL_PI ) * ( DopplerParams.fkdot[0] ) * ( DopplerParams.asini ) / ( DopplerParams.period ) );
1878 *g_pp = SinSquaWeightedAve * sigmaTSqr * 16 * QUAD( LAL_PI ) * SQUARE( DopplerParams.fkdot[0] ) * SQUARE( DopplerParams.asini ) / ( QUAD( DopplerParams.period ) );
1879
1880 return XLAL_SUCCESS;
1881
1882} // end XLALCalculateLMXBCrossCorrDiagMetricShort
1883
1884///** (possible future function) Wrapper for Bessel Orbital Space stepper in the manner of V. Dergachev's loosely-coherent search */
1885//int
1886//XLALBesselCrossCorrOrbitalSpaceStep( COMPLEX8 * xTildeOut, /**< output Fa or Fb (FFT of resampled time series) */
1887// COMPLEX8 * xTildeIn, /**< input Fa or Fb (FFT of resampled time series) */
1888// PulsarDopplerParams * dopplerPoint, /**< Input: Doppler point to search */
1889// PulsarDopplerParams * binaryTemplateSpacings, /**< Input: Set of spacings for search */
1890// INT4 aStep, /**< how many steps in a sin i */
1891// INT4 pStep, /**< how many steps in period */
1892// INT4 tStep, /**< how many steps in time of ascension */
1893// INT4 nFFT, /**< number of samples in the FFT */
1894// UINT4 nTermsMax /**< Maximum number of terms in convolution */
1895//)
1896//{
1897// /* Experimental shift */
1898// /* Example call to this function from Compute Fa Fb: */
1899// //XLALBesselCrossCorrOrbitalSpaceStep(ws->FaX_k, ws->FaX_k, dopplerpos, binaryTemplateSpacings, 0, 0, 0, ws->numFreqBinsOut, 10);
1900// //XLALBesselCrossCorrOrbitalSpaceStep(ws->FbX_k, ws->FbX_k, dopplerpos, binaryTemplateSpacings, 0, 0, 0, ws->numFreqBinsOut, 10);
1901//
1902// XLAL_CHECK ( xTildeOut != NULL, XLAL_EINVAL );
1903// XLAL_CHECK ( xTildeIn != NULL, XLAL_EINVAL );
1904// XLAL_CHECK ( dopplerPoint != NULL, XLAL_EINVAL );
1905// if (pStep > (INT4)nTermsMax){
1906// fprintf(stdout, "pStep seems suspiciously large\n");
1907// }
1908// if (tStep > (INT4)nTermsMax){
1909// fprintf(stdout, "tStep seems suspiciously large\n");
1910// }
1911// //fprintf(stdout, "aStep, pStep, tStep, nFFT, nTermsMax: %i, %i, %i, %i, %u\n", aStep, pStep, tStep, nFFT, nTermsMax);
1912//
1913// COMPLEX8 *besselFX_k;
1914// XLAL_CHECK ( (besselFX_k = fftw_malloc ( nFFT * sizeof(COMPLEX8) )) != NULL, XLAL_ENOMEM );
1915// memset ( besselFX_k, 0, nFFT * sizeof(besselFX_k[0]) );
1916// //memcpy ( besselFX_k, xTildeIn, nFFT);
1917//
1918// /* Act upon the input */
1919// /* Simple test */
1920// //for ( INT4 k = 0; k < nFFT; k++ )
1921// //{
1922// // COMPLEX8 normX_k = 10.0 ;
1923// // besselFX_k[k] = normX_k * xTildeIn[k];
1924// // //if (k == nFFT-1){
1925// // // fprintf(stdout, "Made it!\n");
1926// // //}
1927// //} // for k < nFFT
1928//
1929// //REAL8 asiniPos = dopplerPoint->asini;
1930// REAL8 minFreq = dopplerPoint->fkdot[0];
1931// REAL8 nominalPeriod = dopplerPoint->period;
1932// REAL8 nominalTp = XLALGPSGetREAL8(&dopplerPoint->tp);
1933// REAL8 asiniSpace = binaryTemplateSpacings->asini;
1934// //REAL8 tpSpace = XLALGPSGetREAL8(&binaryTemplateSpacings->tp);
1935// //REAL8 periodSpace = binaryTemplateSpacings->period;
1936// REAL8 asiniShift = aStep * asiniSpace;
1937// //REAL8 tpShift = tStep * tpSpace;
1938// //REAL8 periodShift = pStep * periodSpace;
1939// REAL8 argBessel = 2 * LAL_PI * minFreq * asiniShift;
1940// /* Number of sidebands is 1 + 2*(2*pi*f0*asini)*/
1941// INT4 oneSidedNsidebands = (INT4)floor(argBessel);
1942// if ( (UINT4)oneSidedNsidebands > nTermsMax){
1943// fprintf(stdout, "Warning! large number of sidebands! Is this the right part of space?\n");
1944// }
1945// INT4 nSidebands = 1 + 2 * oneSidedNsidebands;
1946// /* Orbital phase shift */
1947// REAL8 orbitalPhaseShift = fmod( (2 * LAL_PI)/(nominalPeriod) * (nominalTp), 2 * LAL_PI );
1948//
1949// /* For reference */
1950// //REAL8 f_k = (offset_bins2L + (UINT4)floor(k*DedecimateFFT2L)) * dFreqFFT2L+0.0;
1951// //REAL8 cycles = - (f_k) * (dtauX2L - dtauX1K); /* Back to usual FFT trick */
1952// //REAL4 sinphase, cosphase;
1953// //XLALSinCos2PiLUT ( &sinphase, &cosphase, cycles );
1954// //COMPLEX8 normX_k = dt_SRC * crectf ( cosphase, sinphase );
1955//
1956// INT4 sidebandIndex;
1957// REAL8 cycles;
1958// REAL8Vector *besselCoeffs = NULL;
1959// XLAL_CHECK ( (besselCoeffs = XLALCreateREAL8Vector ( nSidebands )) != NULL, XLAL_EFUNC );
1960// for ( INT4 j = 0; j < nSidebands; j++){
1961// /* Wrap argBessel in J_s to get true filter coefficients */
1962// /* Note that J_s has s = (j - oneSidedNsidebands), it this notation */
1963// /* TECHNICALLY, this should depend on the frequency too */
1964// besselCoeffs->data[j] = argBessel;
1965// }
1966// COMPLEX8Vector *shiftsInPhase = NULL;
1967// REAL4 sinphase, cosphase;
1968// XLAL_CHECK ( (shiftsInPhase = XLALCreateCOMPLEX8Vector ( nSidebands )) != NULL, XLAL_EFUNC );
1969// for ( INT4 j = 0; j < nSidebands; j++){
1970// sidebandIndex = j - oneSidedNsidebands;
1971// cycles = sidebandIndex * orbitalPhaseShift;
1972// XLALSinCos2PiLUT ( &sinphase, &cosphase, cycles );
1973// shiftsInPhase->data[j] = crectf( cosphase, sinphase );
1974// }
1975//
1976//
1977// //fprintf(stdout, "nSidebands, tpShift, periodShift: %u, %f, %f\n", nSidebands, tpShift, periodShift);
1978// //fprintf(stdout, "nSidebands, argBessel, orbitalPhaseShift: %u, %f, %f\n", nSidebands, argBessel, orbitalPhaseShift);
1979// //fprintf(stdout, "nSidebands, besselCoeffs, cycles: %u, %f, %f\n", nSidebands, besselCoeffs->data[0], cycles);
1980// fprintf(stdout, "nSidebands, besselCoeffs, shiftsInPhase: %u, %f, %f\n", nSidebands, besselCoeffs->data[0], cimag(shiftsInPhase->data[0]));
1981// //fprintf(stdout, "asini, spacing: %f, %f\n", asiniPos, asiniSpace);
1982// /* More complex test */
1983// //COMPLEX8 partialSumK = 0;
1984// INT4 edgeOfSidebands = 0;
1985// //INT4 localNsidebands = 0;
1986// INT4 diffInEdge = 0;
1987// for ( INT4 k = 0; k < nFFT; k++ )
1988// {
1989// //COMPLEX8 normX_k = 1.0 ;
1990// //besselFX_k[k] = normX_k * xTildeIn[k];
1991// /* start bessel application */
1992// edgeOfSidebands = MYMIN(k, oneSidedNsidebands);
1993// diffInEdge = oneSidedNsidebands - edgeOfSidebands;
1994// //localNsidebands = MYMIN(2*edgeOfSidebands+1, nSidebands);
1995// for ( INT4 j = 0; j < nSidebands; j++){
1996// sidebandIndex = j - edgeOfSidebands;
1997// /* May need to take frequency spacing into account very soon*/
1998// //fprintf(stdout, "diffInEdge!: %i\n", diffInEdge);
1999// besselFX_k[k] += besselCoeffs->data[j+diffInEdge] * xTildeIn[k+sidebandIndex] * shiftsInPhase->data[j+diffInEdge];
2000// }
2001// /* end bessel application */
2002// //if (k == nFFT-1){
2003// // fprintf(stdout, "Made it!\n");
2004// //}
2005// } // for k < nFFT
2006//
2007//
2008// /* for testing */
2009// //xTildeOut = xTildeIn;
2010// memcpy (xTildeOut, besselFX_k, nFFT * sizeof(COMPLEX8));
2011// //for ( INT4 l = 0; l < nFFT; l++ )
2012// //{
2013// // xTildeOut[l] = besselFX_k[l];
2014// //}
2015// free (besselFX_k);
2016// XLALDestroyREAL8Vector(besselCoeffs);
2017// XLALDestroyCOMPLEX8Vector(shiftsInPhase);
2018// return XLAL_SUCCESS;
2019//} // XLALBesselCrossCorrOrbitalSpaceStep
2020
2021
2022/** Function to extract timestamps with tShort */
2025 REAL8TimeSeries **sciFlag, /**< [out] science or not flag */
2026 const SFTVector *sfts, /**< [in] input SFT-vector */
2027 REAL8 tShort, /**< [in] new time baseline, Tshort */
2028 UINT4 numShortPerDet /**< [in] number of Tshort per detector */
2029)
2030{
2031
2032 REAL8TimeSeries *retFlag = NULL;
2033 /* check input consistency */
2034 if ( !sfts ) {
2035 XLALPrintError( "%s: invalid NULL input 'sfts'\n", __func__ );
2037 }
2038
2039 UINT4 numSFTsNew = numShortPerDet;
2040 /* create output vector */
2041 LIGOTimeGPSVector *ret = NULL;
2042 if ( ( ret = XLALCreateTimestampVector( numSFTsNew ) ) == NULL ) {
2043 XLALPrintError( "%s: XLALCreateTimestampVector(%d) failed.\n", __func__, numSFTsNew );
2045 }
2046 ret->deltaT = tShort;
2047 ret->length = numSFTsNew;
2048
2049 UINT4 i;
2050 LIGOTimeGPS epochHolder = {0, 0};
2051 LIGOTimeGPS naiveEpoch = sfts->data[0].epoch;
2052 REAL8 naiveEpochReal = XLALGPSGetREAL8( &( naiveEpoch ) );
2053 /* Wanting a consistent baseline, calculate this externally */
2054 for ( i = 0; i < numShortPerDet; i ++ ) {
2055 epochHolder.gpsSeconds = 0;
2056 epochHolder.gpsNanoSeconds = 0;
2057 XLALGPSAdd( &( epochHolder ), naiveEpochReal );
2058 XLALGPSAdd( &( epochHolder ), i * tShort );
2059 ret->data[i] = epochHolder;
2060 }
2061
2062 retFlag = XLALCrossCorrGapFinderResampAlt( ret, sfts );
2063 /* done: return Ts-vector */
2064 ( *sciFlag ) = retFlag;
2065 return ret;
2066
2067} /* XLALExtractTimestampsFromSFTsShort() */
2068/** Generate timestamps for one detector with tShort */
2071 const REAL8 tShort, /**< [in] new time baseline, Tshort */
2072 const UINT4 numShortPerDet, /**< [in] number of Tshort per detector */
2073 const LIGOTimeGPS epoch /**< [in] start time for first Tshort */
2074)
2075{
2076
2077 UINT4 numSFTsNew = numShortPerDet;
2078 /* create output vector */
2079 LIGOTimeGPSVector *ret = NULL;
2080 if ( ( ret = XLALCreateTimestampVector( numSFTsNew ) ) == NULL ) {
2081 XLALPrintError( "%s: XLALCreateTimestampVector(%d) failed.\n", __func__, numSFTsNew );
2083 }
2084 ret->deltaT = tShort;
2085 ret->length = numSFTsNew;
2086
2087 UINT4 i;
2088 LIGOTimeGPS epochHolder = {0, 0};
2089 REAL8 epochReal = XLALGPSGetREAL8( &( epoch ) );
2090 /* Wanting a consistent baseline, calculate this externally */
2091 for ( i = 0; i < numShortPerDet; i ++ ) {
2092 epochHolder.gpsSeconds = 0;
2093 epochHolder.gpsNanoSeconds = 0;
2094 XLALGPSAdd( &( epochHolder ), epochReal );
2095 XLALGPSAdd( &( epochHolder ), i * tShort );
2096 ret->data[i] = epochHolder;
2097 }
2098 return ret;
2099
2100} /* XLALGenerateTshortTimestamps() */
2101
2102/* DEPRECATED function; use XLALGenerateTshortTimestamps() instead */
2103/** Modify timestamps from one detector with tShort */
2106 REAL8TimeSeries **sciFlag, /**< [out] science or not flag */
2107 const LIGOTimeGPSVector *restrict Times, /**< [in] input SFT-vector */
2108 const REAL8 tShort, /**< [in] new time baseline, Tshort */
2109 const UINT4 numShortPerDet /**< [in] number of Tshort per detector */
2110)
2111{
2112
2113 REAL8TimeSeries *retFlag = NULL;
2114 /* check input consistency */
2115 if ( !Times ) {
2116 XLALPrintError( "%s: invalid NULL input 'Times'\n", __func__ );
2118 }
2119
2120 UINT4 numSFTsNew = numShortPerDet;
2121 /* create output vector */
2122 LIGOTimeGPSVector *ret = NULL;
2123 if ( ( ret = XLALCreateTimestampVector( numSFTsNew ) ) == NULL ) {
2124 XLALPrintError( "%s: XLALCreateTimestampVector(%d) failed.\n", __func__, numSFTsNew );
2126 }
2127 ret->deltaT = tShort;
2128 ret->length = numSFTsNew;
2129
2130 UINT4 i;
2131 LIGOTimeGPS epochHolder = {0, 0};
2132 LIGOTimeGPS naiveEpoch = Times->data[0];
2133 REAL8 naiveEpochReal = XLALGPSGetREAL8( &( naiveEpoch ) );
2134 /* Wanting a consistent baseline, calculate this externally */
2135 for ( i = 0; i < numShortPerDet; i ++ ) {
2136 epochHolder.gpsSeconds = 0;
2137 epochHolder.gpsNanoSeconds = 0;
2138 XLALGPSAdd( &( epochHolder ), naiveEpochReal );
2139 XLALGPSAdd( &( epochHolder ), i * tShort );
2140 ret->data[i] = epochHolder;
2141 }
2142 retFlag = XLALCrossCorrGapFinderResamp( ret, Times );
2143 /* done: return Ts-vector */
2144 ( *sciFlag ) = retFlag;
2145 return ret;
2146
2147} /* XLALModifyTimestampsFromSFTsShort() */
2148
2149/**
2150 * Given a multi-SFT vector, return a MultiLIGOTimeGPSVector holding the
2151 * modified SFT timestamps (production function using tShort)
2152 */
2155 const MultiLIGOTimeGPSVector *restrict multiTimes, /**< [in] multiTimes, standard */
2156 const REAL8 tShort, /**< [in] new time baseline, Tshort */
2157 const UINT4 numShortPerDet, /**< [in] number of Tshort per detector */
2158 const BOOLEAN alignTShorts /**< [in] align segments between detectors */
2159)
2160{
2161
2162 /* check input consistency */
2163 if ( !multiTimes || multiTimes->length == 0 ) {
2164 XLALPrintError( "%s: illegal NULL or empty input 'multiTimes'.\n", __func__ );
2166 }
2167 UINT4 numIFOs = multiTimes->length;
2168
2169 /* create output vector */
2170 MultiLIGOTimeGPSVector *ret = NULL;
2171 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
2172 XLALPrintError( "%s: failed to XLALCalloc ( 1, %zu ).\n", __func__, sizeof( *ret ) );
2174 }
2175
2176 if ( ( ret->data = XLALCalloc( numIFOs, sizeof( *ret->data ) ) ) == NULL ) {
2177 XLALPrintError( "%s: failed to XLALCalloc ( %d, %zu ).\n", __func__, numIFOs, sizeof( ret->data[0] ) );
2178 XLALFree( ret );
2180 }
2181 ret->length = numIFOs;
2182
2183 /* now extract timestamps vector from each SFT-vector */
2184 UINT4 X;
2186 if ( alignTShorts == TRUE ) {
2187 /* Find the earliest starting epoch among the detectors */
2188 epoch = multiTimes->data[0]->data[0];
2189 for ( X = 1; X < numIFOs; X ++ ) {
2190 if ( XLALGPSDiff( &epoch, &( multiTimes->data[X]->data[0] ) ) > 0 ) {
2191 epoch = multiTimes->data[X]->data[0];
2192 }
2193 }
2194 }
2195 for ( X = 0; X < numIFOs; X ++ ) {
2196 if ( alignTShorts == FALSE ) {
2197 epoch = multiTimes->data[X]->data[0];
2198 }
2199 if ( ( ret->data[X] = XLALGenerateTshortTimestamps( tShort, numShortPerDet, epoch ) ) == NULL ) {
2200 XLALPrintError( "%s: XLALGenerateTshortTimestamps() failed for X=%d\n", __func__, X );
2203 }
2204
2205 } /* for X < numIFOs */
2206
2207 return ret;
2208
2209} /* XLALGenerateMultiTshortTimestamps() */
2210
2211
2212/* DEPRECATED function; use XLALGenerateMultiTshortTimestamps() instead */
2213/**
2214 * Given a multi-SFT vector, return a MultiLIGOTimeGPSVector holding the
2215 * modified SFT timestamps (production function using tShort)
2216 */
2219 MultiREAL8TimeSeries **scienceFlagVect, /**< [out] science flag vector */
2220 const MultiLIGOTimeGPSVector *restrict multiTimes, /**< [in] multiTimes, standard */
2221 const REAL8 tShort, /**< [in] new time baseline, Tshort */
2222 const UINT4 numShortPerDet /**< [in] number of Tshort per detector */
2223)
2224{
2225
2226 MultiREAL8TimeSeries *retFlagVect = NULL;
2227 /* check input consistency */
2228 if ( !multiTimes || multiTimes->length == 0 ) {
2229 XLALPrintError( "%s: illegal NULL or empty input 'multiTimes'.\n", __func__ );
2231 }
2232 UINT4 numIFOs = multiTimes->length;
2233
2234 /* create output vector */
2235 MultiLIGOTimeGPSVector *ret = NULL;
2236 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
2237 XLALPrintError( "%s: failed to XLALCalloc ( 1, %zu ).\n", __func__, sizeof( *ret ) );
2239 }
2240
2241 if ( ( ret->data = XLALCalloc( numIFOs, sizeof( *ret->data ) ) ) == NULL ) {
2242 XLALPrintError( "%s: failed to XLALCalloc ( %d, %zu ).\n", __func__, numIFOs, sizeof( ret->data[0] ) );
2243 XLALFree( ret );
2245 }
2246 ret->length = numIFOs;
2247
2248 /* new: duplicate above for the science flag vector */
2249 if ( ( retFlagVect = XLALCalloc( 1, sizeof( *retFlagVect ) ) ) == NULL ) {
2250 XLALPrintError( "%s: failed to XLALCalloc ( 1, %zu ).\n", __func__, sizeof( *retFlagVect ) );
2252 }
2253
2254 if ( ( retFlagVect->data = XLALCalloc( numIFOs, sizeof( *retFlagVect->data ) ) ) == NULL ) {
2255 XLALPrintError( "%s: failed to XLALCalloc ( %d, %zu ).\n", __func__, numIFOs, sizeof( retFlagVect->data[0] ) );
2256 XLALFree( retFlagVect );
2258 }
2259 retFlagVect->length = numIFOs;
2260
2261 /* now extract timestamps vector from each SFT-vector */
2262 UINT4 X;
2263 for ( X = 0; X < numIFOs; X ++ ) {
2264 if ( ( ret->data[X] = XLALModifyTimestampsFromSFTsShort( &retFlagVect->data[X], multiTimes->data[X], tShort, numShortPerDet ) ) == NULL ) {
2265 XLALPrintError( "%s: XLALModifyTimestampsFromSFTsShort() failed for X=%d\n", __func__, X );
2268 }
2269
2270 } /* for X < numIFOs */
2271
2272 ( *scienceFlagVect ) = retFlagVect;
2273 return ret;
2274
2275} /* XLALModifyMultiTimestampsFromSFTs() */
2276
2277/**
2278 * Given a multi-SFT vector, return a MultiLIGOTimeGPSVector holding the
2279 * SFT timestamps (test function using tShort)
2280 */
2283 MultiREAL8TimeSeries **scienceFlagVect, /**< [out] science flag vector */
2284 const MultiSFTVector *multiSFTs, /**< [in] multiSFT vector */
2285 REAL8 tShort, /**< [in] new time baseline, Tshort */
2286 UINT4 numShortPerDet /**< [in] number of Tshort per detector */
2287)
2288{
2289
2290 MultiREAL8TimeSeries *retFlagVect = NULL;
2291 /* check input consistency */
2292 if ( !multiSFTs || multiSFTs->length == 0 ) {
2293 XLALPrintError( "%s: illegal NULL or empty input 'multiSFTs'.\n", __func__ );
2295 }
2296 UINT4 numIFOs = multiSFTs->length;
2297
2298 /* create output vector */
2299 MultiLIGOTimeGPSVector *ret = NULL;
2300 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
2301 XLALPrintError( "%s: failed to XLALCalloc ( 1, %zu ).\n", __func__, sizeof( *ret ) );
2303 }
2304
2305 if ( ( ret->data = XLALCalloc( numIFOs, sizeof( *ret->data ) ) ) == NULL ) {
2306 XLALPrintError( "%s: failed to XLALCalloc ( %d, %zu ).\n", __func__, numIFOs, sizeof( ret->data[0] ) );
2307 XLALFree( ret );
2309 }
2310 ret->length = numIFOs;
2311
2312 /* new: duplicate above for the science flag vector */
2313 if ( ( retFlagVect = XLALCalloc( 1, sizeof( *retFlagVect ) ) ) == NULL ) {
2314 XLALPrintError( "%s: failed to XLALCalloc ( 1, %zu ).\n", __func__, sizeof( *retFlagVect ) );
2316 }
2317
2318 if ( ( retFlagVect->data = XLALCalloc( numIFOs, sizeof( *retFlagVect->data ) ) ) == NULL ) {
2319 XLALPrintError( "%s: failed to XLALCalloc ( %d, %zu ).\n", __func__, numIFOs, sizeof( retFlagVect->data[0] ) );
2320 XLALFree( retFlagVect );
2322 }
2323 retFlagVect->length = numIFOs;
2324
2325 /* now extract timestamps vector from each SFT-vector */
2326 UINT4 X;
2327 for ( X = 0; X < numIFOs; X ++ ) {
2328
2329 if ( ( ret->data[X] = XLALExtractTimestampsFromSFTsShort( &retFlagVect->data[X], multiSFTs->data[X], tShort, numShortPerDet ) ) == NULL ) {
2330 XLALPrintError( "%s: XLALExtractTimestampsFromSFTsShort() failed for X=%d\n", __func__, X );
2333 }
2334
2335 } /* for X < numIFOs */
2336
2337 ( *scienceFlagVect ) = retFlagVect;
2338 return ret;
2339
2340} /* XLALExtractMultiTimestampsFromSFTsShort() */
2341
2342
2343/** (test function) fill detector state with tShort, importing various slightly-modified LALPulsar functions for testing */
2344int
2345XLALFillDetectorTensorShort( DetectorState *detState, /**< [out,in]: detector state: fill in detector-tensor */
2346 const LALDetector *detector /**< [in]: which detector */
2347 )
2348{
2349 const CHAR *prefix;
2350
2351 if ( !detState || !detector ) {
2353 return -1;
2354 }
2355
2356 prefix = detector->frDetector.prefix;
2357
2358 /* we need to distinguish two cases: space-borne (i.e. LISA) and Earth-based detectors */
2359 if ( prefix[0] == 'Z' ) { /* LISA */
2360 //if ( XLALprecomputeLISAarms ( detState ) != 0 ) {
2361 // XLALPrintError ("\nXLALprecomputeLISAarms() failed !\n\n");
2362 // xlalErrno = XLAL_EINVAL;
2363 // return -1;
2364 //}
2365 //
2366 //if ( XLALgetLISADetectorTensorLWL ( &(detState->detT), detState->detArms, prefix[1] ) != 0 ) {
2367 // XLALPrintError ("\nXLALgetLISADetectorTensorLWL() failed !\n\n");
2368 // xlalErrno = XLAL_EINVAL;
2369 // return -1;
2370 //}
2371
2372 } /* if LISA */
2373 else {
2374 REAL4 sinG, cosG, sinGcosG, sinGsinG, cosGcosG;
2375 SymmTensor3 *detT = &( detState->detT );
2376
2377 XLAL_CHECK( XLALSinCosLUT( &sinG, &cosG, detState->earthState.gmstRad ) == XLAL_SUCCESS, XLAL_EFUNC );
2378 sinGsinG = sinG * sinG;
2379 sinGcosG = sinG * cosG;
2380 cosGcosG = cosG * cosG;
2381
2382 /*
2383 printf("GMST = %fdeg; cosG = %f, sinG= %f\n",
2384 LAL_180_PI * atan2(sinG,cosG), cosG, sinG);
2385 */
2386
2387 detT->d11 = detector->response[0][0] * cosGcosG
2388 - 2 * detector->response[0][1] * sinGcosG
2389 + detector->response[1][1] * sinGsinG;
2390 detT->d22 = detector->response[0][0] * sinGsinG
2391 + 2 * detector->response[0][1] * sinGcosG
2392 + detector->response[1][1] * cosGcosG;
2393 detT->d12 = ( detector->response[0][0] - detector->response[1][1] )
2394 * sinGcosG
2395 + detector->response[0][1] * ( cosGcosG - sinGsinG );
2396 detT->d13 = detector->response[0][2] * cosG
2397 - detector->response[1][2] * sinG;
2398 detT->d23 = detector->response[0][2] * sinG
2399 + detector->response[1][2] * cosG;
2400 detT->d33 = detector->response[2][2];
2401
2402 /*
2403 printf("d = (%f %f %f\n",detT->d11,detT->d12,detT->d13);
2404 printf(" %f %f %f\n",detT->d12,detT->d22,detT->d23);
2405 printf(" %f %f %f)\n",detT->d13,detT->d23,detT->d33);
2406
2407 printf("d*= (%f %f %f\n",detector->response[0][0],
2408 detector->response[0][1],detector->response[0][2]);
2409 printf(" %f %f %f\n",detector->response[1][0],
2410 detector->response[1][1],detector->response[1][2]);
2411 printf(" %f %f %f)\n",detector->response[2][0],
2412 detector->response[2][1],detector->response[2][2]);
2413 */
2414
2415 } /* if Earth-based */
2416
2417 return 0;
2418
2419} /* XLALFillDetectorTensorShort() */
2420
2421
2422/** (test function) get detector states for tShort */
2424XLALGetDetectorStatesShort( const LIGOTimeGPSVector *timestamps, /**< array of GPS timestamps t_i */
2425 const LALDetector *detector, /**< detector info */
2426 const EphemerisData *edat, /**< ephemeris file data */
2427 REAL8 tOffset, /**< compute detector states at timestamps SHIFTED by tOffset */
2428 REAL8 tShort, /**< [in] new time baseline, Tshort */
2429 UINT4 numShortPerDet /**< [in] number of Tshort per detector */
2430 )
2431{
2432 /* check input consistency */
2433 if ( !timestamps || !detector || !edat ) {
2434 XLALPrintError( "%s: invalid NULL input, timestamps=%p, detector=%p, edat=%p\n", __func__, timestamps, detector, edat );
2436 }
2437
2438 /* prepare return vector */
2439 UINT4 numSteps = numShortPerDet;
2440 printf( "numSteps in GetDetectorStatesShort: %u\n", numSteps );
2441 DetectorStateSeries *ret = NULL;
2442 if ( ( ret = XLALCreateDetectorStateSeries( numSteps ) ) == NULL ) {
2443 XLALPrintError( "%s: XLALCreateDetectorStateSeries(%d) failed.\n", __func__, numSteps );
2445 }
2446
2447 /* enter detector-info into the head of the state-vector */
2448 ret->detector = ( *detector );
2449
2450 /* set 'time-span' associated with each timestamp */
2451 //ret->deltaT = timestamps->deltaT;
2452 ret->deltaT = tShort;
2453
2454 /* set SSB coordinate system used: EQUATORIAL for Earth-based, ECLIPTIC for LISA */
2455 if ( detector->frDetector.prefix[0] == 'Z' ) { /* LISA */
2457 } else { /* Earth-based */
2459 }
2460
2461 /* now fill all the vector-entries corresponding to different timestamps */
2462 UINT4 i;
2463 for ( i = 0; i < numSteps; i++ ) {
2464 BarycenterInput baryinput;
2465 EmissionTime emit;
2466 DetectorState *state = &( ret->data[i] );
2467 EarthState *earth = &( state->earthState );
2468 LIGOTimeGPS tgps;
2469
2470 /* shift timestamp by tOffset */
2471 tgps = timestamps->data[i];
2472 XLALGPSAdd( &tgps, tOffset );
2473 /*----- first get earth-state */
2474 if ( XLALBarycenterEarth( earth, &tgps, edat ) != XLAL_SUCCESS ) {
2476 XLALPrintError( "%s: XLALBarycenterEarth() failed with xlalErrno=%d\n", __func__, xlalErrno );
2478 }
2479
2480 /*----- then get detector-specific info */
2481 baryinput.tgps = tgps;
2482 baryinput.site = ( *detector );
2483 baryinput.site.location[0] /= LAL_C_SI;
2484 baryinput.site.location[1] /= LAL_C_SI;
2485 baryinput.site.location[2] /= LAL_C_SI;
2486 baryinput.alpha = baryinput.delta = 0; /* irrelevant */
2487 baryinput.dInv = 0;
2488
2489 if ( XLALBarycenter( &emit, &baryinput, earth ) != XLAL_SUCCESS ) {
2491 XLALPrintError( "%s: XLALBarycenterEarth() failed with xlalErrno=%d\n", __func__, xlalErrno );
2493 }
2494
2495 /*----- extract the output-data from this */
2496 UINT4 j;
2497 for ( j = 0; j < 3; j++ ) { /* copy detector's position and velocity */
2498 state->rDetector[j] = emit.rDetector[j];
2499 state->vDetector[j] = emit.vDetector[j];
2500 } /* for j < 3 */
2501
2502 /* local mean sidereal time = GMST + longitude */
2503 state->LMST = earth->gmstRad + detector->frDetector.vertexLongitudeRadians;
2504 state->LMST = fmod( state->LMST, LAL_TWOPI ); /* normalize */
2505
2506 /* insert timestamp */
2507 state->tGPS = tgps;
2508
2509 /* compute the detector-tensor at this time-stamp in SSB-fixed Cartesian coordinates
2510 * [EQUATORIAL for Earth-based, ECLIPTIC for LISA]
2511 */
2512 /* XLALFillDetectorTensorShort should be identical to non-short
2513 version, simply a copy because non-short was inaccessible
2514 without editing header files (i.e., it is internal to other file) */
2515 if ( XLALFillDetectorTensorShort( state, detector ) != 0 ) {
2517 XLALPrintError( "%s: XLALFillDetectorTensorShort() failed ... errno = %d\n\n", __func__, xlalErrno );
2519 }
2520
2521 } /* for i < numSteps */
2522
2523 /* return result */
2524 return ret;
2525
2526} /* XLALGetDetectorStatesShort() */
2527
2528
2529/** (test function) get multi detector states for tShort */
2531XLALGetMultiDetectorStatesShort( const MultiLIGOTimeGPSVector *multiTS, /**< [in] multi-IFO timestamps */
2532 const MultiLALDetector *multiIFO, /**< [in] multi-IFO array holding detector info */
2533 const EphemerisData *edat, /**< [in] ephemeris data */
2534 REAL8 tOffset, /**< [in] shift all timestamps by this amount */
2535 REAL8 tShort, /**< [in] new time baseline, Tshort */
2536 UINT4 numShortPerDet /**< [in] number of Tshort segments per detector */
2537 )
2538{
2539 /* check input consistency */
2540 if ( !multiIFO || !multiTS || !edat ) {
2541 XLALPrintError( "%s: invalid NULL input (multiIFO=%p, multiTS=%p or edat=%p)\n", __func__, multiIFO, multiTS, edat );
2543 }
2544
2546 numDetectors = multiIFO->length;
2547 if ( numDetectors != multiTS->length ) {
2548 XLALPrintError( "%s: inconsistent number of IFOs in 'multiIFO' (%d) and 'multiTS' (%d)\n", __func__, multiIFO->length, multiTS->length );
2550 }
2551
2552 /* prepare return-structure */
2553 MultiDetectorStateSeries *ret = NULL;
2554 if ( ( ret = LALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
2555 XLALPrintError( "%s: LALCalloc ( 1, %zu ) failed\n", __func__, sizeof( *ret ) );
2557 }
2558 if ( ( ret->data = LALCalloc( numDetectors, sizeof( *( ret->data ) ) ) ) == NULL ) {
2559 XLALFree( ret );
2560 XLALPrintError( "%s: LALCalloc ( %d, %zu ) failed\n", __func__, numDetectors, sizeof( *( ret->data ) ) );
2562 }
2563 ret->length = numDetectors;
2564
2566 REAL8 t1 = 0;
2567 //REAL8 deltaT = tShort;
2568 //LIGOTimeGPS startTime = {0, 0};
2569 /* loop over detectors */
2570 UINT4 X;
2571 for ( X = 0; X < numDetectors; X ++ ) {
2572 LIGOTimeGPSVector *tsX = multiTS->data[X];
2573 const LALDetector *detX = &( multiIFO->sites[X] );
2574
2575 if ( !tsX || !detX ) {
2576 XLALPrintError( "%s: invalid NULL data-vector tsX[%d] = %p, detX[%d] = %p\n", __func__, X, tsX, X, detX );
2578 }
2579
2580 /* fill in the detector-state series for this detector */
2581 if ( ( ret->data[X] = XLALGetDetectorStatesShort( tsX, detX, edat, tOffset, tShort, numShortPerDet ) ) == NULL ) {
2582 XLALPrintError( "%s: XLALGetDetectorStates() failed.\n", __func__ );
2584 }
2585
2586 /* keep track of earliest/latest timestamp in order to determine total Tspan */
2587 /* This remains very close to true even with Tshort */
2588 UINT4 numTS = tsX->length;
2589 REAL8 t0_X = XLALGPSGetREAL8( &tsX->data[0] );
2590 REAL8 t1_X = XLALGPSGetREAL8( &tsX->data[numTS - 1] );
2591
2592 if ( t0_X < t0 ) {
2593 t0 = t0_X;
2594 //startTime = tsX->data[0];
2595 }
2596 if ( t1_X > t1 ) {
2597 t1 = t1_X;
2598 }
2599
2600 } /* for X < numDetectors */
2601
2602 //ret->Tspan = t1 - t0 + deltaT; /* total time spanned by all SFTs */
2603 //ret->startTime = startTime; /* earliest start-time of observation */
2604
2605 return ret;
2606
2607} /* XLALGetMultiDetectorStatesShort() */
2608
2609
2610/** Modify amplitude weight coefficients for tShort */
2611int
2613 REAL8Vector **resampMultiWeightsX, /**< [out] new weights */
2614 const MultiNoiseWeights *restrict multiWeights, /**< [in] old weights */
2615 const REAL8 tShort, /**< [in] new time baseline, Tshort */
2616 const REAL8 tSFTOld, /**< [in] old time baseline, tSFTOld */
2617 const UINT4 numShortPerDet, /**< [in] number of tShort segments per detector */
2618 const MultiLIGOTimeGPSVector *restrict multiTimes, /**< [in] multi-times vector to tell us when the SFTs were */
2619 const UINT4 maxNumStepsOldIfGapless, /**< [in] how many SFTs there would be without gaps */
2620 const UINT4 X /**< [in] detector number */
2621)
2622{
2623 REAL8Vector *ret = NULL;
2624 UINT4 numStepsXNew = numShortPerDet;
2625 COMPLEX8Vector *newWeightsX = NULL;
2626 REAL8Vector *newWeightStamps = NULL;
2627 REAL8Vector *newWeightsXReal = NULL;
2628
2629 XLAL_CHECK( ( newWeightsXReal = XLALCreateREAL8Vector( numStepsXNew ) ) != NULL, XLAL_EFUNC );
2630 XLAL_CHECK( ( newWeightsX = XLALCreateCOMPLEX8Vector( numStepsXNew ) ) != NULL, XLAL_EFUNC );
2631 XLAL_CHECK( ( newWeightStamps = XLALCreateREAL8Vector( numStepsXNew ) ) != NULL, XLAL_EFUNC );
2632 COMPLEX8TimeSeries *oldTSWeightsX = NULL;
2633
2634 for ( UINT4 alphaFuture = 0; alphaFuture < numStepsXNew; alphaFuture++ ) {
2635 newWeightStamps->data[alphaFuture] = alphaFuture * tShort;
2636 }
2637 REAL8Vector *weightsX = multiWeights->data[X];
2638 LIGOTimeGPS weightEpoch = {0, 0};
2639 /* The idea: we are going to sinc interpolate to find what the
2640 * weights should be for the coefficients. However, we need to
2641 * first make the old weights, in weightsX, into an evenly-sampled
2642 * series, with zeroes filling any gaps. That is oldTSWeightX. We
2643 * then can interpolate oldTSWeightX into newWeightsX, with
2644 * spacing according to tShort instead of tSFTOld. */
2645 oldTSWeightsX = XLALCreateCOMPLEX8TimeSeries( "old TS weights", &weightEpoch, 0, tSFTOld, &lalDimensionlessUnit, maxNumStepsOldIfGapless );
2646 UINT4 jj = 0;
2647 REAL8 tAlpha = 0;
2648 REAL8 tAlphaOldWithGaps = 0;
2649 /* The for-loop is over alphaLoad, an index at a cadence of the
2650 * old SFTs, as if they did not have gaps */
2651 for ( UINT4 alphaLoad = 0; alphaLoad < maxNumStepsOldIfGapless; alphaLoad++ ) {
2652 /* tAlpha is the time in this gapless sequence*/
2653 tAlpha = alphaLoad * tSFTOld;
2654 /* tAlphaOldWithGaps is the actual SFT time from timestamps */
2655 tAlphaOldWithGaps = XLALGPSDiff( &( multiTimes->data[X]->data[jj] ), &( multiTimes->data[X]->data[0] ) );
2656 for ( UINT4 kk = jj; kk < multiTimes->data[X]->length ; kk++ ) {
2657 /* Will overshoot gap to next SFT when reached */
2658 tAlphaOldWithGaps = XLALGPSDiff( &( multiTimes->data[X]->data[kk] ), &( multiTimes->data[X]->data[0] ) );
2659 if ( tAlphaOldWithGaps <= tAlpha ) {
2660 /* In this branch if we are at least the time of first old SFT */
2661 jj = kk;
2662 } else {
2663 /* in this branch, we do not match any old sfts */
2664 break;
2665 }
2666 if ( ( tAlpha - tAlphaOldWithGaps ) < tSFTOld ) {
2667 /* Standard progression without gaps, assuming constant cadence */
2668 oldTSWeightsX->data->data[alphaLoad] = weightsX->data[jj] + 0.0 * I;
2669 } else {
2670 /* in this branch, we do not match match the next sft:
2671 * probably there was a gap */
2672 oldTSWeightsX->data->data[alphaLoad] = 0.0 + 0.0 * I;
2673 }
2674 } // for kk
2675 } // for alphaLoad
2676 XLAL_CHECK( XLALSincInterpolateCOMPLEX8TimeSeries( newWeightsX, newWeightStamps, oldTSWeightsX, 8 ) == XLAL_SUCCESS, XLAL_EFUNC );
2677 /* Note that this above sequence differs from that in the
2678 * timestamps, because here we simply transcribed the old weights
2679 * into a zero-padded sequence at the same cadence and used the
2680 * sinc interpolation to do the heavy-lifting into the new
2681 * timeseries at new cadence. In the timestamps, we were creating,
2682 * in effect, a Boolean sequence in the next time series from
2683 * branch checks alone, with no sinc interpolation. */
2684 for ( UINT4 alphaReal = 0; alphaReal < numStepsXNew; alphaReal++ ) {
2685 /* Weights must never be negative or else next loop yields nans*/
2686 newWeightsXReal->data[alphaReal] = MYMAX( 0, creal( newWeightsX->data[alphaReal] ) );
2687 }
2688 ret = newWeightsXReal;
2689 XLALDestroyCOMPLEX8TimeSeries( oldTSWeightsX );
2690 XLALDestroyCOMPLEX8Vector( newWeightsX );
2691 XLALDestroyREAL8Vector( newWeightStamps );
2692 ( *resampMultiWeightsX ) = ret;
2693 return XLAL_SUCCESS;
2694} // XLALModifyAMCoeffsWeights
2695
2696
2697/** Modify multiple detectors' amplitude weight coefficients for tShort */
2700 const MultiNoiseWeights *restrict multiWeights, /**< [in] old weights */
2701 const REAL8 tShort, /**< [in] new time baseline, Tshort */
2702 const REAL8 tSFTOld, /**< [in] old time baseline, tSFTOld */
2703 const UINT4 numShortPerDet, /**< [in] number of tShort segments per detector */
2704 const MultiLIGOTimeGPSVector *restrict multiTimes /**< [in] multi-times vector to tell us when the SFTs were */
2705)
2706{
2707
2708 /* ----- input sanity checks ----- */
2709 UINT4 numDetectors = multiWeights->length;
2710 UINT4 numIFOs = numDetectors;
2711
2712 REAL8 ratioSFTs = tShort / tSFTOld;
2713
2714 /* Prepare output values */
2715 /* create multi noise weights for output */
2716
2717 MultiNoiseWeights *ret = NULL;
2718
2719 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
2720 XLALPrintError( "%s: failed to XLALCalloc ( 1, %zu ).\n", __func__, sizeof( *ret ) );
2722 }
2723 if ( ( ret->data = XLALCalloc( numIFOs, sizeof( *ret->data ) ) ) == NULL ) {
2724 XLALPrintError( "%s: failed to XLALCalloc ( %d, %zu ).\n", __func__, numIFOs, sizeof( ret->data[0] ) );
2725 XLALFree( ret );
2727 }
2728 ret->length = numIFOs;
2729
2730 /* As documented for MultiNoiseWeights, the S inv Tsft field is a
2731 * normalization factor equal to S^(-1) Tsft. Since we changed the
2732 * effective Tsft from Tsft to Tshort = ratioSFTs*Tsft, we also
2733 * need to multiply this normalization factor by ratioSFTs. */
2734 ret->Sinv_Tsft = multiWeights->Sinv_Tsft * ratioSFTs;
2735
2736 REAL8 Tobs = numShortPerDet * tShort;
2737 UINT4 maxNumStepsOldIfGapless = lround( Tobs / tSFTOld );
2738
2739 /* ---------- main loop over detectors X ---------- */
2740 UINT4 X;
2741
2742 for ( X = 0; X < numDetectors; X ++ ) {
2743 XLALModifyAMCoeffsWeights( &ret->data[X], multiWeights, tShort, tSFTOld, numShortPerDet, multiTimes, maxNumStepsOldIfGapless, X );
2744 }
2745
2746 return ret;
2747
2748} /* XLALModifyMultiWeights() */
2749
2750/* DEPRECATED function; use XLALModifyMultiWeights() instead */
2751
2752/** Modify multiple detectors' amplitude weight coefficients for tShort */
2753int
2755 MultiNoiseWeights **multiWeights, /**< [in/out] old and new weights */
2756 const REAL8 tShort, /**< [in] new time baseline, Tshort */
2757 const REAL8 tSFTOld, /**< [in] old time baseline, tSFTOld */
2758 const UINT4 numShortPerDet, /**< [in] number of tShort segments per detector */
2759 const MultiLIGOTimeGPSVector *restrict multiTimes /**< [in] multi-times vector to tell us when the SFTs were */
2760)
2761{
2762
2763 /* ----- input sanity checks ----- */
2764 MultiNoiseWeights *multiWeightsLocal = ( *multiWeights );
2765 UINT4 numDetectors = multiWeightsLocal->length;
2766 UINT4 numIFOs = numDetectors;
2767
2768 REAL8 ratioSFTs = tShort / tSFTOld;
2769
2770 /* Prepare output values */
2771 /* create multi noise weights for output */
2772
2773 MultiNoiseWeights *ret = NULL;
2774 XLAL_CHECK( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_EFUNC );
2775 XLAL_CHECK( ( ret->data = XLALCalloc( numIFOs, sizeof( *ret->data ) ) ) != NULL, XLAL_EFUNC );
2776 ret->length = numIFOs;
2777 /* As documented for MultiNoiseWeights, the S inv Tsft field is a
2778 * normalization factor equal to S^(-1) Tsft. Since we changed the
2779 * effective Tsft from Tsft to Tshort = ratioSFTs*Tsft, we also
2780 * need to multiply this normalization factor by ratioSFTs. */
2781 ret->Sinv_Tsft = multiWeightsLocal->Sinv_Tsft * ratioSFTs;
2782
2783 REAL8 Tobs = numShortPerDet * tShort;
2784 UINT4 maxNumStepsOldIfGapless = lround( Tobs / tSFTOld );
2785
2786 /* ---------- main loop over detectors X ---------- */
2787 UINT4 X;
2788
2789 for ( X = 0; X < numDetectors; X ++ ) {
2790 XLALModifyAMCoeffsWeights( &ret->data[X], multiWeightsLocal, tShort, tSFTOld, numShortPerDet, multiTimes, maxNumStepsOldIfGapless, X );
2791 }
2792
2793 XLALDestroyMultiNoiseWeights( ( *multiWeights ) );
2794 ( *multiWeights ) = ret;
2795 return XLAL_SUCCESS;
2796
2797} /* XLALModifyMultiAMCoeffsWeights() */
2798
2799/** (test function) used for weighting multi amplitude modulation coefficients */
2800int
2802 MultiAMCoeffs *multiAMcoef, /**< [in/out] amplitude coefficients */
2803 const MultiNoiseWeights *multiWeights, /**< [in/out] weights */
2804 REAL8 tShort, /**< [in] new time baseline, Tshort */
2805 REAL8 tSFTOld, /**< [in] old time baseline, tSFTOld */
2806 UINT4 numShortPerDet, /**< [in] number of tShort segments per detector */
2807 MultiLIGOTimeGPSVector *multiTimes /**< [in] multi-times vector to tell us when the SFTs were */
2808)
2809{
2810
2811 /* ----- input sanity checks ----- */
2812 if ( !multiAMcoef ) {
2813 XLALPrintError( "%s: illegal NULL input received in 'multiAMcoefs'.\n", __func__ );
2815 }
2816 UINT4 numDetectors = multiAMcoef->length;
2817 /* make sure identical number of detectors in amCoefs and weights */
2818 if ( multiWeights && ( multiWeights->length != numDetectors ) ) {
2819 XLALPrintError( "%s: multiWeights must be NULL or have the same number of detectors (numDet=%d) as mulitAMcoef (numDet=%d)!\n", __func__, multiWeights->length, numDetectors );
2821 }
2822
2823 REAL8 ratioSFTs = tShort / tSFTOld;
2824
2825 REAL4 Ad = 0, Bd = 0, Cd = 0; // multi-IFO values
2826
2827 REAL8 Tobs = numShortPerDet * tShort;
2828 UINT4 maxNumStepsOldIfGapless = lround( Tobs / tSFTOld );
2829
2830 /* ---------- main loop over detectors X ---------- */
2831 UINT4 X;
2832 for ( X = 0; X < numDetectors; X ++ ) {
2833 AMCoeffs *amcoeX = multiAMcoef->data[X];
2834 UINT4 numStepsXNew = numShortPerDet;
2835 if ( multiWeights ) {
2836 COMPLEX8Vector *newWeightsX = NULL;
2837 REAL8Vector *newWeightStamps = NULL;
2838 REAL8Vector *newWeightsXReal = NULL;
2839 XLAL_CHECK( ( newWeightsXReal = XLALCreateREAL8Vector( numStepsXNew ) ) != NULL, XLAL_EFUNC );
2840 XLAL_CHECK( ( newWeightsX = XLALCreateCOMPLEX8Vector( numStepsXNew ) ) != NULL, XLAL_EFUNC );
2841 XLAL_CHECK( ( newWeightStamps = XLALCreateREAL8Vector( numStepsXNew ) ) != NULL, XLAL_EFUNC );
2842 for ( UINT4 alphaFuture = 0; alphaFuture < numStepsXNew; alphaFuture++ ) {
2843 newWeightStamps->data[alphaFuture] = alphaFuture * tShort;
2844 }
2845 REAL8Vector *weightsX = multiWeights->data[X];
2846 COMPLEX8TimeSeries *oldTSWeightsX = NULL;
2847 LIGOTimeGPS weightEpoch = {0, 0};
2848 /* The idea: we are going to sinc interpolate to find what the
2849 * weights should be for the coefficients. However, we need to
2850 * first make the old weights, in weightsX, into an evenly-sampled
2851 * series, with zeroes filling any gaps. That is oldTSWeightX. We
2852 * then can interpolate oldTSWeightX into newWeightsX, with
2853 * spacing according to tShort instead of tSFTOld. */
2854 oldTSWeightsX = XLALCreateCOMPLEX8TimeSeries( "old TS weights", &weightEpoch, 0, tSFTOld, &lalDimensionlessUnit, maxNumStepsOldIfGapless );
2855 UINT4 jj = 0;
2856 REAL8 tAlpha = 0;
2857 REAL8 tAlphaOldWithGaps = 0;
2858 /* The for-loop is over alphaLoad, an index at a cadence of the
2859 * old SFTs, as if they did not have gaps */
2860 for ( UINT4 alphaLoad = 0; alphaLoad < maxNumStepsOldIfGapless; alphaLoad++ ) {
2861 /* tAlpha is the time in this gapless sequence*/
2862 tAlpha = alphaLoad * tSFTOld;
2863 /* tAlphaOldWithGaps is the actual SFT time from timestamps */
2864 tAlphaOldWithGaps = XLALGPSDiff( &( multiTimes->data[X]->data[jj] ), &( multiTimes->data[X]->data[0] ) );
2865 for ( UINT4 kk = jj; kk < multiTimes->data[X]->length ; kk++ ) {
2866 /* Will overshoot gap to next SFT when reached */
2867 tAlphaOldWithGaps = XLALGPSDiff( &( multiTimes->data[X]->data[kk] ), &( multiTimes->data[X]->data[0] ) );
2868
2869 if ( tAlphaOldWithGaps <= tAlpha ) {
2870 /* In this branch if we are at least the time of first old SFT */
2871 jj = kk;
2872 } else {
2873 /* in this branch, we do not match any old sfts */
2874 //oldTSWeightsX->data->data[alphaLoad] = 0.0 + 0.0*I;
2875 break;
2876 }
2877 if ( ( tAlpha - tAlphaOldWithGaps ) < tSFTOld ) {
2878 /* Standard progression without gaps, assuming constant cadence */
2879 oldTSWeightsX->data->data[alphaLoad] = weightsX->data[jj] + 0.0 * I;
2880 } else {
2881 /* in this branch, we do not match match the next sft:
2882 * probably there was a gap */
2883 oldTSWeightsX->data->data[alphaLoad] = 0.0 + 0.0 * I;
2884 }
2885 } // for kk
2886
2887 } // for alphaLoad
2888 XLAL_CHECK( XLALSincInterpolateCOMPLEX8TimeSeries( newWeightsX, newWeightStamps, oldTSWeightsX, 8 ) == XLAL_SUCCESS, XLAL_EFUNC );
2889 /* Note that this above sequence differs from that in the
2890 * timestamps, because here we simply transcribed the old weights
2891 * into a zero-padded sequence at the same cadence and used the
2892 * sinc interpolation to do the heavy-lifting into the new
2893 * timeseries at new cadence. In the timestamps, we were creating,
2894 * in effect, a Boolean sequence in the next time series from
2895 * branch checks alone, with no sinc interpolation. */
2896
2897 for ( UINT4 alphaReal = 0; alphaReal < numStepsXNew; alphaReal++ ) {
2898 /* Weights must never be negative or else next loop yields nans*/
2899 newWeightsXReal->data[alphaReal] = MYMAX( 0, creal( newWeightsX->data[alphaReal] ) );
2900 }
2901 UINT4 alpha;
2902 for ( alpha = 0; alpha < numStepsXNew; alpha++ ) {
2903 REAL8 Sqwi = sqrt( newWeightsXReal->data[alpha] );
2904 amcoeX->a->data[alpha] *= Sqwi;
2905 amcoeX->b->data[alpha] *= Sqwi;
2906 } // for alphaOld < numSteps
2907 XLALDestroyCOMPLEX8TimeSeries( oldTSWeightsX );
2908 XLALDestroyCOMPLEX8Vector( newWeightsX );
2909 XLALDestroyREAL8Vector( newWeightsXReal );
2910 XLALDestroyREAL8Vector( newWeightStamps );
2911 } // if weights
2912
2913
2914 UINT4 alpha; // SFT-index
2915 REAL4 AdX = 0, BdX = 0, CdX = 0; // single-IFO values
2916 /* compute single-IFO antenna-pattern coefficients AX,BX,CX, by summing over time-steps 'alpha' */
2917 for ( alpha = 0; alpha < numStepsXNew; alpha++ ) {
2918 REAL4 ahat = amcoeX->a->data[alpha];
2919 REAL4 bhat = amcoeX->b->data[alpha];
2920
2921 AdX += ahat * ahat;
2922 BdX += bhat * bhat;
2923 CdX += ahat * bhat;
2924 //printf("Final alpha! %u\n", alpha);
2925 } /* for alpha < numStepsXNew */
2926
2927 /* store those */
2928 amcoeX->A = AdX;
2929 amcoeX->B = BdX;
2930 amcoeX->C = CdX;
2931 amcoeX->D = AdX * BdX - CdX * CdX;
2932
2933 // in the unlikely event of a degenerate M-matrix with D = det[A, C; C, B] <= 0,
2934 // we set D->inf, in order to set the corresponding F-value to zero rather than >>1
2935 // By setting 'D=inf', we also allow upstream catching/filtering on such singular cases
2936 if ( amcoeX->D <= 0 ) {
2937 amcoeX->D = INFINITY;
2938 }
2939 /* compute multi-IFO antenna-pattern coefficients A,B,C by summing over IFOs X */
2940 Ad += AdX;
2941 Bd += BdX;
2942 Cd += CdX;
2943
2944 } /* for X < numDetectors */
2945 //printf("Final A, B, C, D: %f %f %f %f\n", Ad, Bd, Cd, Ad * Bd - Cd * Cd);
2946
2947 multiAMcoef->Mmunu.Ad = Ad;
2948 multiAMcoef->Mmunu.Bd = Bd;
2949 multiAMcoef->Mmunu.Cd = Cd;
2950 multiAMcoef->Mmunu.Dd = Ad * Bd - Cd * Cd;
2951
2952 // in the unlikely event of a degenerate M-matrix with D = det[A, C; C, B] <= 0,
2953 // we set D->inf, in order to set the corresponding F-value to zero rather than >>1
2954 // By setting 'D=inf', we also allow upstream catching/filtering on such singular cases
2955 if ( multiAMcoef->Mmunu.Dd <= 0 ) {
2956 multiAMcoef->Mmunu.Dd = INFINITY;
2957 }
2958
2959
2960 if ( multiWeights ) {
2961 //multiAMcoef->Mmunu.Sinv_Tsft = multiWeights->Sinv_Tsft;
2962 multiAMcoef->Mmunu.Sinv_Tsft = multiWeights->Sinv_Tsft * ratioSFTs;
2963 }
2964
2965 return XLAL_SUCCESS;
2966
2967} /* XLALWeightMultiAMCoeffsShort() */
2968
2969
2970/** (test function) used for computing amplitude modulation weights */
2971AMCoeffs *
2972XLALComputeAMCoeffsShort( const DetectorStateSeries *DetectorStates, /**< timeseries of detector states */
2973 SkyPosition skypos /**< {alpha,delta} of the source */
2974 )
2975{
2976 /* ---------- check input consistency ---------- */
2977 if ( !DetectorStates ) {
2978 XLALPrintError( "%s: invalid NULL input 'DetectorStates'\n", __func__ );
2980 }
2981
2982 /* currently requires sky-pos to be in equatorial coordinates (FIXME) */
2983 if ( skypos.system != COORDINATESYSTEM_EQUATORIAL ) {
2984 XLALPrintError( "%s: only equatorial coordinates currently supported in 'skypos'\n", __func__ );
2986 }
2987
2988 /*---------- We write components of xi and eta vectors in SSB-fixed coords */
2989 REAL4 alpha = skypos.longitude;
2990 REAL4 delta = skypos.latitude;
2991
2992 REAL4 sin1delta, cos1delta;
2993 REAL4 sin1alpha, cos1alpha;
2994 XLAL_CHECK_NULL( XLALSinCosLUT( &sin1delta, &cos1delta, delta ) == XLAL_SUCCESS, XLAL_EFUNC );
2995 XLAL_CHECK_NULL( XLALSinCosLUT( &sin1alpha, &cos1alpha, alpha ) == XLAL_SUCCESS, XLAL_EFUNC );
2996
2997 REAL4 xi1 = - sin1alpha;
2998 REAL4 xi2 = cos1alpha;
2999 REAL4 eta1 = sin1delta * cos1alpha;
3000 REAL4 eta2 = sin1delta * sin1alpha;
3001 REAL4 eta3 = - cos1delta;
3002
3003 /* prepare output vector */
3004 UINT4 numSteps = DetectorStates->length;
3005 //printf("numSteps in ComputeAMCoeffsShort: %u\n", numSteps);
3006 AMCoeffs *coeffs;
3007 if ( ( coeffs = XLALCreateAMCoeffs( numSteps ) ) == NULL ) {
3008 XLALPrintError( "%s: XLALCreateAMCoeffs(%d) failed\n", __func__, numSteps );
3010 }
3011
3012 /*---------- Compute the a(t_i) and b(t_i) ---------- */
3013 UINT4 i;
3014 for ( i = 0; i < numSteps; i++ ) {
3015 REAL4 ai, bi;
3016
3017 SymmTensor3 *d = &( DetectorStates->data[i].detT );
3018
3019 ai = d->d11 * ( xi1 * xi1 - eta1 * eta1 )
3020 + 2 * d->d12 * ( xi1 * xi2 - eta1 * eta2 )
3021 - 2 * d->d13 * eta1 * eta3
3022 + d->d22 * ( xi2 * xi2 - eta2 * eta2 )
3023 - 2 * d->d23 * eta2 * eta3
3024 - d->d33 * eta3 * eta3;
3025
3026 bi = d->d11 * 2 * xi1 * eta1
3027 + 2 * d->d12 * ( xi1 * eta2 + xi2 * eta1 )
3028 + 2 * d->d13 * xi1 * eta3
3029 + d->d22 * 2 * xi2 * eta2
3030 + 2 * d->d23 * xi2 * eta3;
3031
3032 coeffs->a->data[i] = ai;
3033 coeffs->b->data[i] = bi;
3034 //printf("ai, bi: %f %f\n", ai, bi);
3035
3036 } /* for i < numSteps */
3037
3038 /* return the result */
3039 return coeffs;
3040
3041} /* XLALComputeAMCoeffsShort() */
3042
3043
3044/** (test function) used for computing multi amplitude modulation weights */
3047 const MultiDetectorStateSeries *multiDetStates, /**< [in] detector-states at timestamps t_i */
3048 const MultiNoiseWeights *multiWeights, /**< [in] noise-weights at timestamps t_i (can be NULL) */
3049 SkyPosition skypos, /**< source sky-position [in equatorial coords!] */
3050 REAL8 tShort, /**< [in] new time baseline, Tshort */
3051 REAL8 tSFTOld, /**< [in] old time baseline, tSFTOld */
3052 UINT4 numShortPerDet, /**< [in] number of tShort segments per detector */
3053 MultiLIGOTimeGPSVector *multiTimes /**< [in] multi-times vector to tell us when the SFTs were */
3054)
3055{
3056 /* check input consistency */
3057 if ( !multiDetStates ) {
3058 XLALPrintError( "%s: invalid NULL input argument 'multiDetStates'\n", __func__ );
3060 }
3061
3062 UINT4 numDetectors = multiDetStates->length;
3063
3064 /* prepare output vector */
3065 MultiAMCoeffs *ret;
3066 if ( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) == NULL ) {
3067 XLALPrintError( "%s: failed to XLALCalloc( 1, %zu)\n", __func__, sizeof( *ret ) );
3069 }
3070
3071 ret->length = numDetectors;
3072 if ( ( ret->data = XLALCalloc( numDetectors, sizeof( *ret->data ) ) ) == NULL ) {
3073 XLALPrintError( "%s: failed to XLALCalloc(%d, %zu)\n", __func__, numDetectors, sizeof( *ret->data ) );
3074 XLALFree( ret );
3076 }
3077
3078 /* loop over detectors and generate AMCoeffs for each one */
3079 UINT4 X;
3080 for ( X = 0; X < numDetectors; X ++ ) {
3081 if ( ( ret->data[X] = XLALComputeAMCoeffsShort( multiDetStates->data[X], skypos ) ) == NULL ) {
3082 XLALPrintError( "%s: call to XLALComputeAMCoeffs() failed with xlalErrno = %d\n", __func__, xlalErrno );
3085 }
3086
3087 } /* for X < numDetectors */
3088
3089 /* Note that the weighting is the only place where multiTimes are used,
3090 * and for that, the old vector is the right one, because we need to
3091 * know when the old SFTs were */
3092 /* apply noise-weights and compute antenna-pattern matrix {A,B,C} */
3093 if ( XLALWeightMultiAMCoeffsShort( ret, multiWeights, tShort, tSFTOld, numShortPerDet, multiTimes ) != XLAL_SUCCESS ) {
3094 /* Turns out tShort and tSFTOld are, surprisingly, irrelevant (I think) */
3095 XLALPrintError( "%s: call to XLALWeightMultiAMCoeffs() failed with xlalErrno = %d\n", __func__, xlalErrno );
3098 }
3099
3100 /* return result */
3101 return ret;
3102
3103} /* XLALComputeMultiAMCoeffsShort() */
3104
3105
3106/** Compute the number of tShort segments per detector */
3107UINT4
3109 const REAL8 resampTshort, /**< [in] resampling Tshort */
3110 const INT4 startTime, /**< [in] start time of observation */
3111 const INT4 endTime /**< [in] end time of observation */
3112)
3113{
3114 UINT4 numShortPerDet = 0;
3115 REAL8 Tobs = ( REAL8 )( endTime - startTime );
3116 numShortPerDet = lround( Tobs / resampTshort );
3117 return numShortPerDet;
3118} /* XLALCrossCorrNumShortPerDetector */
3119
3120
3121/** Find gaps in the data given the SFTs*/
3124 LIGOTimeGPSVector *restrict timestamps, /**< [in] timestamps vector */
3125 const LIGOTimeGPSVector *restrict Times /**< [in] input SFT-vector */
3126)
3127{
3128 UINT4 numSFTsNew = timestamps->length;
3129 REAL8TimeSeries *retFlag = NULL;
3130 /* creation and memory allocation for the science-or-not vector */
3131 if ( ( retFlag = XLALCreateREAL8TimeSeries( "science-or-not Boolean-as-real vector", &( timestamps->data[0] ), 0, ( timestamps->deltaT ), &lalDimensionlessUnit, numSFTsNew ) ) == NULL ) {
3132 XLALPrintError( "%s: XLALCreateREAL8TimeSeries(%d) failed.\n", __func__, numSFTsNew );
3134 }
3135 REAL8 Tsft = Times->deltaT;
3136 UINT4 jj = 0;
3137 REAL8 tAlpha = 0;
3138 REAL8 tAlphaOldWithGaps = 0;
3139 /* Now make the science-or-not vector */
3140 for ( UINT4 ii = 0; ii < numSFTsNew; ii++ ) {
3141 /* tAlpha is the time in this gapless sequence,
3142 * equivalent to corresponding epoch holder */
3143 /* for tAlpha, use tShort*/
3144 tAlpha = XLALGPSDiff( &( timestamps->data[ii] ), &( timestamps->data[0] ) );
3145 /* tAlphaOldWithGaps is the actual SFT time from timestamps */
3146 tAlphaOldWithGaps = XLALGPSDiff( &( Times->data[jj] ), &( Times->data[0] ) );
3147 /* A science segment begins with an old stamp, continues, and ends
3148 * when the next stamp is more than 1 usual SFT time away -- the
3149 * ending time is that one SFT time */
3150 /* First goal: find out what is the last tAlphaOldWithGaps <= tAlpha;
3151 * then can come the second goal: is tAlpha - tAlphaOldWithGaps < Tsft?
3152 * If yes, then is science (flagHolder = 1), else not (flagHolder = 0) */
3153 for ( UINT4 kk = jj; kk < Times->length ; kk++ ) {
3154 tAlphaOldWithGaps = XLALGPSDiff( &( Times->data[kk] ), &( Times->data[0] ) );
3155 if ( tAlphaOldWithGaps <= tAlpha ) {
3156 jj = kk;
3157 /* At this point, tAlphaOldWithGaps is right for this kk,
3158 * and jj has been set */
3159 } else {
3160 /* Then it has gone too far */
3161 break;
3162 } /* Goal 1: done */
3163 if ( tAlpha - tAlphaOldWithGaps < Tsft ) {
3164 /* time is within an SFT and thus science */
3165 retFlag->data->data[ii] = 1.0;
3166 } else {
3167 /* time is outside an SFT and thus not science */
3168 retFlag->data->data[ii] = 0.0;
3169 } /* Goal 2: done */
3170 }
3171 }
3172 return retFlag;
3173} /* XLALCrossCorrGapFinderResamp */
3174
3175
3176/** (test function) find gaps in the data given the SFTs */
3177//LIGOTimeGPSVector *
3180 LIGOTimeGPSVector *restrict timestamps, /**< [in] timestamps vector */
3181 const SFTVector *restrict sfts /**< [in] input SFT-vector */
3182)
3183{
3184 UINT4 numSFTsNew = timestamps->length;
3185 REAL8TimeSeries *retFlag = NULL;
3186 /* creation and memory allocation for the science-or-not vector */
3187 if ( ( retFlag = XLALCreateREAL8TimeSeries( "science-or-not Boolean-as-real vector", &( timestamps->data[0] ), 0, ( timestamps->deltaT ), &lalDimensionlessUnit, numSFTsNew ) ) == NULL ) {
3188 XLALPrintError( "%s: XLALCreateREAL8TimeSeries(%d) failed.\n", __func__, numSFTsNew );
3190 }
3191 REAL8 Tsft = 1.0 / sfts->data[0].deltaF;
3192 UINT4 jj = 0;
3193 REAL8 tAlpha = 0;
3194 REAL8 tAlphaOldWithGaps = 0;
3195 /* Now make the science-or-not vector */
3196 for ( UINT4 ii = 0; ii < numSFTsNew; ii++ ) {
3197 /* tAlpha is the time in this gapless sequence,
3198 * equivalent to corresponding epoch holder */
3199 /* for tAlpha, use tShort*/
3200 tAlpha = XLALGPSDiff( &( timestamps->data[ii] ), &( timestamps->data[0] ) );
3201 /* tAlphaOldWithGaps is the actual SFT time from timestamps */
3202 tAlphaOldWithGaps = XLALGPSDiff( &( sfts->data[jj].epoch ), &( sfts->data[0] ).epoch );
3203 /* A science segment begins with an old stamp, continues, and ends
3204 * when the next stamp is more than 1 usual SFT time away -- the
3205 * ending time is that one SFT time */
3206 /* First goal: find out what is the last tAlphaOldWithGaps <= tAlpha;
3207 * then can come the second goal: is tAlpha - tAlphaOldWithGaps < Tsft?
3208 * If yes, then is science (flagHolder = 1), else not (flagHolder = 0) */
3209 for ( UINT4 kk = jj; kk < sfts->length ; kk++ ) {
3210 tAlphaOldWithGaps = XLALGPSDiff( &( sfts->data[kk].epoch ), &( sfts->data[0] ).epoch );
3211 if ( tAlphaOldWithGaps <= tAlpha ) {
3212 jj = kk;
3213 /* At this point, tAlphaOldWithGaps is right for this kk,
3214 * and jj has been set */
3215 } else {
3216 /* Then it has gone too far */
3217 break;
3218 } /* Goal 1: done */
3219 if ( tAlpha - tAlphaOldWithGaps < Tsft ) {
3220 /* time is within an SFT and thus science */
3221 retFlag->data->data[ii] = 1.0;
3222 } else {
3223 /* time is outside an SFT and thus not science */
3224 retFlag->data->data[ii] = 0.0;
3225 } /* Goal 2: done */
3226 }
3227 }
3228 return retFlag;
3229} /* XLALCrossCorrGapFinderResampAlt */
3230
3231
3232/** Demarcate pairs with flags about whether data exists in zero-padded timeseries */
3233int
3235 MultiResampSFTPairMultiIndexList *resampMultiPairs, /**< [in] resampling pairs */
3236 MultiREAL8TimeSeries *scienceFlagVect /**< [in] science flags */
3237)
3238{
3239 /* Note that some functions see the science segment gaps implicitly,
3240 * as with the gammas function being interpolated with zeroes at gaps,
3241 * and the gamma function thus affecting, via the coefficient of pairs
3242 * of phase derivatives, the metric. For these purposes, the science
3243 * flags serve simply as a sanity check. */
3244 REAL4 castSciFlag1 = 0;
3245 REAL4 castSciFlag2 = 0;
3246 UINT4 detInd1;
3247 UINT4 detInd2;
3248 UINT4 sftInd1;
3249 UINT4 sftInd2;
3250 for ( UINT4 detX = 0; detX < resampMultiPairs->length; detX++ ) {
3251 detInd1 = resampMultiPairs->data[detX].detInd;
3252 for ( UINT4 k = 0; k < resampMultiPairs->data[detX].length; k++ ) {
3253 sftInd1 = resampMultiPairs->data[detX].data[k].sftInd;
3254 castSciFlag1 = ( REAL4 )scienceFlagVect->data[detInd1]->data->data[sftInd1];
3255 resampMultiPairs->data[detX].data[k].sciFlag = castSciFlag1;
3256 for ( UINT4 detY = 0; detY < resampMultiPairs->data[detX].data[k].length; detY++ ) {
3257 detInd2 = resampMultiPairs->data[detX].data[k].data[detY].detInd;
3258 for ( UINT4 l = 0; l < resampMultiPairs->data[detX].data[k].data[detY].length; l++ ) {
3259 sftInd2 = resampMultiPairs->data[detX].data[k].data[detY].data[l].sftInd;
3260 castSciFlag2 = ( REAL4 )scienceFlagVect->data[detInd2]->data->data[sftInd2];
3261 resampMultiPairs->data[detX].data[k].data[detY].data[l].sciFlag = castSciFlag2;
3262 }
3263 }
3264 }
3265 }
3266 return XLAL_SUCCESS;
3267} /* XLALEquipCrossCorrPairsWithScienceFlags */
3268
3269///** (possible future function) does not work -- would adjust timestamps of an SFT vector */
3270//MultiSFTVector
3271//*XLALModifyCrossCorrTimestampsIntoSFTVector(
3272// const MultiLIGOTimeGPSVector *multiTimes /**< [in] timestamps */
3273//)
3274//{
3275// //XLAL_CHECK ( multiTimes != NULL, XLAL_EINVAL );
3276// //XLAL_CHECK ( multiTimes->length != 0, XLAL_EINVAL );
3277//
3278// UINT4 numIFOs = multiTimes->length;
3279// UINT4 nSFTs = 0;
3280//
3281// /* create multi sft vector */
3282// MultiSFTVector *multiSFTs = NULL;
3283// //XLAL_CHECK_NULL ( (multiSFTs = XLALCalloc(1, sizeof(*multiSFTs))) != NULL, XLAL_ENOMEM );
3284// //XLAL_CHECK_NULL ( (multiSFTs->data = XLALCalloc ( numIFOs, sizeof(*multiSFTs->data))) != NULL, XLAL_ENOMEM );
3285// multiSFTs = XLALCalloc(1, sizeof(*multiSFTs));
3286// multiSFTs->data = XLALCalloc ( numIFOs, sizeof(*multiSFTs->data));
3287// multiSFTs->length = numIFOs;
3288//
3289// for ( UINT4 X = 0; X < numIFOs; X++ )
3290// {
3291// nSFTs = multiTimes->data[X]->length;
3292// multiSFTs->data[X]->length = nSFTs;
3293// //SFTVector* sftVector = NULL;
3294// //sftVector = XLALCreateSFTVector (nSFTs, 1);
3295// //if (!(sftVector = XLALCreateSFTVector (nSFTs, 1))) {
3296// // XLALPrintError("ERROR: Couldn't create short sftVector\n");
3297// // XLALLOADSFTSERROR(XLAL_EINVAL);
3298// //}
3299// for ( UINT4 jj = 0; jj < nSFTs; jj++)
3300// {
3301// multiSFTs->data[X]->data[jj].epoch = multiTimes->data[X]->data[jj];
3302// }
3303// } // for X < numIFOs
3304//
3305// return multiSFTs;
3306//} /* XLALModifyCrossCorrTimestampsIntoSFTVector */
3307
3308
3309/** Generates a resampling workspace for CrossCorr */
3310int
3312 ResampCrossCorrWorkspace **wsOut, /**< [out] workspace for one cross-correlation */
3313 COMPLEX8 **ws1KFaX_kOut, /**< [out] holder for detector 1 Fa */
3314 COMPLEX8 **ws1KFbX_kOut, /**< [out] holder for detector 1 Fb */
3315 COMPLEX8 **ws2LFaX_kOut, /**< [out] holder for detector 2 Fa */
3316 COMPLEX8 **ws2LFbX_kOut, /**< [out] holder for detector 2 Fb */
3317 MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_aOut, /**< [out] resampling A time series */
3318 MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_bOut, /**< [out] resampling B time series */
3319 const PulsarDopplerParams binaryTemplateSpacings, /**< [in ]binary template spacings */
3320 FstatInput *resampFstatInput, /**< [in] resampling f-statistic input */
3321 const UINT4 numFreqBins, /**< [in] number of frequency bins */
3322 const REAL8 tCoh, /**< [in] Tcoh = 2 * max lag + resampling tShort */
3323 const BOOLEAN treatWarningsAsErrors /**< [in] abort program if any warnings encountered */
3324)
3325{
3326
3327 MultiCOMPLEX8TimeSeries *multiTimeSeries_SRC_a = ( *multiTimeSeries_SRC_aOut );
3328 MultiCOMPLEX8TimeSeries *multiTimeSeries_SRC_b = ( *multiTimeSeries_SRC_bOut );
3329
3330 COMPLEX8 *restrict ws1KFaX_k = ( *ws1KFaX_kOut );
3331 COMPLEX8 *restrict ws1KFbX_k = ( *ws1KFbX_kOut );
3332 COMPLEX8 *restrict ws2LFaX_k = ( *ws2LFaX_kOut );
3333 COMPLEX8 *restrict ws2LFbX_k = ( *ws2LFbX_kOut );
3334 /* Extract base info from the resampled time series.
3335 * Use both a and b time series structs to make vars used */
3336 XLALExtractResampledTimeseries( &multiTimeSeries_SRC_a, &multiTimeSeries_SRC_b, resampFstatInput );
3337 const REAL8 dt_SRC = multiTimeSeries_SRC_b->data[0]->deltaT;
3338 ( *multiTimeSeries_SRC_aOut ) = multiTimeSeries_SRC_a;
3339 ( *multiTimeSeries_SRC_bOut ) = multiTimeSeries_SRC_b;
3340 /* extract more by using the workspace */
3341
3342 /* Compare with the timing model document, T1600531, for the F-stat.
3343 * Tcoh here matches Tcoh there, but note that the metric is defined in
3344 * terms of maxLag instead. Tcoh = 2*maxLag + tShort. In this stage, we
3345 * no longer access dt_DET, only dt_SRC.
3346 * In source frame, SRCsampPerTcoh = tCoh / dt_SRC. But we can also
3347 * define the metric timescale,
3348 * metricSRCsampPerTcoh = 1/(dFreqMetric*dt_SRC),
3349 * then round each up to the nearest power of 2 to define,
3350 * metricNumSamplesFFT = (UINT4)pow(2, ceil(log2(metricSRCsampPerTcoh))),
3351 * shortNumSamplesFFT = (UINT4)pow(2, ceil(log2(metricSRCsampPeTcoh))),
3352 * and choose the maximum between the two to be numSampledFFT. This is
3353 * equivalent to how Fstat calculates it.
3354 * To see why, note: our SRCsampPerTcoh is Fstat's N^SRC_samp. We can
3355 * access it immediately because the resampling is already done for us.
3356 * If decimateFFT = (UINT4)ceil( tCoh / TspanFFT),
3357 * = (UINT4)ceil( tCoh * dFreqMetric ),
3358 * then numSamplesFFT0 = (UINT4)ceil(decimateFFT * TspanFFT / dt_SRC)
3359 * for us -- note, dt_SRC, because we have no access to the detector.
3360 * and, numSamplesFFT0 = (UINT4)ceil(decimateFFT / (dFreqMetric*dt_SRC)),
3361 * then rounded up to the nearest power of 2, numSamplesFFT0.
3362 * Ergo, comingling our two notations,
3363 * numSamplesFFT0 = (UINT4)ceil(decimateFFT * metricSRCsampPerTcoh),
3364 * and the exact same error should be thrown if decimateFFT > 1 as if
3365 * shortNumSamplesFFT <= metricNumSamplesFFT.
3366 * Beware: we divide the resampled time-series up into sections, and
3367 * in the statistic this plays a crucial role.
3368 * The equivalent of decimate is the quantity,
3369 * RedecimateFFT
3370 * = binaryTemplateSpacings->fkdot[0] * (dt_SRC) * (ws->numSamplesFFT)
3371 * = dFreqMetric * dt_SRC * (UINT4)pow(2, ceil(log2(...
3372 * (UINT4)ceil(decimateFFT / (dFreqMetric * dt_SRC)) )))
3373 * which although proportional to decimateFFT is not equal to it, and
3374 * is a real quantity rather than integer.
3375 * (GDM)
3376 */
3377 /* Metric spacing: */
3378 const REAL8 dFreqMetric = binaryTemplateSpacings.fkdot[0];
3379 // determine resampled timeseries parameters
3380 const REAL8 TspanFFT = 1.0 / dFreqMetric;
3381 const UINT4 decimateFFT = ( UINT4 )ceil( tCoh / TspanFFT ); // larger than 1 means we need to artificially increase dFreqFFT by 'decimateFFT'
3382 if ( 1 <= ( dFreqMetric * dt_SRC ) ) {
3383 printf( "Warning! Metric spacing less than one FFT sample,...\n ...is maxLag < tShort? \n ...proceeding in radiometer mode...\n ...intended for non-production comparison tests only!\n" );
3384 if ( treatWarningsAsErrors ) {
3385 XLALPrintError( "Error! (treating warnings as errors) metric spacing less than one FFT sample.\n" );
3386 XLAL_CHECK( 1 >= ( dFreqMetric * dt_SRC ), XLAL_EFUNC );
3387 }
3388 }
3389 if ( decimateFFT > 1 ) {
3390 printf( "Warning! Frequency spacing larger than 1/Tcoh, decimation being applied of %" LAL_UINT4_FORMAT "\n", decimateFFT );
3391 if ( treatWarningsAsErrors == TRUE ) {
3392 XLALPrintError( "Error! (treating warnings as errors) FFT samples limited by tCoh (not metric), unexpected unless high mismatchF.\n" );
3393 XLAL_CHECK( ( decimateFFT < 1 ), XLAL_EFUNC );
3394 }
3395 }
3396 const REAL8 TspanFFT1 = decimateFFT * TspanFFT;
3397 /* Note difference from Fstat in using dt_SRC rather than dt_DET here */
3398 const UINT4 numSamplesFFT0 = ( UINT4 ) ceil( TspanFFT1 / dt_SRC ); // we use ceil() so that we artificially widen the band rather than reduce it
3399 const UINT4 numSamplesFFT = ( UINT4 ) pow( 2, ceil( log2( numSamplesFFT0 ) ) ); // round numSamplesFFT up to next power of 2 for most effiecient FFT
3400 ResampCrossCorrWorkspace *restrict ws = NULL;
3401 /* CP'd from ComputeFstat_resamp:538 */
3402 const int fft_plan_flags = FFTW_MEASURE;
3403 //int fft_plan_flags=FFTW_ESTIMATE;
3404 const double fft_plan_timeout = FFTW_NO_TIMELIMIT ;
3405 /* Memory pre-allocate: */
3406 XLAL_CHECK( ( ws = XLALCalloc( 1, sizeof( *ws ) ) ) != NULL, XLAL_ENOMEM );
3407 XLAL_CHECK( ( ws->TStmp1_SRC = XLALCreateCOMPLEX8Vector( numSamplesFFT ) ) != NULL, XLAL_EFUNC );
3408 XLAL_CHECK( ( ws->TStmp2_SRC = XLALCreateCOMPLEX8Vector( numSamplesFFT ) ) != NULL, XLAL_EFUNC );
3409 XLAL_CHECK( ( ws->SRCtimes_DET = XLALCreateREAL8Vector( numSamplesFFT ) ) != NULL, XLAL_EFUNC );
3410 XLAL_CHECK( ( ws->FaX_k = fftw_malloc( numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
3411 XLAL_CHECK( ( ws->FbX_k = fftw_malloc( numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
3412 XLAL_CHECK( ( ws->FabX_Raw = fftw_malloc( numSamplesFFT * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
3413 XLAL_CHECK( ( ws->TS_FFT = fftw_malloc( numSamplesFFT * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
3414 ws->decimateFFT = decimateFFT;
3415 ws->numSamplesFFT = numSamplesFFT;
3416 ws->numFreqBinsOut = numFreqBins;
3417 /* -- create FFT plan with FFTW */
3419 //XLALGetFFTPlanHints (& fft_plan_flags , & fft_plan_timeout );
3420 fftw_set_timelimit( fft_plan_timeout );
3421 XLAL_CHECK( ( ws->fftplan = fftwf_plan_dft_1d( numSamplesFFT, ws->TS_FFT, ws->FabX_Raw, FFTW_FORWARD, fft_plan_flags ) ) != NULL, XLAL_EFAILED, "fftwf_plan_dft_1d() failed\n" );
3423 /* -- finish creating FFT plan with FFTW */
3424
3425 XLAL_CHECK( ( ws1KFaX_k = fftw_malloc( numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
3426 XLAL_CHECK( ( ws1KFbX_k = fftw_malloc( numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
3427 XLAL_CHECK( ( ws2LFaX_k = fftw_malloc( numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
3428 XLAL_CHECK( ( ws2LFbX_k = fftw_malloc( numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
3429 ( *ws1KFaX_kOut ) = ws1KFaX_k;
3430 ( *ws1KFbX_kOut ) = ws1KFbX_k;
3431 ( *ws2LFaX_kOut ) = ws2LFaX_k;
3432 ( *ws2LFbX_kOut ) = ws2LFbX_k;
3433 ( *wsOut ) = ws;
3434 return XLAL_SUCCESS;
3435} /* XLALCreateCrossCorrWorkspace */
3436
3437/* ===== Object destruction functions ===== */
3438
3439/**
3440 * Destroy a SFTIndexList structure.
3441 * Note, this is "NULL-robust" in the sense that it will not crash
3442 * on NULL-entries anywhere in this struct, so it can be used
3443 * for failure-cleanup even on incomplete structs
3444 */
3445void
3447{
3448 if ( ! sftIndices ) {
3449 return;
3450 }
3451
3452 if ( sftIndices->data ) {
3453 XLALFree( sftIndices->data );
3454 }
3455
3456 XLALFree( sftIndices );
3457
3458 return;
3459
3460} /* XLALDestroySFTIndexList() */
3461
3462/**
3463 * Destroy a SFTPairIndexList structure.
3464 * Note, this is "NULL-robust" in the sense that it will not crash
3465 * on NULL-entries anywhere in this struct, so it can be used
3466 * for failure-cleanup even on incomplete structs
3467 */
3468void
3470{
3471 if ( ! sftPairs ) {
3472 return;
3473 }
3474
3475 if ( sftPairs->data ) {
3476 XLALFree( sftPairs->data );
3477 }
3478
3479 XLALFree( sftPairs );
3480
3481 return;
3482
3483} /* XLALDestroySFTPairIndexList() */
3484
3486{
3487 if ( !sftResampList ) {
3488 return;
3489 }
3490
3491 if ( sftResampList->data ) {
3492 XLALFree( sftResampList->data );
3493 }
3494
3495 //XLALFree( sftResampList );
3496
3497 return;
3498} /* XLALDestroyResampSFTIndexList */
3499
3501{
3502 if ( !sftResampMultiList ) {
3503 return;
3504 }
3505
3506 for ( UINT4 detY = 0; detY < sftResampMultiList->length; detY++ ) {
3507 XLALDestroyResampSFTIndexList( & sftResampMultiList->data[detY] );
3508 }
3509
3510 if ( sftResampMultiList->data ) {
3511 XLALFree( sftResampMultiList->data );
3512 }
3513
3514
3515 return;
3516} /* XLALDestroyResampSFTMultiIndexList */
3517
3519{
3520 if ( !sftResampPairMultiList ) {
3521 return;
3522 }
3523
3524 for ( UINT4 k = 0; k < sftResampPairMultiList->length; k++ ) {
3525 XLALDestroyResampSFTMultiIndexList( & sftResampPairMultiList->data[k] );
3526 }
3527
3528 if ( sftResampPairMultiList->data ) {
3529 XLALFree( sftResampPairMultiList->data );
3530 }
3531
3532
3533 return;
3534} /* XLALDestroyResampSFTPairMultiIndexList */
3535
3536void
3538{
3539 if ( ! sftMultiPairsResamp ) {
3540 return;
3541 }
3542
3543 /* Iterate through the structure and destroy completely */
3544 for ( UINT4 detX = 0; detX < sftMultiPairsResamp->length; detX++ ) {
3545 XLALDestroyResampSFTPairMultiIndexList( & sftMultiPairsResamp->data[detX] );
3546 }
3547
3548 /* Rely on external functions to clear pairs and flat index
3549 for now, to make robust */
3550
3551 if ( sftMultiPairsResamp->data ) {
3552 XLALFree( sftMultiPairsResamp->data );
3553 }
3554
3555 XLALFree( sftMultiPairsResamp );
3556
3557 return;
3558
3559} /* XLALDestroyMultiResampSFTPairMultiIndexList() */
3560
3561/* Destroy the struct that matched pairs */
3562void
3563XLALDestroyMultiMatchList( MultiResampSFTMultiCountList *localMultiListOfLmatchingGivenMultiK )
3564{
3565
3566 if ( ! localMultiListOfLmatchingGivenMultiK ) {
3567 return;
3568 }
3569
3570 UINT4 numDets = localMultiListOfLmatchingGivenMultiK->length; /* Because it is a multi-multi-list */
3571 /* furthermore, scroll through each detector X to read how many SFTs K_X it has */
3572 for ( UINT4 detX = 0; detX < numDets; detX++ ) {
3573 for ( UINT4 k = 0; k < localMultiListOfLmatchingGivenMultiK->data[detX].length; k++ ) {
3574 if ( localMultiListOfLmatchingGivenMultiK->data[detX].data[k].data ) {
3575 XLALFree( localMultiListOfLmatchingGivenMultiK->data[detX].data[k].data );
3576 }
3577 }
3578 if ( localMultiListOfLmatchingGivenMultiK->data[detX].data ) {
3579 XLALFree( localMultiListOfLmatchingGivenMultiK->data[detX].data );
3580 }
3581 }
3582
3583 if ( localMultiListOfLmatchingGivenMultiK->data ) {
3584 XLALFree( localMultiListOfLmatchingGivenMultiK->data );
3585 }
3586
3587 XLALFree( localMultiListOfLmatchingGivenMultiK );
3588
3589}
3590
3591void
3593{
3595
3599
3601 fftwf_destroy_plan( ws->fftplan );
3603
3604 fftw_free( ws->FabX_Raw );
3605 fftw_free( ws->TS_FFT );
3606
3607 fftw_free( ws->FaX_k );
3608 fftw_free( ws->FbX_k );
3609 XLALFree( ws->Fa_k );
3610 XLALFree( ws->Fb_k );
3611
3612 XLALFree( ws );
3613 return;
3614
3615} // XLALDestroyResampWorkspace()
3616
3617// ---------- internal functions ----------
3618
3619/** Imported and modified from ComputeFstat_Resamp.c */
3620static int
3622(
3623 COMPLEX8 *restrict xOut, ///< [out] the spindown-corrected SRC-frame timeseries
3624 const COMPLEX8TimeSeries *restrict xIn, ///< [in] the input SRC-frame timeseries
3625 const PulsarDopplerParams *restrict doppler, ///< [in] containing spindown parameters
3626 const REAL8 freqShift, ///< [in] frequency-shift to apply, sign is "new - old"
3627 const UINT4 indexStartResamp, ///< [in] index in resampling time series to start
3628 const UINT4 indexEndResamp, ///< [in] index in resampling time series to end
3629 const UINT4 numSamplesIn, ///< [in] number of samples in the output
3630 const UINT4 insertPoint ///< [in] number of sample indices offset to begin output
3631)
3632{
3633 // input sanity checks
3634 XLAL_CHECK( xOut != NULL, XLAL_EINVAL );
3635 XLAL_CHECK( xIn != NULL, XLAL_EINVAL );
3636 XLAL_CHECK( doppler != NULL, XLAL_EINVAL );
3637
3638 //// determine number of spin downs to include
3639 //UINT4 s_max = PULSAR_MAX_SPINS - 1;
3640 //while ( (s_max > 0) && (doppler->fkdot[s_max] == 0) ) {
3641 // s_max --;
3642 //}
3643
3644 const REAL8 dt = xIn->deltaT;
3645 if ( insertPoint > numSamplesIn ) {
3646 XLALPrintError( "ERROR! Would insert off end of matrix, numSamplesIn < insertPoint: %i, %i\n", numSamplesIn, insertPoint );
3648 }
3649 /* original */ //UINT4 numSamplesIn = xIn->data->length;
3650 /* resampling: use user input */
3651
3652 const LIGOTimeGPS epoch = xIn->epoch;
3653 const REAL8 Dtau0 = GPSDIFF( epoch, doppler->refTime );
3654
3655 // loop over time samples
3656 if ( ( indexEndResamp - indexStartResamp ) > numSamplesIn ) {
3657 XLALPrintError( "indexStartResamp, indexEndResamp: %u %u\n", indexStartResamp, indexEndResamp );
3658 XLALPrintError( "ERROR! numSamplesIn only: %u\n", numSamplesIn );
3659 XLALPrintError( "diff in indices, and num samples: %i %u\n", ( indexEndResamp - indexStartResamp ), numSamplesIn );
3661 }
3662
3663 REAL8 taup_j = 0.0;
3664 REAL8 cycles = 0.0;
3665 REAL4 cosphase, sinphase;
3666 COMPLEX8 em2piphase;
3667 for ( UINT4 j = 0; j < ( indexEndResamp - indexStartResamp ); j ++ ) {
3668 /* j does appear to need indexStartResamp: count from overall start */
3669 taup_j = ( j + indexStartResamp ) * dt + Dtau0;
3670 //REAL8 Dtau_alpha_j = Dtau0 + taup_j;
3671
3672 cycles = - freqShift * taup_j;
3673
3674 //REAL8 Dtau_pow_kp1 = Dtau_alpha_j;
3675 /* Unused because we ignore spindown in CrossCorr */
3676 //for ( UINT4 k = 1; k <= s_max; k++ )
3677 // {
3678 // Dtau_pow_kp1 *= Dtau_alpha_j;
3679 // cycles += - LAL_FACT_INV[k+1] * doppler->fkdot[k] * Dtau_pow_kp1;
3680 // } // for k = 1 ... s_max
3681
3682 XLAL_CHECK( XLALSinCos2PiLUT( &sinphase, &cosphase, cycles ) == XLAL_SUCCESS, XLAL_EFUNC );
3683 em2piphase = crectf( cosphase, sinphase );
3684
3685 // weight the complex timeseries by the antenna patterns
3686 /* old comment above? I think it means by any freqshift */
3687 xOut[j + insertPoint] = em2piphase * xIn->data->data[( j + indexStartResamp )];
3688
3689 } // for j < numSamplesIn
3690
3691 return XLAL_SUCCESS;
3692
3693} // XLALApplyCrossCorrFreqShiftResamp()
3694
3695/** Compute the equivalent of Fa and Fb for CrossCorr's rho statistic */
3696static int
3698(
3699 ResampCrossCorrWorkspace *restrict ws, /**< [out] contains modified Fa and Fb for cross-correlation */
3700 COMPLEX8 *restrict wsFaX_k, /**< [out] contains modified and normalized Fa for cross-correlation statistic */
3701 COMPLEX8 *restrict wsFbX_k, /**< [out] contains modified and normalized Fb for cross-correlation statistic */
3702 const MultiResampSFTPairMultiIndexList *restrict resampMultiPairs, /**< [in] resamp multi list of SFT pairs */
3703 const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_a, /**< [in] Resampled, heterodyned A(t)x(t) */
3704 const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_b, /**< [in] Resampled, heterodyned B(t)x(t) */
3705 const PulsarDopplerParams *restrict dopplerpos, /**< [in] Doppler point to search */
3706 const PulsarDopplerParams *restrict binaryTemplateSpacings, /**< [in] spacings for the search */
3707 const REAL8 SRCsampPerTcoh, /**< [in] floating point number of samples per tShort equivalent */
3708 const UINT4 detX, /**< [in] detector X index */
3709 const UINT4 sftK, /**< [in] tShort K index*/
3710 const UINT4 detY, /**< [in] detector Y index */
3711 const BOOLEAN isL /**< [in] Indicates that is not K but L, the second half of the cross-corr pair */
3712)
3713{
3714 XLAL_CHECK( ws != NULL, XLAL_EINVAL );
3715 XLAL_CHECK( wsFaX_k != NULL, XLAL_EINVAL );
3716 XLAL_CHECK( wsFbX_k != NULL, XLAL_EINVAL );
3717 const REAL8 FreqOut0 = dopplerpos->fkdot[0];
3718 const REAL8 fHet = multiTimeSeries_SRC_a->data[0]->f0;
3719 const REAL8 dt_SRC = multiTimeSeries_SRC_b->data[0]->deltaT;
3720 const REAL8 dFreqMetric = binaryTemplateSpacings->fkdot[0];
3721
3722 /* Compare to the F-statistic timing model, T1600531. Here, we cannot
3723 * change dt_SRC -- it is fixed and given to us. We cannot change it
3724 * because dt_SRC, after ceiling and power-of-two rounding, determined
3725 * by TspanFFT in SetupFstatResamp, and that TspanFFT must be = Tobs
3726 * for us to get the resampling data.
3727 * Where the F-statistic handles power-of-two rounding by reducing
3728 * dt_SRC, we must instead increase T_FFT by zero-padding.
3729 * Yet the number of bins, numSamplesFFT, is fixed.
3730 * What does this imply? Namely, we have a finer frequency resolution,
3731 * which we must use to evaluate cycles for times inside the FFT (as
3732 * well as for bin shifts):
3733 * dFreqMetric -> dFreqFFT
3734 * How do we find dFreqFFT? It is not dFreqMetric/decimateFFT now,
3735 * because T_FFT was lengthened. Whereas F-stat has a higher maximum
3736 * frequency of the band, we have a higher frequency resolution.
3737 * Nevertheless dFreqFFT remains equal to
3738 * dFreqFFT = 1/T_FFT = 1/(dt_SRC * numSamplesFFT), definitionally.
3739 * So if we defined a variable RedecimateFFT, by
3740 * dFreqFFT := dFreqMetric/RedecimateFFT
3741 * ->RedecimateFFT = dFreqMetric/(dFreqFFT)
3742 * = dFreqMetric * dt_SRC * numSamplesFFT
3743 * The finer frequency resolution needed by our FFT means that
3744 * RedecimateFFT is bigger than decimateFFT, by between 1x and 2x.
3745 * Thus, we must also change multiplications,
3746 * x * decimateFFT -> (UINT4)floor( x * RedecimateFFT )
3747 * - - - Comparison to the timing model document - - -
3748 * In the workspace function, we note that
3749 * our SRCsampPerTcoh corresponds to N^SRC_samp from the document.
3750 * However, our N^SRC_samp for a given Tcoh will be smaller than
3751 * The F-statistic, because for fixed number of FFT bins, dt_SRC
3752 * will be bigger than in the F-statistic (because it was not
3753 * reducable to fit the next power of 2). Correspondingly, our R
3754 * is smaller. Specifically,
3755 * R_crosscorr / R_fstat = D_fstat / D_crosscorr,
3756 * Where D_fstat is decimateFFT and D_crosscorr is RedecimateFFT.
3757 * This ratio is simply the power-of-2 rounding, i.e.,
3758 * R_crosscorr / R_fstat = numSamplesFFT0 / numSamplesFFT,
3759 * - - - CrossCorr timing model by analogy - - -
3760 * Whereas the F-stat timing model had,
3761 * tau^eff_F = tau^(0)_Fbin +
3762 * N^FFT_samp / N_fbin * (
3763 * R(tau^(0)_spin +b tau^(0)_bary) +5log_2(N^FFT_samp) tau^(0)_FFT
3764 * ),
3765 * we have no search over spin-down and our b = 1 always.
3766 * Our equivalent of tau^(0)_Fbin, however, is different, but the
3767 * more critical difference is the way that semicoherent segments are
3768 * combined. Namely, instead of multiplying
3769 * tau_semi_F = tau^eff_F by (Tobs/Tcoh) Ndet, [not in timing document]
3770 * we must calculate the above and multiply by the overlap factor,
3771 * (tCoh/tShort), after adding in any paired detectors. So we will have
3772 * tau_semi_CC ~= tau^eff_CC (Tobs/Tshort) * (Ndet + (Ndet+1)Ndet/2 ) ,
3773 * where
3774 * tau^eff_CC ~= tau^(0)_CCbin +
3775 * N^FFT_samp / N_CCbin * (
3776 * R_CC b tau^(0)_bary + 5log_2(N^FFT_samp) tau^(0)_FFT
3777 * ).
3778 * More accurately, the Ndet term must go inside, because barycentering
3779 * occurs once per detector, the first FFT of a pair happens once per
3780 * detector, and the second FFT of a pair happens Triangular(Ndet),
3781 * where Triangular is the triangular number sequence,
3782 * Triangular(Ndet) = (Ndet)(Ndet+1)/2.
3783 * Thus the full semicoherent number should be
3784 * tau_semi_CC = (Tobs/Tshort) tau^(0)_CCbin + N^FFT_samp/N_CCbin *(
3785 * (R_CC b tau^(0)_bary) * Ndet +
3786 * (5log_2(N^FFT_samp) tau^(0)_FFT) * (Ndet + Ndet(Ndet+1)/2)
3787 * ).
3788 * Accurately calculating N^FFT_samp = numSamplesFFT is therefore key:
3789 * following from the timing model document for the F-stat,
3790 * numSamplesFFT0 = (Delta f_SFT) decimateFFT / dFreqMetric,
3791 * where,
3792 * delta f_SFT = (1+4/(2 Dterms +1))(Delta f+Delta f_drift+16/Tsft)
3793 * with Delta_f = f_max - f_min,
3794 * for Sco X-1,
3795 * Delta f_drift = v_earth / c + 2 pi f_max / (c Period)
3796 * Putting it altogether, where
3797 * N^FFT_samp = numSamplesFFT,
3798 * = (UINT4)pow(2, ceil(log2(numSamplesFFT0))),
3799 * = (UINT4)pow(2, ceil(log2(
3800 * (decimateFFT/dFreqMetric) *
3801 * (
3802 * (1+4/(2 Dterms + 1)) *
3803 * ( f_max - f_min + 16/Tsft +
3804 * v_earth/c +2 pi f_max /(c Period)
3805 * )
3806 * )
3807 * ))).
3808 * That forms the basis of the CrossCorr timing model.
3809 * (GDM)
3810 */
3811 const REAL4 RedecimateFFT = dFreqMetric * dt_SRC * ( ws->numSamplesFFT ); //Equals metric freq res divided by freq res of our FFT
3812 const REAL8 dFreqFFT = dFreqMetric / RedecimateFFT;
3813 const REAL8 freqShiftInFFT = remainder( FreqOut0 - fHet, dFreqFFT ); // frequency shift to closest bin in final resolution
3814 const REAL8 fMinFFT = fHet + freqShiftInFFT - dFreqFFT * ( ws->numSamplesFFT / 2 ); // we'll shift DC into the *middle bin* N/2 [N always even!]
3815 XLAL_CHECK( FreqOut0 >= fMinFFT, XLAL_EDOM, "Lowest output frequency outside the available frequency band: [FreqOut0 = %.16g] < [fMinFFT = %.16g]\n", FreqOut0, fMinFFT );
3816 /* -> THIS AFFECTS indices below, in FaX_k loop */
3817 const UINT4 offset_bins = ( UINT4 ) lround( ( FreqOut0 - fMinFFT ) / dFreqFFT );
3818 const UINT4 maxOutputBin = offset_bins + ( UINT4 )floor( ( ws->numFreqBinsOut - 1 ) * RedecimateFFT );
3819 XLAL_CHECK( maxOutputBin < ws->numSamplesFFT, XLAL_EDOM, "Highest output frequency bin outside available band: [maxOutputBin = %d] >= [ws->numSamplesFFT = %d]\n", maxOutputBin, ws->numSamplesFFT );
3820
3821 /* start and stop variables */
3822 UINT4 startFirstInd = 0;
3823 UINT4 startInd = 0;
3824 UINT4 endInd = 0;
3825 UINT4 sftIndFirst = 0;
3826 UINT4 detInd = 0;
3827 UINT4 sftInd = 0;
3828
3829 /* set sftInd and dftInd values using the like-named fields encoded in
3830 * resampMultiPairs, which are with respect to the sft vector,
3831 * inputSFTs. This should handle gaps correctly.
3832 * For any loops over derived values, determined only for matching sfts,
3833 * instead use detX, sftK, detY, sftL, otherwise index may be out-of-bound
3834 */
3835 const ResampSFTPairMultiIndexList *restrict resampMultiPairsDetX = &( resampMultiPairs->data[detX] );
3836 const ResampSFTMultiIndexList *restrict resampMultiPairsDetXsftK = &( resampMultiPairsDetX->data[sftK] );
3837
3838 if ( isL == TRUE ) {
3839 detInd = resampMultiPairsDetXsftK->data[detY].detInd;
3840 } else {
3841 detInd = resampMultiPairsDetX->detInd;
3842 }
3843
3844 /* ------- begin FFT replacement using RESAMP ------- */
3845 /* resamp data */
3846 const COMPLEX8TimeSeries *restrict resampDataArrayA = multiTimeSeries_SRC_a->data[detInd];
3847 const COMPLEX8TimeSeries *restrict resampDataArrayB = multiTimeSeries_SRC_b->data[detInd];
3848
3849 if ( isL == TRUE ) {
3850 /* Need to consider handling if no sftInd exists because none match */
3851 if ( resampMultiPairsDetXsftK->data[detY].length > 0 ) {
3852 sftIndFirst = resampMultiPairsDetXsftK->data[detY].data[0].sftInd;
3853 startFirstInd = ( UINT4 )round( sftIndFirst * SRCsampPerTcoh );
3854 }
3855 } else {
3856 sftIndFirst = resampMultiPairsDetXsftK->sftInd;
3857 startFirstInd = ( UINT4 )round( sftIndFirst * SRCsampPerTcoh );
3858 }
3859 if ( startFirstInd > resampDataArrayA->data->length ) {
3860 startFirstInd = resampDataArrayA->data->length;
3861 }
3862
3863 memset( ws->TS_FFT, 0, ws->numSamplesFFT * sizeof( ws->TS_FFT[0] ) );
3864 UINT4 sftLength = 0;
3865 if ( isL == TRUE ) {
3866 sftLength = resampMultiPairsDetXsftK->data[detY].length;
3867 } else {
3868 sftLength = 1;
3869 }
3870 // Load and FFT A time series
3871 for ( UINT4 sft = 0; sft < sftLength; sft++ ) {
3872 //if (resampMultiPairsDetXsftK->data[detY].data[sft].sciFlag > 0){
3873 /* Needs to be defined wrt resamp time series, so:*/
3874 if ( isL == TRUE ) {
3875 sftInd = resampMultiPairsDetXsftK->data[detY].data[sft].sftInd;
3876 } else {
3877 sftInd = resampMultiPairsDetXsftK->sftInd;
3878 }
3879 startInd = ( UINT4 )round( sftInd * SRCsampPerTcoh );
3880 endInd = ( UINT4 )round( ( sftInd + 1 ) * SRCsampPerTcoh );
3881 if ( startInd > resampDataArrayA->data->length ) {
3882 startInd = resampDataArrayA->data->length;
3883 }
3884 if ( endInd > resampDataArrayA->data->length ) {
3885 endInd = resampDataArrayA->data->length;
3886 }
3887 if ( startInd > endInd ) {
3888 startInd = endInd;
3889 }
3890 UINT4 headOfSliceIndex = startInd - startFirstInd;
3891 XLAL_CHECK( XLALApplyCrossCorrFreqShiftResamp( ws->TS_FFT, resampDataArrayA, dopplerpos, freqShiftInFFT, startInd, endInd, ws->numSamplesFFT, headOfSliceIndex ) == XLAL_SUCCESS, XLAL_EFUNC );
3892 //}
3893 }
3894 fftwf_execute( ws->fftplan );
3895 for ( UINT4 k = 0; k < ws->numFreqBinsOut; k++ ) {
3896 ws->FaX_k[k] = ws->FabX_Raw [ offset_bins + ( UINT4 )floor( k * RedecimateFFT ) ];
3897 }
3898 // END load and FFT A time series
3899
3900 // Load and FFT B time series
3901 memset( ws->TS_FFT, 0, ws->numSamplesFFT * sizeof( ws->TS_FFT[0] ) );
3902 for ( UINT4 sft = 0; sft < sftLength; sft++ ) {
3903 //if (resampMultiPairsDetXsftK->data[detY].data[sft].sciFlag > 0){
3904 if ( isL == TRUE ) {
3905 sftInd = resampMultiPairsDetXsftK->data[detY].data[sft].sftInd;
3906 } else {
3907 sftInd = resampMultiPairsDetXsftK->sftInd;
3908 }
3909 startInd = ( UINT4 )round( sftInd * SRCsampPerTcoh );
3910 endInd = ( UINT4 )round( ( sftInd + 1 ) * SRCsampPerTcoh );
3911 if ( startInd > resampDataArrayB->data->length ) {
3912 startInd = resampDataArrayB->data->length;
3913 }
3914 if ( endInd > resampDataArrayB->data->length ) {
3915 endInd = resampDataArrayB->data->length;
3916 }
3917 if ( startInd > endInd ) {
3918 startInd = endInd;
3919 }
3920 UINT4 headOfSliceIndex = startInd - startFirstInd;
3921 XLAL_CHECK( XLALApplyCrossCorrFreqShiftResamp( ws->TS_FFT, resampDataArrayB, dopplerpos, freqShiftInFFT, startInd, endInd, ws->numSamplesFFT, headOfSliceIndex ) == XLAL_SUCCESS, XLAL_EFUNC );
3922 //}
3923 }
3924 fftwf_execute( ws->fftplan );
3925 for ( UINT4 k = 0; k < ws->numFreqBinsOut; k++ ) {
3926 ws->FbX_k[k] = ws->FabX_Raw [ offset_bins + ( UINT4 )floor( k * RedecimateFFT ) ];
3927 }
3928 // End load and FFT B time series
3929
3930 const REAL8 dtauX = GPSDIFF( resampDataArrayB->epoch, dopplerpos->refTime );
3931 const REAL8 timeFromResampStartToSFTFirst = startFirstInd * dt_SRC;
3932 REAL8 f_kOut;
3933 REAL8 f_kIn;
3934 REAL8 cyclesOut;
3935 REAL8 cyclesIn;
3936 REAL8 cycles;
3937 REAL4 sinphase, cosphase;
3938 COMPLEX8 normX_k;
3939 for ( UINT4 k = 0; k < ws->numFreqBinsOut; k++ ) {
3940 f_kOut = FreqOut0 + k * dFreqMetric;
3941 f_kIn = ( offset_bins + ( UINT4 )floor( k * RedecimateFFT ) ) * dFreqFFT;
3942 cyclesOut = - f_kOut * dtauX;
3943 cyclesIn = -f_kIn * timeFromResampStartToSFTFirst;
3944 cycles = cyclesOut + cyclesIn;
3945 XLALSinCos2PiLUT( &sinphase, &cosphase, cycles );
3946 normX_k = dt_SRC * crectf( cosphase, sinphase );
3947 wsFaX_k[k] = normX_k * ws->FaX_k[k];
3948 wsFbX_k[k] = normX_k * ws->FbX_k[k];
3949 } // for k < numFreqBinsOut
3950
3951 return XLAL_SUCCESS;
3952} // XLALComputeFaFb_CrossCorrResamp()
3953
3954/// @}
#define __func__
log an I/O error, i.e.
#define LAL_FFTW_WISDOM_UNLOCK
#define LAL_FFTW_WISDOM_LOCK
int j
int k
#define LALCalloc(m, n)
static double double delta
#define L(i, j)
#define MYMIN(x, y)
#define SINC_SAFETY
#define GPSDIFF(x, y)
#define MYMAX(x, y)
#define SQUARE(x)
#define TRUE
#define FALSE
#define QUAD(x)
const WeaveSearchTimingDenominator denom
Definition: SearchTiming.c:95
LIGOTimeGPSVector * timestamps
#define fprintf
int l
const double xi2
REAL8VectorSequence * XLALCreateREAL8VectorSequence(UINT4 length, UINT4 veclen)
UINT4VectorSequence * XLALCreateUINT4VectorSequence(UINT4 length, UINT4 veclen)
void XLALDestroyUINT4VectorSequence(UINT4VectorSequence *vecseq)
int XLALExtractResampledTimeseries(MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_a, MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_b, FstatInput *input)
Extracts the resampled timeseries from a given FstatInput structure (must have been initialized previ...
DetectorStateSeries * XLALCreateDetectorStateSeries(UINT4 length)
Create a DetectorStateSeries with length entries.
void XLALDestroyDetectorStateSeries(DetectorStateSeries *detStates)
Get rid of a DetectorStateSeries.
int XLALBarycenterEarth(EarthState *earth, const LIGOTimeGPS *tGPS, const EphemerisData *edat)
Computes the position and orientation of the Earth, at some arrival time , specified LIGOTimeGPS inp...
Definition: LALBarycenter.c:78
int XLALBarycenter(EmissionTime *emit, const BarycenterInput *baryinput, const EarthState *earth)
Transforms from detector arrival time in GPS (as specified in the LIGOTimeGPS structure) to pulse em...
AMCoeffs * XLALCreateAMCoeffs(UINT4 numSteps)
Create an AMCeoffs vector for given number of timesteps.
Definition: LALComputeAM.c:435
void XLALDestroyMultiAMCoeffs(MultiAMCoeffs *multiAMcoef)
Destroy a MultiAMCoeffs structure.
Definition: LALComputeAM.c:469
#define LAL_UINT4_MAX
#define LAL_REAL4_MAX
#define LAL_PI
#define LAL_1_PI
#define LAL_TWOPI
unsigned char BOOLEAN
uint64_t UINT8
double REAL8
#define crectf(re, im)
char CHAR
uint32_t UINT4
float complex COMPLEX8
int32_t INT4
float REAL4
void * XLALCalloc(size_t m, size_t n)
void * XLALRealloc(void *p, size_t n)
void XLALFree(void *p)
#define LAL_UINT4_FORMAT
int XLALSincInterpolateCOMPLEX8TimeSeries(COMPLEX8Vector *y_out, const REAL8Vector *t_out, const COMPLEX8TimeSeries *ts_in, UINT4 Dterms)
Interpolate a given regularly-spaced COMPLEX8 timeseries 'ts_in = x_in(j * dt)' onto new samples 'y_o...
void LogPrintf(LogLevel_t, const char *format,...) _LAL_GCC_PRINTF_FORMAT_(2
LOG_CRITICAL
void XLALDestroyMultiNoiseWeights(MultiNoiseWeights *weights)
Destroy a MultiNoiseWeights object.
Definition: PSDutils.c:172
int XLALEquipCrossCorrPairsWithScienceFlags(MultiResampSFTPairMultiIndexList *resampMultiPairs, MultiREAL8TimeSeries *scienceFlagVect)
Demarcate pairs with flags about whether data exists in zero-padded timeseries.
void XLALDestroyResampSFTIndexList(ResampSFTIndexList *sftResampList)
void XLALDestroySFTPairIndexList(SFTPairIndexList *sftPairs)
Destroy a SFTPairIndexList structure.
void XLALDestroyResampCrossCorrWorkspace(void *workspace)
int XLALCreateCrossCorrWorkspace(ResampCrossCorrWorkspace **wsOut, COMPLEX8 **ws1KFaX_kOut, COMPLEX8 **ws1KFbX_kOut, COMPLEX8 **ws2LFaX_kOut, COMPLEX8 **ws2LFbX_kOut, MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_aOut, MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_bOut, const PulsarDopplerParams binaryTemplateSpacings, FstatInput *resampFstatInput, const UINT4 numFreqBins, const REAL8 tCoh, const BOOLEAN treatWarningsAsErrors)
‍** (possible future function) does not work – would adjust timestamps of an SFT vector *‍/
MultiLIGOTimeGPSVector * XLALGenerateMultiTshortTimestamps(const MultiLIGOTimeGPSVector *restrict multiTimes, const REAL8 tShort, const UINT4 numShortPerDet, const BOOLEAN alignTShorts)
Given a multi-SFT vector, return a MultiLIGOTimeGPSVector holding the modified SFT timestamps (produc...
int XLALCalculateCrossCorrPhaseDerivatives(REAL8VectorSequence **phaseDerivs, const PulsarDopplerParams *dopplerPoint, const EphemerisData *edat, SFTIndexList *indexList, MultiSSBtimes *multiTimes, const DopplerCoordinateSystem *coordSys)
calculate signal phase derivatives wrt Doppler coords, for each SFT
int XLALModifyMultiAMCoeffsWeights(MultiNoiseWeights **multiWeights, const REAL8 tShort, const REAL8 tSFTOld, const UINT4 numShortPerDet, const MultiLIGOTimeGPSVector *restrict multiTimes)
Modify multiple detectors' amplitude weight coefficients for tShort.
int XLALCreateSFTPairIndexList(SFTPairIndexList **pairIndexList, SFTIndexList *indexList, MultiSFTVector *sfts, REAL8 maxLag, BOOLEAN inclAutoCorr)
Construct list of SFT pairs for inclusion in statistic.
AMCoeffs * XLALComputeAMCoeffsShort(const DetectorStateSeries *DetectorStates, SkyPosition skypos)
(test function) used for computing amplitude modulation weights
int XLALCalculateLMXBCrossCorrDiagMetric(REAL8 *hSens, REAL8 *g_ff, REAL8 *g_aa, REAL8 *g_TT, REAL8 *g_pp, REAL8 *weightedMuTAve, PulsarDopplerParams DopplerParams, REAL8Vector *G_alpha, SFTPairIndexList *pairIndexList, SFTIndexList *indexList, MultiSFTVector *sfts, MultiNoiseWeights *multiWeights)
REAL8TimeSeries * XLALCrossCorrGapFinderResampAlt(LIGOTimeGPSVector *restrict timestamps, const SFTVector *restrict sfts)
(test function) find gaps in the data given the SFTs
int XLALCalculateCrossCorrGammasResampShort(REAL8Vector **Gamma_ave, REAL8Vector **Gamma_circ, MultiResampSFTPairMultiIndexList *resampMultiPairIndexList, MultiAMCoeffs *multiCoeffs)
test function for RESAMPLING with tShort
int XLALFillDetectorTensorShort(DetectorState *detState, const LALDetector *detector)
(test function) fill detector state with tShort, importing various slightly-modified LALPulsar functi...
int XLALWeightMultiAMCoeffsShort(MultiAMCoeffs *multiAMcoef, const MultiNoiseWeights *multiWeights, REAL8 tShort, REAL8 tSFTOld, UINT4 numShortPerDet, MultiLIGOTimeGPSVector *multiTimes)
(test function) used for weighting multi amplitude modulation coefficients
LIGOTimeGPSVector * XLALExtractTimestampsFromSFTsShort(REAL8TimeSeries **sciFlag, const SFTVector *sfts, REAL8 tShort, UINT4 numShortPerDet)
‍** (possible future function) Wrapper for Bessel Orbital Space stepper in the manner of V....
MultiNoiseWeights * XLALModifyMultiWeights(const MultiNoiseWeights *restrict multiWeights, const REAL8 tShort, const REAL8 tSFTOld, const UINT4 numShortPerDet, const MultiLIGOTimeGPSVector *restrict multiTimes)
Modify multiple detectors' amplitude weight coefficients for tShort.
int XLALCalculateCrossCorrGammas(REAL8Vector **Gamma_ave, REAL8Vector **Gamma_circ, SFTPairIndexList *pairIndexList, SFTIndexList *indexList, MultiAMCoeffs *multiCoeffs)
Construct vector of G_alpha amplitudes for each SFT pair.
int XLALCalculatePulsarCrossCorrStatisticResamp(REAL8Vector *restrict ccStatVector, REAL8Vector *restrict evSquaredVector, REAL8Vector *restrict numeEquivAve, REAL8Vector *restrict numeEquivCirc, const REAL8Vector *restrict resampCurlyGAmp, const MultiResampSFTPairMultiIndexList *restrict resampMultiPairs, const MultiNoiseWeights *restrict multiWeights, const PulsarDopplerParams *restrict binaryTemplateSpacings, const PulsarDopplerParams *restrict dopplerpos, const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_a, const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_b, ResampCrossCorrWorkspace *restrict ws, COMPLEX8 *restrict ws1KFaX_k, COMPLEX8 *restrict ws1KFbX_k, COMPLEX8 *restrict ws2LFaX_k, COMPLEX8 *restrict ws2LFbX_k)
Calculate multi-bin cross-correlation statistic using resampling.
int XLALCreateSFTPairIndexListAccurateResamp(SFTPairIndexList **pairIndexList, UINT4VectorSequence **sftPairForTshortPair, SFTIndexList *indexList, MultiResampSFTPairMultiIndexList *resampPairs, const MultiLIGOTimeGPSVector *restrict multiTimes, const MultiLIGOTimeGPSVector *restrict resampMultiTimes)
Construct list of SFT pairs corresponding to a list of tShort pairs.
int XLALTestResampPairIndexList(MultiResampSFTPairMultiIndexList *resampMultiPairIndexList)
Check that the contents of a resampling multi-pair index list are sensible by inspection.
MultiLIGOTimeGPSVector * XLALModifyMultiTimestampsFromSFTs(MultiREAL8TimeSeries **scienceFlagVect, const MultiLIGOTimeGPSVector *restrict multiTimes, const REAL8 tShort, const UINT4 numShortPerDet)
Given a multi-SFT vector, return a MultiLIGOTimeGPSVector holding the modified SFT timestamps (produc...
int XLALCreateSFTPairIndexListResamp(MultiResampSFTPairMultiIndexList **resampMultiPairIndexList, SFTPairIndexList **pairIndexList, SFTIndexList *indexList, MultiSFTVector *sfts, REAL8 maxLag, BOOLEAN inclAutoCorr, BOOLEAN inclSameDetector, REAL8 Tsft, REAL8 Tshort)
Resampling-modified: construct list of SFT pairs for inclusion in statistic.
LIGOTimeGPSVector * XLALGenerateTshortTimestamps(const REAL8 tShort, const UINT4 numShortPerDet, const LIGOTimeGPS epoch)
Generate timestamps for one detector with tShort.
MultiAMCoeffs * XLALComputeMultiAMCoeffsShort(const MultiDetectorStateSeries *multiDetStates, const MultiNoiseWeights *multiWeights, SkyPosition skypos, REAL8 tShort, REAL8 tSFTOld, UINT4 numShortPerDet, MultiLIGOTimeGPSVector *multiTimes)
(test function) used for computing multi amplitude modulation weights
int XLALCalculateCrossCorrPhaseMetricShort(gsl_matrix **g_ij, gsl_vector **eps_i, REAL8 *sumGammaSq, const REAL8VectorSequence *phaseDerivs, const MultiResampSFTPairMultiIndexList *resampMultiPairs, const REAL8Vector *Gamma_ave, const REAL8Vector *Gamma_circ, const DopplerCoordinateSystem *coordSys)
(test function) Redesigning to use Tshort instead
int XLALCalculatePulsarCrossCorrStatistic(REAL8 *ccStat, REAL8 *evSquared, REAL8Vector *curlyGAmp, COMPLEX8Vector *expSignalPhases, UINT4Vector *lowestBins, REAL8VectorSequence *sincList, SFTPairIndexList *sftPairs, SFTIndexList *sftIndices, MultiSFTVector *inputSFTs, MultiNoiseWeights *multiWeights, UINT4 numBins)
Calculate multi-bin cross-correlation statistic.
int XLALModifyAMCoeffsWeights(REAL8Vector **resampMultiWeightsX, const MultiNoiseWeights *restrict multiWeights, const REAL8 tShort, const REAL8 tSFTOld, const UINT4 numShortPerDet, const MultiLIGOTimeGPSVector *restrict multiTimes, const UINT4 maxNumStepsOldIfGapless, const UINT4 X)
Modify amplitude weight coefficients for tShort.
void XLALDestroySFTIndexList(SFTIndexList *sftIndices)
Destroy a SFTIndexList structure.
static int XLALApplyCrossCorrFreqShiftResamp(COMPLEX8 *restrict xOut, const COMPLEX8TimeSeries *restrict xIn, const PulsarDopplerParams *restrict doppler, const REAL8 freqShift, const UINT4 indexStartResamp, const UINT4 indexEndResamp, const UINT4 numSamplesIn, const UINT4 insertPoint)
Imported and modified from ComputeFstat_Resamp.c.
void XLALDestroyMultiResampSFTPairMultiIndexList(MultiResampSFTPairMultiIndexList *sftMultiPairsResamp)
void XLALDestroyResampSFTMultiIndexList(ResampSFTMultiIndexList *sftResampMultiList)
int XLALCombineCrossCorrGammas(REAL8Vector **resampGamma, REAL8Vector *Gamma, UINT4VectorSequence *sftPairForTshortPair, REAL8 Tsft, REAL8 Tshort)
Combine G_alpha amplitudes for SFT pairs into amplitudes for Tshort pairs.
int XLALCreateSFTIndexListFromMultiSFTVect(SFTIndexList **indexList, MultiSFTVector *sfts)
Construct flat SFTIndexList out of a MultiSFTVector.
int XLALGetDopplerShiftedFrequencyInfo(REAL8Vector *shiftedFreqs, UINT4Vector *lowestBins, COMPLEX8Vector *expSignalPhases, REAL8VectorSequence *sincList, UINT4 numBins, PulsarDopplerParams *dopp, SFTIndexList *sftIndices, MultiSFTVector *inputSFTs, MultiSSBtimes *multiTimes, MultiUINT4Vector *badBins, REAL8 Tsft)
Calculate the Doppler-shifted frequency associated with each SFT in a list.
int XLALCalculateCrossCorrGammasResamp(REAL8Vector **Gamma_ave, REAL8Vector **Gamma_circ, MultiResampSFTPairMultiIndexList *resampMultiPairIndexList, MultiAMCoeffs *multiCoeffs)
test function for RESAMPLING
int XLALCalculateCrossCorrPhaseMetric(gsl_matrix **g_ij, gsl_vector **eps_i, REAL8 *sumGammaSq, const REAL8VectorSequence *phaseDerivs, const SFTPairIndexList *pairIndexList, const REAL8Vector *Gamma_ave, const REAL8Vector *Gamma_circ, const DopplerCoordinateSystem *coordSys)
calculate phase metric for CW cross-correlation search, as well as vector used for parameter offsets
void XLALDestroyMultiMatchList(MultiResampSFTMultiCountList *localMultiListOfLmatchingGivenMultiK)
MultiLIGOTimeGPSVector * XLALExtractMultiTimestampsFromSFTsShort(MultiREAL8TimeSeries **scienceFlagVect, const MultiSFTVector *multiSFTs, REAL8 tShort, UINT4 numShortPerDet)
Given a multi-SFT vector, return a MultiLIGOTimeGPSVector holding the SFT timestamps (test function u...
int XLALCalculateLMXBCrossCorrDiagMetricShort(REAL8 *hSens, REAL8 *g_ff, REAL8 *g_aa, REAL8 *g_TT, REAL8 *g_pp, const PulsarDopplerParams DopplerParams, const REAL8Vector *restrict G_alpha, const MultiResampSFTPairMultiIndexList *restrict resampMultiPairIndexList, const MultiLIGOTimeGPSVector *restrict timestamps, const MultiNoiseWeights *restrict multiWeights)
MODIFIED for Tshort: calculate metric diagonal components, also include the estimation of sensitivity...
static int XLALComputeFaFb_CrossCorrResamp(ResampCrossCorrWorkspace *restrict ws2L, COMPLEX8 *restrict wsFaX_k, COMPLEX8 *restrict wsFbX_k, const MultiResampSFTPairMultiIndexList *restrict resampMultiPairs, const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_a, const MultiCOMPLEX8TimeSeries *restrict multiTimeSeries_SRC_b, const PulsarDopplerParams *restrict dopplerpos, const PulsarDopplerParams *restrict binaryTemplateSpacings, const REAL8 SRCsampPerTcoh, const UINT4 detX, const UINT4 sftK, const UINT4 detY, const BOOLEAN isL)
Compute the equivalent of Fa and Fb for CrossCorr's rho statistic.
REAL8TimeSeries * XLALCrossCorrGapFinderResamp(LIGOTimeGPSVector *restrict timestamps, const LIGOTimeGPSVector *restrict Times)
Find gaps in the data given the SFTs.
UINT4 XLALCrossCorrNumShortPerDetector(const REAL8 resampTshort, const INT4 startTime, const INT4 endTime)
Compute the number of tShort segments per detector.
DetectorStateSeries * XLALGetDetectorStatesShort(const LIGOTimeGPSVector *timestamps, const LALDetector *detector, const EphemerisData *edat, REAL8 tOffset, REAL8 tShort, UINT4 numShortPerDet)
(test function) get detector states for tShort
LIGOTimeGPSVector * XLALModifyTimestampsFromSFTsShort(REAL8TimeSeries **sciFlag, const LIGOTimeGPSVector *restrict Times, const REAL8 tShort, const UINT4 numShortPerDet)
Modify timestamps from one detector with tShort.
int XLALCreateSFTPairIndexListShortResamp(MultiResampSFTPairMultiIndexList **resampMultiPairIndexList, const REAL8 maxLag, const BOOLEAN inclAutoCorr, const BOOLEAN inclSameDetector, const REAL8 Tsft, const MultiLIGOTimeGPSVector *restrict multiTimes)
With Tshort, and Resampling-modified: construct list of SFT pairs for inclusion in statistic.
void XLALDestroyResampSFTPairMultiIndexList(ResampSFTPairMultiIndexList *sftResampPairMultiList)
MultiDetectorStateSeries * XLALGetMultiDetectorStatesShort(const MultiLIGOTimeGPSVector *multiTS, const MultiLALDetector *multiIFO, const EphemerisData *edat, REAL8 tOffset, REAL8 tShort, UINT4 numShortPerDet)
(test function) get multi detector states for tShort
int XLALCalculateCrossCorrPhaseDerivativesShort(REAL8VectorSequence **resampPhaseDerivs, const PulsarDopplerParams *dopplerPoint, const EphemerisData *edat, SFTIndexList *indexList, MultiResampSFTPairMultiIndexList *resampMultiPairs, MultiSSBtimes *multiTimes, const DopplerCoordinateSystem *coordSys)
(test function) MODIFIED for Tshort
#define PULSAR_MAX_SPINS
maximal number of spin-parameters (Freq + spindowns) we can handle
LIGOTimeGPSVector * XLALCreateTimestampVector(UINT4 len)
Allocate a LIGOTimeGPSVector.
Definition: SFTtimestamps.c:47
void XLALDestroyMultiTimestamps(MultiLIGOTimeGPSVector *multiTS)
Destroy a MultiLIGOTimeGPSVector timestamps vector.
int XLALSinCosLUT(REAL4 *sinx, REAL4 *cosx, REAL8 x)
Calculate sin(x) and cos(x) to roughly 1e-7 precision using a lookup-table and Taylor-expansion.
Definition: SinCosLUT.c:83
int XLALSinCos2PiLUT(REAL4 *sin2pix, REAL4 *cos2pix, REAL8 x)
Calculate sin(2*pi*x) and cos(2*pi*x) to roughly 1e-7 precision using a lookup-table and Taylor-expan...
Definition: SinCosLUT.c:97
COORDINATESYSTEM_ECLIPTIC
COORDINATESYSTEM_EQUATORIAL
COMPLEX8TimeSeries * XLALCreateCOMPLEX8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
void XLALDestroyCOMPLEX8TimeSeries(COMPLEX8TimeSeries *series)
REAL8TimeSeries * XLALCreateREAL8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalDimensionlessUnit
REAL8 XLALComputePhaseDerivative(REAL8 t, const PulsarDopplerParams *dopplerPoint, DopplerCoordinateID coordID, const EphemerisData *edat, const LALDetector *site, BOOLEAN includeRoemer)
COMPLEX8Vector * XLALCreateCOMPLEX8Vector(UINT4 length)
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
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,...)
XLAL_EBADLEN
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFUNC
XLAL_EDOM
XLAL_EINVAL
XLAL_EFAILED
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
REAL8 XLALGPSDiff(const LIGOTimeGPS *t1, const LIGOTimeGPS *t0)
float data[BLOCKSIZE]
Definition: hwinject.c:360
string prefix
double alpha
size_t numDetectors
double t0
This structure contains the per-SFT (weighted) antenna-pattern functions , with the SFT-index,...
Definition: LALComputeAM.h:63
REAL4 B
summed antenna-pattern matrix coefficient:
Definition: LALComputeAM.h:67
REAL4Vector * b
(weighted) per-SFT antenna-pattern function
Definition: LALComputeAM.h:65
REAL4 A
summed antenna-pattern matrix coefficient:
Definition: LALComputeAM.h:66
REAL4 C
summed antenna-pattern matrix coefficient:
Definition: LALComputeAM.h:68
REAL4Vector * a
(weighted) per-SFT antenna-pattern function
Definition: LALComputeAM.h:64
REAL4 D
determinant
Definition: LALComputeAM.h:69
REAL8 Sinv_Tsft
normalization-factor (using single-sided PSD!)
Definition: LALComputeAM.h:133
REAL4 Dd
determinant factor , such that
Definition: LALComputeAM.h:132
Basic input structure to LALBarycenter.c.
REAL8 alpha
Source right ascension in ICRS J2000 coords (radians).
REAL8 dInv
1/(distance to source), in 1/sec.
LIGOTimeGPS tgps
input GPS arrival time.
REAL8 delta
Source declination in ICRS J2000 coords (radians)
LALDetector site
detector site info.
COMPLEX8Sequence * data
A vector of COMPLEX8FrequencySeries.
COMPLEX8FrequencySeries * data
Pointer to the data array.
UINT4 length
Number of elements in array.
COMPLEX8Sequence * data
COMPLEX8 * data
State-info about position, velocity and LMST of a detector together with corresponding EarthState.
REAL8 vDetector[3]
Cart.
EarthState earthState
EarthState information.
REAL8 rDetector[3]
Cartesian coords of detector position in ICRS J2000.
LIGOTimeGPS tGPS
GPS timestamps corresponding to this entry.
SymmTensor3 detT
Detector-tensor components in SSB-fixed, Cartesian coordinates.
REAL8 LMST
local mean sidereal time at the detector-location in radians
Timeseries of DetectorState's, representing the detector-info at different timestamps.
REAL8 deltaT
timespan centered on each timestamp (e.g.
CoordinateSystem system
The coordinate system used for detector's position/velocity and detector-tensor.
DetectorState * data
array of DetectorState entries
UINT4 length
total number of entries
LALDetector detector
detector-info corresponding to this timeseries
type describing a Doppler coordinate system: lists the number of dimensions and the symbolic names of...
DopplerCoordinateID coordIDs[DOPPLERMETRIC_MAX_DIM]
coordinate 'names'
UINT4 dim
number of dimensions covered
Basic output structure of LALBarycenterEarth.c.
REAL8 gmstRad
Greenwich Mean Sidereal Time (GMST) in radians, at tgps.
Basic output structure produced by LALBarycenter.c.
REAL8 rDetector[3]
Cartesian coords (0=x,1=y,2=z) of detector position at $t_a$ (GPS), in ICRS J2000 coords.
REAL8 vDetector[3]
This structure contains all information about the center-of-mass positions of the Earth and Sun,...
REAL8 location[3]
INT4 gpsNanoSeconds
A vector of 'timestamps' of type LIGOTimeGPS.
Definition: SFTfileIO.h:188
REAL8 deltaT
'length' of each timestamp (e.g.
Definition: SFTfileIO.h:194
LIGOTimeGPS * data
array of timestamps
Definition: SFTfileIO.h:193
UINT4 length
number of timestamps
Definition: SFTfileIO.h:192
Multi-IFO container for antenna-pattern coefficients and atenna-pattern matrix .
Definition: LALComputeAM.h:137
UINT4 length
number of IFOs
Definition: LALComputeAM.h:141
AMCoeffs ** data
noise-weighted AM-coeffs , and
Definition: LALComputeAM.h:142
AntennaPatternMatrix Mmunu
antenna-pattern matrix
Definition: LALComputeAM.h:143
Multi-IFO container for COMPLEX8 resampled timeseries.
Definition: LFTandTSutils.h:52
COMPLEX8TimeSeries ** data
array of COMPLEX8TimeSeries (pointers)
Definition: LFTandTSutils.h:57
Multi-IFO time-series of DetectorStates.
UINT4 length
number of detectors
DetectorStateSeries ** data
vector of pointers to DetectorStateSeries
array of detectors definitions 'LALDetector'
UINT4 length
number of detectors
LALDetector sites[PULSAR_MAX_DETECTORS]
array of site information
A collection of (multi-IFO) LIGOTimeGPSVector time-stamps vectors.
Definition: SFTfileIO.h:198
UINT4 length
number of timestamps vectors or ifos
Definition: SFTfileIO.h:202
LIGOTimeGPSVector ** data
timestamps vector for each ifo
Definition: SFTfileIO.h:203
One noise-weight (number) per SFT (therefore indexed over IFOs and SFTs.
Definition: PSDutils.h:71
REAL8 Sinv_Tsft
normalization factor used: (using single-sided PSD!)
Definition: PSDutils.h:77
UINT4 length
number of detectors
Definition: PSDutils.h:75
REAL8Vector ** data
weights-vector for each detector
Definition: PSDutils.h:76
A collection of (multi-IFO) REAL8 time-series.
REAL8TimeSeries ** data
Pointer to the data array.
UINT4 length
Number of elements in array.
OUTER List of SFT indices.
ResampSFTMultiCountListDet * data
list per-detectors X
UINT4 length
number of detectors X
Resampling Multi List of all paired SFTs L_Y_K_X, top level (multiple pairs, multiple detectors)
UINT4 oldPairCount
count of sft pairs, old-style
REAL8 Tshort
Duration of resamp Tshort.
REAL8 maxLag
Maximum allowed lag time.
SFTPairIndexList * pairIndexList
Make a classic pair index list.
UINT4 sftTotalCount
count of all sfts
BOOLEAN inclSameDetector
Do we include same detectors?
ResampSFTPairMultiIndexList * data
list per-detector X
UINT4 length
number of detectors X
REAL8 Tsft
Duration of one SFT.
SFTIndexList * indexList
Make an overall flat index list.
UINT4 allPairCount
count of all pairs
BOOLEAN inclAutoCorr
Do we include auto-correlation?
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
Multi-IFO container for SSB timings.
Definition: SSBtimes.h:67
SSBtimes ** data
array of SSBtimes (pointers)
Definition: SSBtimes.h:72
UINT4 length
number of IFOs
Definition: SSBtimes.h:71
A collection of UINT4Vectors – one for each IFO
UINT4Vector ** data
unit4vector for each ifo
UINT4 length
number of ifos
Type containing the 'Doppler-parameters' affecting the time-evolution of the phase.
REAL8 period
Binary: orbital period (sec)
PulsarSpins fkdot
Intrinsic spins: [Freq, f1dot, f2dot, ... ] where fkdot = d^kFreq/dt^k.
LIGOTimeGPS refTime
Reference time of pulsar parameters (in SSB!)
REAL8 asini
Binary: projected, normalized orbital semi-major axis (s).
REAL4 * data
REAL8Sequence * data
REAL8 * data
COMPLEX8 * FabX_Raw
raw full-band FFT result Fa,Fb
COMPLEX8 * Fa_k
properly normalized F_a(f_k) over output bins
COMPLEX8Vector * TStmp2_SRC
can hold a single-detector SRC-frame spindown-corrected timeseries [without zero-padding]
COMPLEX8 * FaX_k
properly normalized F_a^X(f_k) over output bins
REAL8Vector * SRCtimes_DET
holds uniformly-spaced SRC-frame timesteps translated into detector frame [for interpolation]
fftwf_plan fftplan
buffer FFT plan for given numSamplesOut length
COMPLEX8 * TS_FFT
zero-padded, spindown-corr SRC-frame TS
COMPLEX8 * Fb_k
properly normalized F_b(f_k) over output bins
COMPLEX8 * FbX_k
properly normalized F_b^X(f_k) over output bins
COMPLEX8Vector * TStmp1_SRC
can hold a single-detector SRC-frame spindown-corrected timeseries [without zero-padding]
REAL4 sciFlag
science-or-not value: 1 is science mode, 0 is in a gap
UINT4 detInd
index of detector in list
UINT4 pairInd
index of SFT among overall pairs
UINT4 sftInd
index of SFT in list for this detector L
UINT4 flatInd
index in the flat SFT list
Resampling: List of SFT indices L for a given detector Y_K_X: indexing method is nominally original v...
UINT4 length
number of SFTs
ResampSFTIndex * data
array of SFT indices
UINT4 detInd
original vector index of detector Y
UINT4 length
number of SFTs K_X
UINT4 detInd
original vector index of detector X
ResampSFTMultiCountList * data
array of SFT L_Y indices for given SFT K_X at detector X
UINT4 sftInd
original vector index of sft K
UINT4 length
number of detectors Y
SFTCount * data
arrays of count of SFTs L_Y, at given detector Y, that match each given SFT K_X
Resampling: Multi List of indices of SFT L_Y, for a given sft K_X
ResampSFTIndexList * data
array, per detector, of lists of SFT indices
UINT4 sftInd
original vector index of sft K
UINT4 length
number of detectors Y
UINT4 flatInd
index in the flat SFT list
REAL4 sciFlag
science-or-not value: 1 is science mode, 0 is in a gap
Resampling Multi List of SFT pair indices (L_Y_K), for a given detector X.
UINT4 length
number of K SFTs at detector X
ResampSFTMultiIndexList * data
array of SFT L_Y indices for given SFT K_X at detector X
UINT4 detInd
original vector index of detector X
UINT4 sftCount
number of matching SFTs
UINT4 detInd
original vector index of detector Y
UINT4 sftInd
index of SFT in list for this detector
UINT4 detInd
index of detector in list
List of SFT indices.
UINT4 length
number of SFTs
SFTIndex * data
array of SFT indices
UINT4 sftNum[2]
ordinal numbers of first and second SFTs
List of SFT pair indices.
UINT4 length
number of SFT Pairs
SFTPairIndex * data
array of SFT Pair indices
Simple container for two REAL8-vectors, namely the SSB-timings DeltaT_alpha and Tdot_alpha,...
Definition: SSBtimes.h:60
REAL8Vector * Tdot
dT/dt : time-derivative of SSB-time wrt local time for SFT-alpha
Definition: SSBtimes.h:63
REAL8Vector * DeltaT
Time-difference of SFT-alpha - tau0 in SSB-frame.
Definition: SSBtimes.h:62
LIGOTimeGPS refTime
reference-time 'tau0'
Definition: SSBtimes.h:61
REAL8 longitude
REAL8 latitude
CoordinateSystem system
A symmetric 3x3 tensor (such as detector-tensors), storing only the upper triangle.
UINT4 * data
enum @1 epoch