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
ComputeFstat_Resamp_Generic.c
Go to the documentation of this file.
1//
2// Copyright (C) 2009, 2014--2015 Reinhard Prix
3// Copyright (C) 2012--2015 Karl Wette
4// Copyright (C) 2009 Chris Messenger, Pinkesh Patel, Xavier Siemens, Holger Pletsch
5//
6// This program is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 2 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with with program; see the file COPYING. If not, write to the
18// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19// MA 02110-1301 USA
20//
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <math.h>
25#include <complex.h>
26#include <fftw3.h>
27
30
31#include <lal/FFTWMutex.h>
32#include <lal/Factorial.h>
33#include <lal/LFTandTSutils.h>
34#include <lal/LogPrintf.h>
35#include <lal/SinCosLUT.h>
36#include <lal/TimeSeries.h>
37#include <lal/Units.h>
38
39///
40/// \defgroup ComputeFstat_Resamp_Generic_c Module ComputeFstat_Resamp_Generic.c
41/// \ingroup ComputeFstat_h
42/// \brief Implements a generic version \cite Prix2022 of the \a Resamp FFT-based resampling algorithm for
43/// computing the \f$ \mathcal{F} \f$ -statistic \cite JKS98 .
44///
45
46/// @{
47
48// ========== Resamp internals ==========
49
50// ----- local constants ----------
51
52// ----- local macros ----------
53
54// ----- local types ----------
55
56// ----- workspace ----------
57typedef struct tagResampGenericWorkspace {
58 // intermediate quantities to interpolate and operate on SRC-frame timeseries
59 COMPLEX8Vector *TStmp1_SRC; // can hold a single-detector SRC-frame spindown-corrected timeseries [without zero-padding]
60 COMPLEX8Vector *TStmp2_SRC; // can hold a single-detector SRC-frame spindown-corrected timeseries [without zero-padding]
61 REAL8Vector *SRCtimes_DET; // holds uniformly-spaced SRC-frame timesteps translated into detector frame [for interpolation]
62
63 // input padded timeseries ts(t) and output Fab(f) of length 'numSamplesFFT'
64 UINT4 numSamplesFFTAlloc; // allocated number of zero-padded SRC-frame time samples (related to dFreq)
65 COMPLEX8 *TS_FFT; // zero-padded, spindown-corr SRC-frame TS
66 COMPLEX8 *FabX_Raw; // raw full-band FFT result Fa,Fb
67
68 // arrays of size numFreqBinsOut over frequency bins f_k:
69 COMPLEX8 *FaX_k; // properly normalized F_a^X(f_k) over output bins
70 COMPLEX8 *FbX_k; // properly normalized F_b^X(f_k) over output bins
71 COMPLEX8 *Fa_k; // properly normalized F_a(f_k) over output bins
72 COMPLEX8 *Fb_k; // properly normalized F_b(f_k) over output bins
73 UINT4 numFreqBinsAlloc; // internal: keep track of allocated length of frequency-arrays
74
76
77typedef struct {
78 UINT4 Dterms; // Number of terms to use (on either side) in Windowed-Sinc interpolation kernel
79 MultiCOMPLEX8TimeSeries *multiTimeSeries_DET; // input SFTs converted into a heterodyned timeseries
80 // ----- buffering -----
81 PulsarDopplerParams prev_doppler; // buffering: previous phase-evolution ("doppler") parameters
82 MultiAMCoeffs *multiAMcoef; // buffered antenna-pattern functions
83 MultiSSBtimes *multiSSBtimes; // buffered SSB times, including *only* sky-position corrections, not binary
84 MultiSSBtimes *multiBinaryTimes; // buffered SRC times, including both sky- and binary corrections [to avoid re-allocating this]
85
86 AntennaPatternMatrix Mmunu; // combined multi-IFO antenna-pattern coefficients {A,B,C,E}
87 AntennaPatternMatrix MmunuX[PULSAR_MAX_DETECTORS]; // per-IFO antenna-pattern coefficients {AX,BX,CX,EX}
88
89 MultiCOMPLEX8TimeSeries *multiTimeSeries_SRC_a; // multi-detector SRC-frame timeseries, multiplied by AM function a(t)
90 MultiCOMPLEX8TimeSeries *multiTimeSeries_SRC_b; // multi-detector SRC-frame timeseries, multiplied by AM function b(t)
91
92 UINT4 numSamplesFFT; // length of zero-padded SRC-frame timeseries (related to dFreq)
93 UINT4 decimateFFT; // output every n-th frequency bin, with n>1 iff (dFreq > 1/Tspan), and was internally decreased by n
94 fftwf_plan fftplan; // FFT plan
95
96 // ----- timing -----
97 BOOLEAN collectTiming; // flag whether or not to collect timing information
98 FstatTimingGeneric timingGeneric; // measured (generic) F-statistic timing values
99 FstatTimingResamp timingResamp; // measured Resamp-specific timing model data
100
102
103
104// ----- local prototypes ----------
105
106int XLALSetupFstatResampGeneric( void **method_data, FstatCommon *common, FstatMethodFuncs *funcs, MultiSFTVector *multiSFTs, const FstatOptionalArgs *optArgs );
107int XLALExtractResampledTimeseries_ResampGeneric( MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_a, MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_b, void *method_data );
108int XLALGetFstatTiming_ResampGeneric( const void *method_data, FstatTimingGeneric *timingGeneric, FstatTimingModel *timingModel );
109
110static int XLALComputeFstatResampGeneric( FstatResults *Fstats, const FstatCommon *common, void *method_data );
111static int XLALApplySpindownAndFreqShiftGeneric( COMPLEX8 *xOut, const COMPLEX8TimeSeries *xIn, const PulsarDopplerParams *doppler, REAL8 freqShift );
113static int XLALComputeFaFb_ResampGeneric( ResampGenericMethodData *resamp, ResampGenericWorkspace *ws, const PulsarDopplerParams thisPoint, REAL8 dFreq, UINT4 numFreqBins, const COMPLEX8TimeSeries *TimeSeries_SRC_a, const COMPLEX8TimeSeries *TimeSeries_SRC_b );
114static void XLALGetFFTPlanHints( int *planMode, double *planGenTimeoutSeconds );
115static void XLALDestroyResampGenericWorkspace( void *workspace );
116static void XLALDestroyResampGenericMethodData( void *method_data );
117
118// ==================== function definitions ====================
119
120static void XLALDestroyResampGenericWorkspace( void *workspace )
121{
123
127
128 fftw_free( ws->FabX_Raw );
129 fftw_free( ws->TS_FFT );
130
131 XLALFree( ws->FaX_k );
132 XLALFree( ws->FbX_k );
133 XLALFree( ws->Fa_k );
134 XLALFree( ws->Fb_k );
135
136 XLALFree( ws );
137 return;
138
139} // XLALDestroyResampGenericWorkspace()
140
141static void XLALDestroyResampGenericMethodData( void *method_data )
142{
143
144 ResampGenericMethodData *resamp = ( ResampGenericMethodData * ) method_data;
145
147
148 // ----- free buffer
154
156 fftwf_destroy_plan( resamp->fftplan );
158
159 XLALFree( resamp );
160
161} // XLALDestroyResampGenericMethodData()
162
163int
164XLALSetupFstatResampGeneric( void **method_data,
165 FstatCommon *common,
166 FstatMethodFuncs *funcs,
168 const FstatOptionalArgs *optArgs
169 )
170{
171 // Check input
172 XLAL_CHECK( method_data != NULL, XLAL_EFAULT );
173 XLAL_CHECK( common != NULL, XLAL_EFAULT );
174 XLAL_CHECK( funcs != NULL, XLAL_EFAULT );
175 XLAL_CHECK( multiSFTs != NULL, XLAL_EFAULT );
176 XLAL_CHECK( optArgs != NULL, XLAL_EFAULT );
177
178 // Allocate method data
179 ResampGenericMethodData *resamp = *method_data = XLALCalloc( 1, sizeof( *resamp ) );
180 XLAL_CHECK( resamp != NULL, XLAL_ENOMEM );
181
182 resamp->Dterms = optArgs->Dterms;
183
184 // Set method function pointers
188
189 // Extra band needed for resampling: Hamming-windowed sinc used for interpolation has a transition bandwith of
190 // TB=(4/L)*fSamp, where L=2*Dterms+1 is the window-length, and here fSamp=Band (i.e. the full SFT frequency band)
191 // However, we're only interested in the physical band and we'll be throwing away all bins outside of this.
192 // This implies that we're only affected by *half* the transition band TB/2 on either side, as the other half of TB is outside of the band of interest
193 // (and will actually get aliased, i.e. the region [-fNy - TB/2, -fNy] overlaps with [fNy-TB/2,fNy] and vice-versa: [fNy,fNy+TB/2] overlaps with [-fNy,-fNy+TB/2])
194 // ==> therefore we only need to add an extra TB/2 on each side to be able to safely avoid the transition-band effects
195 REAL8 f0 = multiSFTs->data[0]->data[0].f0;
196 REAL8 dFreq = multiSFTs->data[0]->data[0].deltaF;
197 REAL8 Band = multiSFTs->data[0]->data[0].data->length * dFreq;
198 REAL8 extraBand = 2.0 / ( 2 * optArgs->Dterms + 1 ) * Band;
199 XLAL_CHECK( XLALMultiSFTVectorResizeBand( multiSFTs, f0 - extraBand, Band + 2 * extraBand ) == XLAL_SUCCESS, XLAL_EFUNC );
200 // Convert SFTs into heterodyned complex timeseries [in detector frame]
202
203 XLALDestroyMultiSFTVector( multiSFTs ); // don't need them SFTs any more ...
204
206 REAL8 dt_DET = resamp->multiTimeSeries_DET->data[0]->deltaT;
207 REAL8 fHet = resamp->multiTimeSeries_DET->data[0]->f0;
208 REAL8 Tsft = common->multiTimestamps->data[0]->deltaT;
209
210 // determine resampled timeseries parameters
211 REAL8 TspanFFT = 1.0 / common->dFreq;
212
213 // check that TspanFFT >= TspanX for all detectors X, otherwise increase TspanFFT by an integer factor 'decimateFFT' such that this is true
214 REAL8 TspanXMax = 0;
215 for ( UINT4 X = 0; X < numDetectors; X ++ ) {
216 UINT4 numSamples_DETX = resamp->multiTimeSeries_DET->data[X]->data->length;
217 REAL8 TspanX = numSamples_DETX * dt_DET;
218 TspanXMax = fmax( TspanXMax, TspanX );
219 }
220 UINT4 decimateFFT = ( UINT4 )ceil( TspanXMax / TspanFFT ); // larger than 1 means we need to artificially increase dFreqFFT by 'decimateFFT'
221 if ( decimateFFT > 1 ) {
222 XLALPrintWarning( "WARNING: Frequency spacing larger than 1/Tspan, we'll internally decimate FFT frequency bins by a factor of %" LAL_UINT4_FORMAT "\n", decimateFFT );
223 }
224 TspanFFT *= decimateFFT;
225 resamp->decimateFFT = decimateFFT;
226
227 UINT4 numSamplesFFT0 = ( UINT4 ) ceil( TspanFFT / dt_DET ); // we use ceil() so that we artificially widen the band rather than reduce it
228 UINT4 numSamplesFFT = 0;
229 if ( optArgs->resampFFTPowerOf2 ) {
230 numSamplesFFT = ( UINT4 ) pow( 2, ceil( log2( numSamplesFFT0 ) ) ); // round numSamplesFFT up to next power of 2 for most effiecient FFT
231 } else {
232 numSamplesFFT = ( UINT4 ) 2 * ceil( numSamplesFFT0 / 2 ); // always ensure numSamplesFFT is even
233 }
234
235 REAL8 dt_SRC = TspanFFT / numSamplesFFT; // adjust sampling rate to allow achieving exact requested dFreq=1/TspanFFT !
236
237 resamp->numSamplesFFT = numSamplesFFT;
238 // ----- allocate buffer Memory ----------
239
240 // header for SRC-frame resampled timeseries buffer
241 XLAL_CHECK( ( resamp->multiTimeSeries_SRC_a = XLALCalloc( 1, sizeof( MultiCOMPLEX8TimeSeries ) ) ) != NULL, XLAL_ENOMEM );
244
245 XLAL_CHECK( ( resamp->multiTimeSeries_SRC_b = XLALCalloc( 1, sizeof( MultiCOMPLEX8TimeSeries ) ) ) != NULL, XLAL_ENOMEM );
248
249 LIGOTimeGPS XLAL_INIT_DECL( epoch0 ); // will be set to corresponding SRC-frame epoch when barycentering
250 UINT4 numSamplesMax_SRC = 0;
251 for ( UINT4 X = 0; X < numDetectors; X ++ ) {
252 // ----- check input consistency ----------
253 REAL8 dt_DETX = resamp->multiTimeSeries_DET->data[X]->deltaT;
254 XLAL_CHECK( dt_DET == dt_DETX, XLAL_EINVAL, "Input timeseries must have identical 'deltaT(X=%d)' (%.16g != %.16g)\n", X, dt_DET, dt_DETX );
255
256 REAL8 fHetX = resamp->multiTimeSeries_DET->data[X]->f0;
257 XLAL_CHECK( fabs( fHet - fHetX ) < LAL_REAL8_EPS * fHet, XLAL_EINVAL, "Input timeseries must have identical heterodyning frequency 'f0(X=%d)' (%.16g != %.16g)\n", X, fHet, fHetX );
258
259 REAL8 TsftX = common->multiTimestamps->data[X]->deltaT;
260 XLAL_CHECK( Tsft == TsftX, XLAL_EINVAL, "Input timestamps must have identical stepsize 'Tsft(X=%d)' (%.16g != %.16g)\n", X, Tsft, TsftX );
261
262 // ----- prepare Memory fo SRC-frame timeseries and AM coefficients
263 const char *nameX = resamp->multiTimeSeries_DET->data[X]->name;
264 UINT4 numSamples_DETX = resamp->multiTimeSeries_DET->data[X]->data->length;
265 UINT4 numSamples_SRCX = ( UINT4 )ceil( numSamples_DETX * dt_DET / dt_SRC );
266
267 XLAL_CHECK( ( resamp->multiTimeSeries_SRC_a->data[X] = XLALCreateCOMPLEX8TimeSeries( nameX, &epoch0, fHet, dt_SRC, &lalDimensionlessUnit, numSamples_SRCX ) ) != NULL, XLAL_EFUNC );
268 XLAL_CHECK( ( resamp->multiTimeSeries_SRC_b->data[X] = XLALCreateCOMPLEX8TimeSeries( nameX, &epoch0, fHet, dt_SRC, &lalDimensionlessUnit, numSamples_SRCX ) ) != NULL, XLAL_EFUNC );
269
270 numSamplesMax_SRC = MYMAX( numSamplesMax_SRC, numSamples_SRCX );
271 } // for X < numDetectors
272
273 XLAL_CHECK( numSamplesFFT >= numSamplesMax_SRC, XLAL_EFAILED, "[numSamplesFFT = %d] < [numSamplesMax_SRC = %d]\n", numSamplesFFT, numSamplesMax_SRC );
274
275 // ---- re-use shared workspace, or allocate here ----------
277 if ( ws != NULL ) {
278 if ( numSamplesFFT > ws->numSamplesFFTAlloc ) {
279 fftw_free( ws->FabX_Raw );
280 XLAL_CHECK( ( ws->FabX_Raw = fftw_malloc( numSamplesFFT * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
281 fftw_free( ws->TS_FFT );
282 XLAL_CHECK( ( ws->TS_FFT = fftw_malloc( numSamplesFFT * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
283
284 ws->numSamplesFFTAlloc = numSamplesFFT;
285 }
286
287 // adjust maximal SRC-frame timeseries length, if necessary
288 if ( numSamplesMax_SRC > ws->TStmp1_SRC->length ) {
289 XLAL_CHECK( ( ws->TStmp1_SRC->data = XLALRealloc( ws->TStmp1_SRC->data, numSamplesMax_SRC * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
290 ws->TStmp1_SRC->length = numSamplesMax_SRC;
291 XLAL_CHECK( ( ws->TStmp2_SRC->data = XLALRealloc( ws->TStmp2_SRC->data, numSamplesMax_SRC * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
292 ws->TStmp2_SRC->length = numSamplesMax_SRC;
293 XLAL_CHECK( ( ws->SRCtimes_DET->data = XLALRealloc( ws->SRCtimes_DET->data, numSamplesMax_SRC * sizeof( REAL8 ) ) ) != NULL, XLAL_ENOMEM );
294 ws->SRCtimes_DET->length = numSamplesMax_SRC;
295 }
296
297 } // end: if shared workspace given
298 else {
299 XLAL_CHECK( ( ws = XLALCalloc( 1, sizeof( *ws ) ) ) != NULL, XLAL_ENOMEM );
300 XLAL_CHECK( ( ws->TStmp1_SRC = XLALCreateCOMPLEX8Vector( numSamplesMax_SRC ) ) != NULL, XLAL_EFUNC );
301 XLAL_CHECK( ( ws->TStmp2_SRC = XLALCreateCOMPLEX8Vector( numSamplesMax_SRC ) ) != NULL, XLAL_EFUNC );
302 XLAL_CHECK( ( ws->SRCtimes_DET = XLALCreateREAL8Vector( numSamplesMax_SRC ) ) != NULL, XLAL_EFUNC );
303
304 XLAL_CHECK( ( ws->FabX_Raw = fftw_malloc( numSamplesFFT * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
305 XLAL_CHECK( ( ws->TS_FFT = fftw_malloc( numSamplesFFT * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
306 ws->numSamplesFFTAlloc = numSamplesFFT;
307
308 common->workspace = ws;
309 } // end: if we create our own workspace
310
311 // ----- compute and buffer FFT plan ----------
312 int fft_plan_flags = FFTW_MEASURE;
313 double fft_plan_timeout = FFTW_NO_TIMELIMIT ;
314 char *wisdom_filename;
315 static int tried_wisdom = 0;
316
318 // if FFTWF_WISDOM_FILENAME is set, try to import that wisdom
319 wisdom_filename = getenv( "FFTWF_WISDOM_FILENAME" );
320 if ( wisdom_filename && !tried_wisdom ) {
321 FILE *fp = fopen( wisdom_filename, "r" );
322 if ( !fp ) {
323 XLALPrintWarning( "WARNING: Couldn't open wisdom file '%s'\n", wisdom_filename );
324 } else if ( fftwf_import_wisdom_from_file( fp ) ) {
325 XLALPrintInfo( "INFO: imported wisdom from file '%s'\n", wisdom_filename );
326 fclose( fp );
327 } else {
328 XLALPrintWarning( "WARNING: Couldn't import wisdom from file '%s'\n", wisdom_filename );
329 fclose( fp );
330 }
331 tried_wisdom = -1;
332 }
333 XLALGetFFTPlanHints( & fft_plan_flags, & fft_plan_timeout );
334 fftw_set_timelimit( fft_plan_timeout );
335 XLAL_CHECK( ( resamp->fftplan = fftwf_plan_dft_1d( resamp->numSamplesFFT, ws->TS_FFT, ws->FabX_Raw, FFTW_FORWARD, fft_plan_flags ) ) != NULL, XLAL_EFAILED, "fftwf_plan_dft_1d() failed\n" );
337
338 // turn on timing collection if requested
339 resamp->collectTiming = optArgs->collectTiming;
340
341 // initialize struct for collecting timing data, store invariant 'meta' quantities about this setup
342 if ( resamp->collectTiming ) {
343 XLAL_INIT_MEM( resamp->timingGeneric );
345
346 XLAL_INIT_MEM( resamp->timingResamp );
347 resamp->timingResamp.Resolution = TspanXMax / TspanFFT;
348 resamp->timingResamp.NsampFFT0 = numSamplesFFT0;
349 resamp->timingResamp.NsampFFT = numSamplesFFT;
350 }
351
352 return XLAL_SUCCESS;
353
354} // XLALSetupFstatResampGeneric()
355
356
357static int
359 const FstatCommon *common,
360 void *method_data
361 )
362{
363 // Check input
364 XLAL_CHECK( Fstats != NULL, XLAL_EFAULT );
365 XLAL_CHECK( common != NULL, XLAL_EFAULT );
366 XLAL_CHECK( method_data != NULL, XLAL_EFAULT );
367
368 ResampGenericMethodData *resamp = ( ResampGenericMethodData * ) method_data;
369
370 const FstatQuantities whatToCompute = Fstats->whatWasComputed;
371 XLAL_CHECK( !( whatToCompute & FSTATQ_ATOMS_PER_DET ), XLAL_EINVAL, "Resampling does not currently support atoms per detector" );
372
374
375 // ----- handy shortcuts ----------
376 PulsarDopplerParams thisPoint = Fstats->doppler;
377 const MultiCOMPLEX8TimeSeries *multiTimeSeries_DET = resamp->multiTimeSeries_DET;
378 UINT4 numDetectors = multiTimeSeries_DET->length;
379
380 // collect internal timing info
381 BOOLEAN collectTiming = resamp->collectTiming;
382 Timings_t *Tau = &( resamp->timingResamp.Tau );
383 XLAL_INIT_MEM( ( *Tau ) ); // these need to be initialized to 0 for each call
384
385 REAL8 ticStart = 0, tocEnd = 0;
386 REAL8 tic = 0, toc = 0;
387 if ( collectTiming ) {
388 XLAL_INIT_MEM( ( *Tau ) ); // re-set all timings to 0 at beginning of each Fstat-call
389 ticStart = XLALGetCPUTime();
390 }
391 // Note: all buffering is done within that function
393
394 if ( whatToCompute == FSTATQ_NONE ) {
395 return XLAL_SUCCESS;
396 }
397
398 MultiCOMPLEX8TimeSeries *multiTimeSeries_SRC_a = resamp->multiTimeSeries_SRC_a;
399 MultiCOMPLEX8TimeSeries *multiTimeSeries_SRC_b = resamp->multiTimeSeries_SRC_b;
400
401 // ============================== check workspace is properly allocated and initialized ===========
402
403 // ----- workspace that depends on maximal number of output frequency bins 'numFreqBins' ----------
404 UINT4 numFreqBins = Fstats->numFreqBins;
405
406 if ( collectTiming ) {
407 tic = XLALGetCPUTime();
408 }
409
410 // NOTE: we try to use as much existing memory as possible in FstatResults, so we only
411 // allocate local 'workspace' storage in case there's not already a vector allocated in FstatResults for it
412 // this also avoid having to copy these results in case the user asked for them to be returned
413 if ( whatToCompute & FSTATQ_FAFB ) {
414 XLALFree( ws->Fa_k ); // avoid memory leak if allocated in previous call
415 ws->Fa_k = Fstats->Fa;
416 XLALFree( ws->Fb_k ); // avoid memory leak if allocated in previous call
417 ws->Fb_k = Fstats->Fb;
418 } // end: if returning FaFb we can use that return-struct as 'workspace'
419 else { // otherwise: we (re)allocate it locally
420 if ( numFreqBins > ws->numFreqBinsAlloc ) {
421 XLAL_CHECK( ( ws->Fa_k = XLALRealloc( ws->Fa_k, numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
422 XLAL_CHECK( ( ws->Fb_k = XLALRealloc( ws->Fb_k, numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
423 } // only increase workspace arrays
424 }
425
426 if ( whatToCompute & FSTATQ_FAFB_PER_DET ) {
427 XLALFree( ws->FaX_k ); // avoid memory leak if allocated in previous call
428 ws->FaX_k = NULL; // will be set in loop over detectors X
429 XLALFree( ws->FbX_k ); // avoid memory leak if allocated in previous call
430 ws->FbX_k = NULL; // will be set in loop over detectors X
431 } // end: if returning FaFbPerDet we can use that return-struct as 'workspace'
432 else { // otherwise: we (re)allocate it locally
433 if ( numFreqBins > ws->numFreqBinsAlloc ) {
434 XLAL_CHECK( ( ws->FaX_k = XLALRealloc( ws->FaX_k, numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
435 XLAL_CHECK( ( ws->FbX_k = XLALRealloc( ws->FbX_k, numFreqBins * sizeof( COMPLEX8 ) ) ) != NULL, XLAL_ENOMEM );
436 } // only increase workspace arrays
437 }
438 if ( numFreqBins > ws->numFreqBinsAlloc ) {
439 ws->numFreqBinsAlloc = numFreqBins; // keep track of allocated array length
440 }
441
442 if ( collectTiming ) {
443 toc = XLALGetCPUTime();
444 Tau->Mem = ( toc - tic ); // this one doesn't scale with number of detector!
445 }
446 // ====================================================================================================
447
448 // loop over detectors
449 for ( UINT4 X = 0; X < numDetectors; X++ ) {
450 // if return-struct contains memory for holding FaFbPerDet: use that directly instead of local memory
451 if ( whatToCompute & FSTATQ_FAFB_PER_DET ) {
452 ws->FaX_k = Fstats->FaPerDet[X];
453 ws->FbX_k = Fstats->FbPerDet[X];
454 }
455 const COMPLEX8TimeSeries *TimeSeriesX_SRC_a = multiTimeSeries_SRC_a->data[X];
456 const COMPLEX8TimeSeries *TimeSeriesX_SRC_b = multiTimeSeries_SRC_b->data[X];
457
458 // compute {Fa^X(f_k), Fb^X(f_k)}: results returned via workspace ws
459 XLAL_CHECK( XLALComputeFaFb_ResampGeneric( resamp, ws, thisPoint, common->dFreq, numFreqBins, TimeSeriesX_SRC_a, TimeSeriesX_SRC_b ) == XLAL_SUCCESS, XLAL_EFUNC );
460
461 if ( collectTiming ) {
462 tic = XLALGetCPUTime();
463 }
464 if ( X == 0 ) {
465 // avoid having to memset this array: for the first detector we *copy* results
466 for ( UINT4 k = 0; k < numFreqBins; k++ ) {
467 ws->Fa_k[k] = ws->FaX_k[k];
468 ws->Fb_k[k] = ws->FbX_k[k];
469 }
470 } // end: if X==0
471 else {
472 // for subsequent detectors we *add to* them
473 for ( UINT4 k = 0; k < numFreqBins; k++ ) {
474 ws->Fa_k[k] += ws->FaX_k[k];
475 ws->Fb_k[k] += ws->FbX_k[k];
476 }
477 } // end:if X>0
478
479 if ( collectTiming ) {
480 toc = XLALGetCPUTime();
481 Tau->SumFabX += ( toc - tic );
482 tic = toc;
483 }
484
485 // ----- if requested: compute per-detector Fstat_X_k
486 if ( whatToCompute & FSTATQ_2F_PER_DET ) {
487 const REAL4 AdX = resamp->MmunuX[X].Ad;
488 const REAL4 BdX = resamp->MmunuX[X].Bd;
489 const REAL4 CdX = resamp->MmunuX[X].Cd;
490 const REAL4 EdX = resamp->MmunuX[X].Ed;
491 const REAL4 DdX_inv = 1.0f / resamp->MmunuX[X].Dd;
492 for ( UINT4 k = 0; k < numFreqBins; k ++ ) {
493 Fstats->twoFPerDet[X][k] = compute_fstat_from_fa_fb( ws->FaX_k[k], ws->FbX_k[k], AdX, BdX, CdX, EdX, DdX_inv );
494 } // for k < numFreqBins
495 } // end: if compute F_X
496
497 if ( collectTiming ) {
498 toc = XLALGetCPUTime();
499 Tau->Fab2F += ( toc - tic );
500 }
501
502 } // for X < numDetectors
503
504 if ( collectTiming ) {
505 Tau->SumFabX /= numDetectors;
506 Tau->Fab2F /= numDetectors;
507 tic = XLALGetCPUTime();
508 }
509
510 if ( whatToCompute & FSTATQ_2F ) {
511 const REAL4 Ad = resamp->Mmunu.Ad;
512 const REAL4 Bd = resamp->Mmunu.Bd;
513 const REAL4 Cd = resamp->Mmunu.Cd;
514 const REAL4 Ed = resamp->Mmunu.Ed;
515 const REAL4 Dd_inv = 1.0f / resamp->Mmunu.Dd;
516 for ( UINT4 k = 0; k < numFreqBins; k++ ) {
517 Fstats->twoF[k] = compute_fstat_from_fa_fb( ws->Fa_k[k], ws->Fb_k[k], Ad, Bd, Cd, Ed, Dd_inv );
518 }
519 } // if FSTATQ_2F
520 if ( whatToCompute & FSTATQ_2F_CUDA ) {
521 XLAL_ERROR( XLAL_EINVAL, "Not implemented for FSTATQ_2F_CUDA" );
522 }
523 if ( whatToCompute & FSTATQ_FAFB_CUDA ) {
524 XLAL_ERROR( XLAL_EINVAL, "Not implemented for FSTATQ_FAFB_CUDA" );
525 }
526
527 if ( collectTiming ) {
528 toc = XLALGetCPUTime();
529 Tau->Fab2F += ( toc - tic );
530 }
531
532 // Return F-atoms per detector
533 if ( whatToCompute & FSTATQ_ATOMS_PER_DET ) {
534 XLAL_ERROR( XLAL_EFAILED, "NOT implemented!" );
535 }
536
537 // Return antenna-pattern matrix
538 Fstats->Mmunu = resamp->Mmunu;
539
540 // return per-detector antenna-pattern matrices
541 for ( UINT4 X = 0; X < numDetectors; X ++ ) {
542 Fstats->MmunuX[X] = resamp->MmunuX[X];
543 }
544
545 // ----- workspace memory management:
546 // if we used the return struct directly to store Fa,Fb results,
547 // make sure to wipe those pointers to avoid mistakenly considering them as 'local' memory
548 // and re-allocing it in another call to this function
549 if ( whatToCompute & FSTATQ_FAFB ) {
550 ws->Fa_k = NULL;
551 ws->Fb_k = NULL;
552 }
553 if ( whatToCompute & FSTATQ_FAFB_PER_DET ) {
554 ws->FaX_k = NULL;
555 ws->FbX_k = NULL;
556 }
557
558 if ( collectTiming ) {
559 tocEnd = XLALGetCPUTime();
560
561 FstatTimingGeneric *tiGen = &( resamp->timingGeneric );
562 FstatTimingResamp *tiRS = &( resamp->timingResamp );
563 XLAL_CHECK( numDetectors == tiGen->Ndet, XLAL_EINVAL, "Inconsistent number of detectors between XLALCreateSetup() [%d] and XLALComputeFstat() [%d]\n", tiGen->Ndet, numDetectors );
564
565 Tau->Total = ( tocEnd - ticStart );
566 // rescale all relevant timings to per-detector
567 Tau->Total /= numDetectors;
568 Tau->Bary /= numDetectors;
569 Tau->Spin /= numDetectors;
570 Tau->FFT /= numDetectors;
571 Tau->Norm /= numDetectors;
572 Tau->Copy /= numDetectors;
573 REAL8 Tau_buffer = Tau->Bary;
574 // compute generic F-stat timing model contributions
575 UINT4 NFbin = Fstats->numFreqBins;
576 REAL8 tauF_eff = Tau->Total / NFbin;
577 REAL8 tauF_core = ( Tau->Total - Tau_buffer ) / NFbin;
578
579 // compute resampling timing model coefficients
580 REAL8 tau0_Fbin = ( Tau->Copy + Tau->Norm + Tau->SumFabX + Tau->Fab2F ) / NFbin;
581 REAL8 tau0_spin = Tau->Spin / ( tiRS->Resolution * tiRS->NsampFFT );
582 REAL8 tau0_FFT = Tau->FFT / ( 5.0 * tiRS->NsampFFT * log2( tiRS->NsampFFT ) );
583
584 // update the averaged timing-model quantities
585 tiGen->NCalls ++; // keep track of number of Fstat-calls for timing
586#define updateAvgF(q) tiGen->q = ((tiGen->q *(tiGen->NCalls-1) + q)/(tiGen->NCalls))
587 updateAvgF( tauF_eff );
588 updateAvgF( tauF_core );
589 // we also average NFbin, which can be different between different calls to XLALComputeFstat() (contrary to Ndet)
590 updateAvgF( NFbin );
591
592#define updateAvgRS(q) tiRS->q = ((tiRS->q *(tiGen->NCalls-1) + q)/(tiGen->NCalls))
593 updateAvgRS( tau0_Fbin );
594 updateAvgRS( tau0_spin );
595 updateAvgRS( tau0_FFT );
596
597 // buffer-quantities only updated if buffer was actually recomputed
598 if ( Tau->BufferRecomputed ) {
599 REAL8 tau0_bary = Tau_buffer / ( tiRS->Resolution * tiRS->NsampFFT );
600 REAL8 tauF_buffer = Tau_buffer / NFbin;
601
602 updateAvgF( tauF_buffer );
603 updateAvgRS( tau0_bary );
604 } // if BufferRecomputed
605
606 } // if collectTiming
607
608 return XLAL_SUCCESS;
609
610} // XLALComputeFstatResampGeneric()
611
612
613static int
614XLALComputeFaFb_ResampGeneric( ResampGenericMethodData *resamp, //!< [in,out] buffered resampling data and workspace
615 ResampGenericWorkspace *ws, //!< [in,out] resampling workspace (memory-sharing across segments)
616 const PulsarDopplerParams thisPoint, //!< [in] Doppler point to compute {FaX,FbX} for
617 REAL8 dFreq, //!< [in] output frequency resolution
618 UINT4 numFreqBins, //!< [in] number of output frequency bins
619 const COMPLEX8TimeSeries *restrict TimeSeries_SRC_a, //!< [in] SRC-frame single-IFO timeseries * a(t)
620 const COMPLEX8TimeSeries *restrict TimeSeries_SRC_b //!< [in] SRC-frame single-IFO timeseries * b(t)
621 )
622{
623 XLAL_CHECK( ( resamp != NULL ) && ( ws != NULL ) && ( TimeSeries_SRC_a != NULL ) && ( TimeSeries_SRC_b != NULL ), XLAL_EINVAL );
624 XLAL_CHECK( dFreq > 0, XLAL_EINVAL );
625 XLAL_CHECK( numFreqBins <= ws->numFreqBinsAlloc, XLAL_EINVAL );
626
627 REAL8 FreqOut0 = thisPoint.fkdot[0];
628
629 // compute frequency shift to align heterodyne frequency with output frequency bins
630 REAL8 fHet = TimeSeries_SRC_a->f0;
631 REAL8 dt_SRC = TimeSeries_SRC_a->deltaT;
632
633 REAL8 dFreqFFT = dFreq / resamp->decimateFFT; // internally may be using higher frequency resolution dFreqFFT than requested
634 REAL8 freqShift = remainder( FreqOut0 - fHet, dFreq ); // frequency shift to closest bin
635 REAL8 fMinFFT = fHet + freqShift - dFreqFFT * ( resamp->numSamplesFFT / 2 ); // we'll shift DC into the *middle bin* N/2 [N always even!]
636 XLAL_CHECK( FreqOut0 >= fMinFFT, XLAL_EDOM, "Lowest output frequency outside the available frequency band: [FreqOut0 = %.16g] < [fMinFFT = %.16g]\n", FreqOut0, fMinFFT );
637 UINT4 offset_bins = ( UINT4 ) lround( ( FreqOut0 - fMinFFT ) / dFreqFFT );
638 UINT4 maxOutputBin = offset_bins + ( numFreqBins - 1 ) * resamp->decimateFFT;
639 XLAL_CHECK( maxOutputBin < resamp->numSamplesFFT, XLAL_EDOM, "Highest output frequency bin outside available band: [maxOutputBin = %d] >= [numSamplesFFT = %d]\n", maxOutputBin, resamp->numSamplesFFT );
640
641 FstatTimingResamp *tiRS = &( resamp->timingResamp );
642 BOOLEAN collectTiming = resamp->collectTiming;
643 REAL8 tic = 0, toc = 0;
644
645 XLAL_CHECK( resamp->numSamplesFFT >= TimeSeries_SRC_a->data->length, XLAL_EFAILED, "[numSamplesFFT = %d] < [len(TimeSeries_SRC_a) = %d]\n", resamp->numSamplesFFT, TimeSeries_SRC_a->data->length );
646 XLAL_CHECK( resamp->numSamplesFFT >= TimeSeries_SRC_b->data->length, XLAL_EFAILED, "[numSamplesFFT = %d] < [len(TimeSeries_SRC_b) = %d]\n", resamp->numSamplesFFT, TimeSeries_SRC_b->data->length );
647
648 if ( collectTiming ) {
649 tic = XLALGetCPUTime();
650 }
651 memset( ws->TS_FFT, 0, resamp->numSamplesFFT * sizeof( ws->TS_FFT[0] ) );
652 // ----- compute FaX_k
653 // apply spindown phase-factors, store result in zero-padded timeseries for 'FFT'ing
654 XLAL_CHECK( XLALApplySpindownAndFreqShiftGeneric( ws->TS_FFT, TimeSeries_SRC_a, &thisPoint, freqShift ) == XLAL_SUCCESS, XLAL_EFUNC );
655
656 if ( collectTiming ) {
657 toc = XLALGetCPUTime();
658 tiRS->Tau.Spin += ( toc - tic );
659 tic = toc;
660 }
661
662 // Fourier transform the resampled Fa(t)
663 fftwf_execute_dft( resamp->fftplan, ws->TS_FFT, ws->FabX_Raw );
664
665 if ( collectTiming ) {
666 toc = XLALGetCPUTime();
667 tiRS->Tau.FFT += ( toc - tic );
668 tic = toc;
669 }
670
671 for ( UINT4 k = 0; k < numFreqBins; k++ ) {
672 ws->FaX_k[k] = ws->FabX_Raw [ offset_bins + k * resamp->decimateFFT ];
673 }
674
675 if ( collectTiming ) {
676 toc = XLALGetCPUTime();
677 tiRS->Tau.Copy += ( toc - tic );
678 tic = toc;
679 }
680
681 // ----- compute FbX_k
682 // apply spindown phase-factors, store result in zero-padded timeseries for 'FFT'ing
683 XLAL_CHECK( XLALApplySpindownAndFreqShiftGeneric( ws->TS_FFT, TimeSeries_SRC_b, &thisPoint, freqShift ) == XLAL_SUCCESS, XLAL_EFUNC );
684
685 if ( collectTiming ) {
686 toc = XLALGetCPUTime();
687 tiRS->Tau.Spin += ( toc - tic );
688 tic = toc;
689 }
690
691 // Fourier transform the resampled Fa(t)
692 fftwf_execute_dft( resamp->fftplan, ws->TS_FFT, ws->FabX_Raw );
693
694 if ( collectTiming ) {
695 toc = XLALGetCPUTime();
696 tiRS->Tau.FFT += ( toc - tic );
697 tic = toc;
698 }
699
700 for ( UINT4 k = 0; k < numFreqBins; k++ ) {
701 ws->FbX_k[k] = ws->FabX_Raw [ offset_bins + k * resamp->decimateFFT ];
702 }
703
704 if ( collectTiming ) {
705 toc = XLALGetCPUTime();
706 tiRS->Tau.Copy += ( toc - tic );
707 tic = toc;
708 }
709
710 // ----- normalization factors to be applied to Fa and Fb:
711 const REAL8 dtauX = GPSDIFF( TimeSeries_SRC_a->epoch, thisPoint.refTime );
712 for ( UINT4 k = 0; k < numFreqBins; k++ ) {
713 REAL8 f_k = FreqOut0 + k * dFreq;
714 REAL8 cycles = - f_k * dtauX;
715 REAL4 sinphase, cosphase;
716 XLALSinCos2PiLUT( &sinphase, &cosphase, cycles );
717 COMPLEX8 normX_k = dt_SRC * crectf( cosphase, sinphase );
718 ws->FaX_k[k] *= normX_k;
719 ws->FbX_k[k] *= normX_k;
720 } // for k < numFreqBinsOut
721
722 if ( collectTiming ) {
723 toc = XLALGetCPUTime();
724 tiRS->Tau.Norm += ( toc - tic );
725 tic = toc;
726 }
727
728 return XLAL_SUCCESS;
729
730} // XLALComputeFaFb_ResampGeneric()
731
732static int
733XLALApplySpindownAndFreqShiftGeneric( COMPLEX8 *restrict xOut, ///< [out] the spindown-corrected SRC-frame timeseries
734 const COMPLEX8TimeSeries *restrict xIn, ///< [in] the input SRC-frame timeseries
735 const PulsarDopplerParams *restrict doppler, ///< [in] containing spindown parameters
736 REAL8 freqShift ///< [in] frequency-shift to apply, sign is "new - old"
737 )
738{
739 // input sanity checks
740 XLAL_CHECK( xOut != NULL, XLAL_EINVAL );
741 XLAL_CHECK( xIn != NULL, XLAL_EINVAL );
742 XLAL_CHECK( doppler != NULL, XLAL_EINVAL );
743
744 // determine number of spin downs to include
745 UINT4 s_max = PULSAR_MAX_SPINS - 1;
746 while ( ( s_max > 0 ) && ( doppler->fkdot[s_max] == 0 ) ) {
747 s_max --;
748 }
749
750 REAL8 dt = xIn->deltaT;
751 UINT4 numSamplesIn = xIn->data->length;
752
753 LIGOTimeGPS epoch = xIn->epoch;
754 REAL8 Dtau0 = GPSDIFF( epoch, doppler->refTime );
755
756 // loop over time samples
757 for ( UINT4 j = 0; j < numSamplesIn; j ++ ) {
758 REAL8 taup_j = j * dt;
759 REAL8 Dtau_alpha_j = Dtau0 + taup_j;
760
761 REAL8 cycles = - freqShift * taup_j;
762
763 REAL8 Dtau_pow_kp1 = Dtau_alpha_j;
764 for ( UINT4 k = 1; k <= s_max; k++ ) {
765 Dtau_pow_kp1 *= Dtau_alpha_j;
766 cycles += - LAL_FACT_INV[k + 1] * doppler->fkdot[k] * Dtau_pow_kp1;
767 } // for k = 1 ... s_max
768
769 REAL4 cosphase, sinphase;
770 XLAL_CHECK( XLALSinCos2PiLUT( &sinphase, &cosphase, cycles ) == XLAL_SUCCESS, XLAL_EFUNC );
771 COMPLEX8 em2piphase = crectf( cosphase, sinphase );
772
773 // weight the complex timeseries by the antenna patterns
774 xOut[j] = em2piphase * xIn->data->data[j];
775
776 } // for j < numSamplesIn
777
778 return XLAL_SUCCESS;
779
780} // XLALApplySpindownAndFreqShiftGeneric()
781
782///
783/// Performs barycentric resampling on a multi-detector timeseries, updates resampling buffer with results
784///
785/// NOTE Buffering: this function does check
786/// 1) whether the previously-buffered solution can be completely reused (same sky-position and binary parameters), or
787/// 2) if at least sky-dependent quantities can be re-used (antenna-patterns + timings) in case only binary parameters changed
788///
789static int
791 ResampGenericMethodData *resamp, // [in/out] resampling input and buffer (to store resampling TS)
792 const PulsarDopplerParams *thisPoint, // [in] current skypoint and reftime
793 const FstatCommon *common // [in] various input quantities and parameters used here
794)
795{
796 // check input sanity
797 XLAL_CHECK( thisPoint != NULL, XLAL_EINVAL );
798 XLAL_CHECK( common != NULL, XLAL_EINVAL );
799 XLAL_CHECK( resamp != NULL, XLAL_EINVAL );
800 XLAL_CHECK( resamp->multiTimeSeries_DET != NULL, XLAL_EINVAL );
801 XLAL_CHECK( resamp->multiTimeSeries_SRC_a != NULL, XLAL_EINVAL );
802 XLAL_CHECK( resamp->multiTimeSeries_SRC_b != NULL, XLAL_EINVAL );
803
805
807 XLAL_CHECK( resamp->multiTimeSeries_SRC_a->length == numDetectors, XLAL_EINVAL, "Inconsistent number of detectors tsDET(%d) != tsSRC(%d)\n", numDetectors, resamp->multiTimeSeries_SRC_a->length );
808 XLAL_CHECK( resamp->multiTimeSeries_SRC_b->length == numDetectors, XLAL_EINVAL, "Inconsistent number of detectors tsDET(%d) != tsSRC(%d)\n", numDetectors, resamp->multiTimeSeries_SRC_b->length );
809
810 // ============================== BEGIN: handle buffering =============================
811 BOOLEAN same_skypos = ( resamp->prev_doppler.Alpha == thisPoint->Alpha ) && ( resamp->prev_doppler.Delta == thisPoint->Delta );
812 BOOLEAN same_refTime = ( GPSDIFF( resamp->prev_doppler.refTime, thisPoint->refTime ) == 0 );
813 BOOLEAN same_binary = \
814 ( resamp->prev_doppler.asini == thisPoint->asini ) &&
815 ( resamp->prev_doppler.period == thisPoint->period ) &&
816 ( resamp->prev_doppler.ecc == thisPoint->ecc ) &&
817 ( GPSDIFF( resamp->prev_doppler.tp, thisPoint->tp ) == 0 ) &&
818 ( resamp->prev_doppler.argp == thisPoint->argp );
819
820 Timings_t *Tau = &( resamp->timingResamp.Tau );
821 REAL8 tic = 0, toc = 0;
822 BOOLEAN collectTiming = resamp->collectTiming;
823
824 // if same sky-position *and* same binary, we can simply return as there's nothing to be done here
825 if ( same_skypos && same_refTime && same_binary ) {
826 Tau->BufferRecomputed = 0;
827 return XLAL_SUCCESS;
828 }
829 // else: keep track of 'buffer miss', ie we need to recompute the buffer
830 Tau->BufferRecomputed = 1;
831 resamp->timingGeneric.NBufferMisses ++;
832 if ( collectTiming ) {
833 tic = XLALGetCPUTime();
834 }
835
836 MultiSSBtimes *multiSRCtimes = NULL;
837
838 // only if different sky-position: re-compute antenna-patterns and SSB timings, re-use from buffer otherwise
839 if ( !( same_skypos && same_refTime ) ) {
840 SkyPosition skypos;
842 skypos.longitude = thisPoint->Alpha;
843 skypos.latitude = thisPoint->Delta;
844
846 XLAL_CHECK( ( resamp->multiAMcoef = XLALComputeMultiAMCoeffs( common->multiDetectorStates, common->multiNoiseWeights, skypos ) ) != NULL, XLAL_EFUNC );
847 resamp->Mmunu = resamp->multiAMcoef->Mmunu;
848 for ( UINT4 X = 0; X < numDetectors; X ++ ) {
849 resamp->MmunuX[X].Ad = resamp->multiAMcoef->data[X]->A;
850 resamp->MmunuX[X].Bd = resamp->multiAMcoef->data[X]->B;
851 resamp->MmunuX[X].Cd = resamp->multiAMcoef->data[X]->C;
852 resamp->MmunuX[X].Ed = 0;
853 resamp->MmunuX[X].Dd = resamp->multiAMcoef->data[X]->D;
854 }
855
857 XLAL_CHECK( ( resamp->multiSSBtimes = XLALGetMultiSSBtimes( common->multiDetectorStates, skypos, thisPoint->refTime, common->SSBprec ) ) != NULL, XLAL_EFUNC );
858
859 } // if cannot re-use buffered solution ie if !(same_skypos && same_binary)
860
861 if ( thisPoint->asini > 0 ) { // binary case
863 multiSRCtimes = resamp->multiBinaryTimes;
864 } else { // isolated case
865 multiSRCtimes = resamp->multiSSBtimes;
866 }
867
868 // record barycenter parameters in order to allow re-usal of this result ('buffering')
869 resamp->prev_doppler = ( *thisPoint );
870
871 // shorthands
872 REAL8 fHet = resamp->multiTimeSeries_DET->data[0]->f0;
873 REAL8 Tsft = common->multiTimestamps->data[0]->deltaT;
874 REAL8 dt_SRC = resamp->multiTimeSeries_SRC_a->data[0]->deltaT;
875
876 const REAL4 signumLUT[2] = {1, -1};
877
878 // loop over detectors X
879 for ( UINT4 X = 0; X < numDetectors; X++ ) {
880 // shorthand pointers: input
881 const COMPLEX8TimeSeries *TimeSeries_DETX = resamp->multiTimeSeries_DET->data[X];
882 const LIGOTimeGPSVector *Timestamps_DETX = common->multiTimestamps->data[X];
883 const SSBtimes *SRCtimesX = multiSRCtimes->data[X];
884 const AMCoeffs *AMcoefX = resamp->multiAMcoef->data[X];
885
886 // shorthand pointers: output
887 COMPLEX8TimeSeries *TimeSeries_SRCX_a = resamp->multiTimeSeries_SRC_a->data[X];
888 COMPLEX8TimeSeries *TimeSeries_SRCX_b = resamp->multiTimeSeries_SRC_b->data[X];
889 REAL8Vector *ti_DET = ws->SRCtimes_DET;
890
891 // useful shorthands
892 REAL8 refTime8 = GPSGETREAL8( &SRCtimesX->refTime );
893 UINT4 numSFTsX = Timestamps_DETX->length;
894 UINT4 numSamples_DETX = TimeSeries_DETX->data->length;
895 UINT4 numSamples_SRCX = TimeSeries_SRCX_a->data->length;
896
897 // sanity checks on input data
898 XLAL_CHECK( numSamples_SRCX == TimeSeries_SRCX_b->data->length, XLAL_EINVAL );
899 XLAL_CHECK( dt_SRC == TimeSeries_SRCX_a->deltaT, XLAL_EINVAL );
900 XLAL_CHECK( dt_SRC == TimeSeries_SRCX_b->deltaT, XLAL_EINVAL );
901 XLAL_CHECK( numSamples_DETX > 0, XLAL_EINVAL, "Input timeseries for detector X=%d has zero samples. Can't handle that!\n", X );
902 XLAL_CHECK( ( SRCtimesX->DeltaT->length == numSFTsX ) && ( SRCtimesX->Tdot->length == numSFTsX ), XLAL_EINVAL );
903 REAL8 fHetX = resamp->multiTimeSeries_DET->data[X]->f0;
904 XLAL_CHECK( fabs( fHet - fHetX ) < LAL_REAL8_EPS * fHet, XLAL_EINVAL, "Input timeseries must have identical heterodyning frequency 'f0(X=%d)' (%.16g != %.16g)\n", X, fHet, fHetX );
905 REAL8 TsftX = common->multiTimestamps->data[X]->deltaT;
906 XLAL_CHECK( Tsft == TsftX, XLAL_EINVAL, "Input timestamps must have identical stepsize 'Tsft(X=%d)' (%.16g != %.16g)\n", X, Tsft, TsftX );
907
908 TimeSeries_SRCX_a->f0 = fHet;
909 TimeSeries_SRCX_b->f0 = fHet;
910 // set SRC-frame time-series start-time
911 REAL8 tStart_SRC_0 = refTime8 + SRCtimesX->DeltaT->data[0] - ( 0.5 * Tsft ) * SRCtimesX->Tdot->data[0];
913 GPSSETREAL8( epoch, tStart_SRC_0 );
914 TimeSeries_SRCX_a->epoch = epoch;
915 TimeSeries_SRCX_b->epoch = epoch;
916
917 // make sure all output samples are initialized to zero first, in case of gaps
918 memset( TimeSeries_SRCX_a->data->data, 0, TimeSeries_SRCX_a->data->length * sizeof( TimeSeries_SRCX_a->data->data[0] ) );
919 memset( TimeSeries_SRCX_b->data->data, 0, TimeSeries_SRCX_b->data->length * sizeof( TimeSeries_SRCX_b->data->data[0] ) );
920 // make sure detector-frame timesteps to interpolate to are initialized to 0, in case of gaps
921 memset( ws->SRCtimes_DET->data, 0, ws->SRCtimes_DET->length * sizeof( ws->SRCtimes_DET->data[0] ) );
922
923 memset( ws->TStmp1_SRC->data, 0, ws->TStmp1_SRC->length * sizeof( ws->TStmp1_SRC->data[0] ) );
924 memset( ws->TStmp2_SRC->data, 0, ws->TStmp2_SRC->length * sizeof( ws->TStmp2_SRC->data[0] ) );
925
926 REAL8 tStart_DET_0 = GPSGETREAL8( &( Timestamps_DETX->data[0] ) ); // START time of the SFT at the detector
927
928 // loop over SFT timestamps and compute the detector frame time samples corresponding to uniformly sampled SRC time samples
929 for ( UINT4 alpha = 0; alpha < numSFTsX; alpha ++ ) {
930 // define some useful shorthands
931 REAL8 Tdot_al = SRCtimesX->Tdot->data [ alpha ]; // the instantaneous time derivitive dt_SRC/dt_DET at the MID-POINT of the SFT
932 REAL8 tMid_SRC_al = refTime8 + SRCtimesX->DeltaT->data[alpha]; // MID-POINT time of the SFT at the SRC
933 REAL8 tStart_SRC_al = tMid_SRC_al - 0.5 * Tsft * Tdot_al; // approximate START time of the SFT at the SRC
934 REAL8 tEnd_SRC_al = tMid_SRC_al + 0.5 * Tsft * Tdot_al; // approximate END time of the SFT at the SRC
935
936 REAL8 tStart_DET_al = GPSGETREAL8( &( Timestamps_DETX->data[alpha] ) ); // START time of the SFT at the detector
937 REAL8 tMid_DET_al = tStart_DET_al + 0.5 * Tsft; // MID-POINT time of the SFT at the detector
938
939 // indices of first and last SRC-frame sample corresponding to this SFT
940 UINT4 iStart_SRC_al = lround( ( tStart_SRC_al - tStart_SRC_0 ) / dt_SRC ); // the index of the resampled timeseries corresponding to the start of the SFT
941 UINT4 iEnd_SRC_al = lround( ( tEnd_SRC_al - tStart_SRC_0 ) / dt_SRC ); // the index of the resampled timeseries corresponding to the end of the SFT
942
943 // truncate to actual SRC-frame timeseries
944 iStart_SRC_al = MYMIN( iStart_SRC_al, numSamples_SRCX - 1 );
945 iEnd_SRC_al = MYMIN( iEnd_SRC_al, numSamples_SRCX - 1 );
946 UINT4 numSamplesSFT_SRC_al = iEnd_SRC_al - iStart_SRC_al + 1; // the number of samples in the SRC-frame for this SFT
947
948 REAL4 a_al = AMcoefX->a->data[alpha];
949 REAL4 b_al = AMcoefX->b->data[alpha];
950 for ( UINT4 j = 0; j < numSamplesSFT_SRC_al; j++ ) {
951 UINT4 iSRC_al_j = iStart_SRC_al + j;
952
953 // for each time sample in the SRC frame, we estimate the corresponding detector time,
954 // using a linear approximation expanding around the midpoint of each SFT
955 REAL8 t_SRC = tStart_SRC_0 + iSRC_al_j * dt_SRC;
956 ti_DET->data [ iSRC_al_j ] = tMid_DET_al + ( t_SRC - tMid_SRC_al ) / Tdot_al;
957
958 // pre-compute correction factors due to non-zero heterodyne frequency of input
959 REAL8 tDiff = iSRC_al_j * dt_SRC + ( tStart_DET_0 - ti_DET->data [ iSRC_al_j ] ); // tSRC_al_j - tDET(tSRC_al_j)
960 REAL8 cycles = fmod( fHet * tDiff, 1.0 ); // the accumulated heterodyne cycles
961
962 // use a look-up-table for speed to compute real and imaginary phase
963 REAL4 cosphase, sinphase; // the real and imaginary parts of the phase correction
964 XLAL_CHECK( XLALSinCos2PiLUT( &sinphase, &cosphase, -cycles ) == XLAL_SUCCESS, XLAL_EFUNC );
965 COMPLEX8 ei2piphase = crectf( cosphase, sinphase );
966
967 // apply AM coefficients a(t), b(t) to SRC frame timeseries [alternate sign to get final FFT return DC in the middle]
968 REAL4 signum = signumLUT [( iSRC_al_j % 2 ) ]; // alternating sign, avoid branching
969 ei2piphase *= signum;
970 ws->TStmp1_SRC->data [ iSRC_al_j ] = ei2piphase * a_al;
971 ws->TStmp2_SRC->data [ iSRC_al_j ] = ei2piphase * b_al;
972 } // for j < numSamples_SRC_al
973
974 } // for alpha < numSFTsX
975
976 XLAL_CHECK( ti_DET->length >= TimeSeries_SRCX_a->data->length, XLAL_EINVAL );
977 UINT4 bak_length = ti_DET->length;
978 ti_DET->length = TimeSeries_SRCX_a->data->length;
979 XLAL_CHECK( XLALSincInterpolateCOMPLEX8TimeSeries( TimeSeries_SRCX_a->data, ti_DET, TimeSeries_DETX, resamp->Dterms ) == XLAL_SUCCESS, XLAL_EFUNC );
980 ti_DET->length = bak_length;
981
982 // apply heterodyne correction and AM-functions a(t) and b(t) to interpolated timeseries
983 for ( UINT4 j = 0; j < numSamples_SRCX; j ++ ) {
984 TimeSeries_SRCX_b->data->data[j] = TimeSeries_SRCX_a->data->data[j] * ws->TStmp2_SRC->data[j];
985 TimeSeries_SRCX_a->data->data[j] *= ws->TStmp1_SRC->data[j];
986 } // for j < numSamples_SRCX
987
988 } // for X < numDetectors
989
990 if ( collectTiming ) {
991 toc = XLALGetCPUTime();
992 Tau->Bary = ( toc - tic );
993 }
994
995 return XLAL_SUCCESS;
996
997} // XLALBarycentricResampleMultiCOMPLEX8TimeSeriesGeneric()
998
999static void
1000XLALGetFFTPlanHints( int *planMode,
1001 double *planGenTimeoutSeconds
1002 )
1003{
1004 char *planMode_env = getenv( "LAL_FSTAT_FFT_PLAN_MODE" );
1005 char *planGenTimeout_env = getenv( "LAL_FSTAT_FFT_PLAN_TIMEOUT" );;
1006 int fft_plan_flags = FFTW_MEASURE;
1007 double fft_plan_timeout = FFTW_NO_TIMELIMIT ;
1008
1009 if ( planGenTimeout_env ) {
1010 char *end;
1011 fft_plan_timeout = strtod( planGenTimeout_env, & end );
1012 if ( end[0] != '\0' ) {
1013 fft_plan_timeout = FFTW_NO_TIMELIMIT;
1014 }
1015 }
1016
1017 if ( planMode_env ) {
1018 if ( strcmp( planMode_env, "ESTIMATE" ) == 0 ) {
1019 fft_plan_flags = FFTW_ESTIMATE;
1020 }
1021
1022 if ( strcmp( planMode_env, "MEASURE" ) == 0 ) {
1023 fft_plan_flags = FFTW_MEASURE;
1024 }
1025
1026 if ( strcmp( planMode_env, "PATIENT" ) == 0 ) {
1027 fft_plan_flags = FFTW_PATIENT;
1028 }
1029 }
1030 *planMode = fft_plan_flags;
1031 *planGenTimeoutSeconds = fft_plan_timeout;
1032} // XLALGetFFTPlanHints
1033
1034int
1035XLALExtractResampledTimeseries_ResampGeneric( MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_a, MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_b, void *method_data )
1036{
1037 XLAL_CHECK( method_data != NULL, XLAL_EINVAL );
1038 XLAL_CHECK( ( multiTimeSeries_SRC_a != NULL ) && ( multiTimeSeries_SRC_b != NULL ), XLAL_EINVAL );
1039 XLAL_CHECK( method_data != NULL, XLAL_EINVAL );
1040
1041 ResampGenericMethodData *resamp = ( ResampGenericMethodData * ) method_data;
1042 *multiTimeSeries_SRC_a = resamp->multiTimeSeries_SRC_a;
1043 *multiTimeSeries_SRC_b = resamp->multiTimeSeries_SRC_b;
1044
1045 return XLAL_SUCCESS;
1046
1047} // XLALExtractResampledTimeseries_intern()
1048
1049int
1050XLALGetFstatTiming_ResampGeneric( const void *method_data, FstatTimingGeneric *timingGeneric, FstatTimingModel *timingModel )
1051{
1052 XLAL_CHECK( method_data != NULL, XLAL_EINVAL );
1053 XLAL_CHECK( timingGeneric != NULL, XLAL_EINVAL );
1054 XLAL_CHECK( timingModel != NULL, XLAL_EINVAL );
1055
1056 const ResampGenericMethodData *resamp = ( const ResampGenericMethodData * ) method_data;
1057 XLAL_CHECK( resamp != NULL, XLAL_EINVAL );
1058
1059 ( *timingGeneric ) = resamp->timingGeneric; // struct-copy generic timing measurements
1060
1062
1063 return XLAL_SUCCESS;
1064} // XLALGetFstatTiming_ResampGeneric()
1065
1066/// @}
#define updateAvgF(q)
#define updateAvgRS(q)
#define GPSGETREAL8(x)
#define GPSSETREAL8(gps, r8)
#define GPSDIFF(x, y)
static int XLALGetFstatTiming_Resamp_intern(const FstatTimingResamp *tiRS, FstatTimingModel *timingModel)
static REAL4 compute_fstat_from_fa_fb(COMPLEX8 Fa, COMPLEX8 Fb, REAL4 A, REAL4 B, REAL4 C, REAL4 E, REAL4 Dinv)
#define LAL_FFTW_WISDOM_UNLOCK
#define LAL_FFTW_WISDOM_LOCK
int j
int k
static int XLALComputeFstatResampGeneric(FstatResults *Fstats, const FstatCommon *common, void *method_data)
static void XLALDestroyResampGenericMethodData(void *method_data)
static int XLALApplySpindownAndFreqShiftGeneric(COMPLEX8 *xOut, const COMPLEX8TimeSeries *xIn, const PulsarDopplerParams *doppler, REAL8 freqShift)
static int XLALComputeFaFb_ResampGeneric(ResampGenericMethodData *resamp, ResampGenericWorkspace *ws, const PulsarDopplerParams thisPoint, REAL8 dFreq, UINT4 numFreqBins, const COMPLEX8TimeSeries *TimeSeries_SRC_a, const COMPLEX8TimeSeries *TimeSeries_SRC_b)
int XLALExtractResampledTimeseries_ResampGeneric(MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_a, MultiCOMPLEX8TimeSeries **multiTimeSeries_SRC_b, void *method_data)
int XLALGetFstatTiming_ResampGeneric(const void *method_data, FstatTimingGeneric *timingGeneric, FstatTimingModel *timingModel)
static int XLALBarycentricResampleMultiCOMPLEX8TimeSeriesGeneric(ResampGenericMethodData *resamp, const PulsarDopplerParams *thisPoint, const FstatCommon *common)
Performs barycentric resampling on a multi-detector timeseries, updates resampling buffer with result...
int XLALSetupFstatResampGeneric(void **method_data, FstatCommon *common, FstatMethodFuncs *funcs, MultiSFTVector *multiSFTs, const FstatOptionalArgs *optArgs)
static void XLALGetFFTPlanHints(int *planMode, double *planGenTimeoutSeconds)
static void XLALDestroyResampGenericWorkspace(void *workspace)
FstatQuantities
Bit-field of -statistic quantities which can be computed by XLALComputeFstat().
Definition: ComputeFstat.h:94
@ FSTATQ_2F
Compute multi-detector .
Definition: ComputeFstat.h:96
@ FSTATQ_FAFB_PER_DET
Compute and for each detector.
Definition: ComputeFstat.h:99
@ FSTATQ_FAFB
Compute multi-detector and .
Definition: ComputeFstat.h:97
@ FSTATQ_NONE
Do not compute -statistic, still compute buffered quantities.
Definition: ComputeFstat.h:95
@ FSTATQ_2F_CUDA
Compute multi-detector , store results on CUDA GPU (CUDA implementation of Resamp only).
Definition: ComputeFstat.h:101
@ FSTATQ_ATOMS_PER_DET
Compute per-SFT -statistic atoms for each detector (Demod only).
Definition: ComputeFstat.h:100
@ FSTATQ_2F_PER_DET
Compute for each detector.
Definition: ComputeFstat.h:98
@ FSTATQ_FAFB_CUDA
Compute multi-detector and , store results on CUDA GPU (CUDA implementation of Resamp only).
Definition: ComputeFstat.h:102
static const REAL8 LAL_FACT_INV[]
void XLALDestroyMultiAMCoeffs(MultiAMCoeffs *multiAMcoef)
Destroy a MultiAMCoeffs structure.
Definition: LALComputeAM.c:469
MultiAMCoeffs * XLALComputeMultiAMCoeffs(const MultiDetectorStateSeries *multiDetStates, const MultiNoiseWeights *multiWeights, SkyPosition skypos)
Multi-IFO version of XLALComputeAMCoeffs().
Definition: LALComputeAM.c:379
#define LAL_REAL8_EPS
unsigned char BOOLEAN
#define XLAL_INIT_MEM(x)
double REAL8
#define XLAL_INIT_DECL(var,...)
#define crectf(re, im)
uint32_t UINT4
float complex COMPLEX8
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
MultiCOMPLEX8TimeSeries * XLALMultiSFTVectorToCOMPLEX8TimeSeries(const MultiSFTVector *multisfts)
Turn the given multiSFTvector into multiple long COMPLEX8TimeSeries, properly dealing with gaps.
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 XLALDestroyMultiCOMPLEX8TimeSeries(MultiCOMPLEX8TimeSeries *multiTimes)
Destroy a MultiCOMPLEX8TimeSeries structure.
REAL8 XLALGetCPUTime(void)
#define PULSAR_MAX_DETECTORS
maximal number of detectors we can handle (for static arrays of detector quantities)
#define PULSAR_MAX_SPINS
maximal number of spin-parameters (Freq + spindowns) we can handle
void XLALDestroyMultiSFTVector(MultiSFTVector *multvect)
Destroy a multi SFT-vector.
Definition: SFTtypes.c:424
int XLALMultiSFTVectorResizeBand(MultiSFTVector *multiSFTs, REAL8 f0, REAL8 Band)
Resize the frequency-band of a given multi-SFT vector to [f0, f0+Band].
Definition: SFTtypes.c:946
MultiSSBtimes * XLALGetMultiSSBtimes(const MultiDetectorStateSeries *multiDetStates, SkyPosition skypos, LIGOTimeGPS refTime, SSBprecision precision)
Multi-IFO version of XLALGetSSBtimes().
Definition: SSBtimes.c:657
void XLALDestroyMultiSSBtimes(MultiSSBtimes *multiSSB)
Destroy a MultiSSBtimes structure.
Definition: SSBtimes.c:845
int XLALAddMultiBinaryTimes(MultiSSBtimes **multiSSBOut, const MultiSSBtimes *multiSSBIn, const PulsarDopplerParams *Doppler)
Multi-IFO version of XLALAddBinaryTimes().
Definition: SSBtimes.c:413
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_EQUATORIAL
COMPLEX8TimeSeries * XLALCreateCOMPLEX8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalDimensionlessUnit
COMPLEX8Vector * XLALCreateCOMPLEX8Vector(UINT4 length)
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
void XLALDestroyCOMPLEX8Vector(COMPLEX8Vector *vector)
int int int XLALPrintInfo(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
int int XLALPrintWarning(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
XLAL_EINVAL
XLAL_EFAILED
end
#define MYMIN(x, y)
#define MYMAX(x, y)
double alpha
size_t numDetectors
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
Struct holding the "antenna-pattern" matrix , in terms of the multi-detector scalar product.
Definition: LALComputeAM.h:127
REAL4 Dd
determinant factor , such that
Definition: LALComputeAM.h:132
CHAR name[LALNameLength]
LIGOTimeGPS epoch
COMPLEX8Sequence * data
COMPLEX8 * data
MultiDetectorStateSeries * multiDetectorStates
SSBprecision SSBprec
MultiLIGOTimeGPSVector * multiTimestamps
MultiNoiseWeights * multiNoiseWeights
int(* compute_func)(FstatResults *, const FstatCommon *, void *)
void(* workspace_destroy_func)(void *)
void(* method_data_destroy_func)(void *)
Struct of optional 'advanced level' and (potentially method-specific) arguments to be passed to the ...
Definition: ComputeFstat.h:137
BOOLEAN resampFFTPowerOf2
Resamp: round up FFT lengths to next power of 2; see FstatMethodType.
Definition: ComputeFstat.h:148
BOOLEAN collectTiming
a flag to turn on/off the collection of F-stat-method-specific timing-data
Definition: ComputeFstat.h:147
UINT4 Dterms
Number of Dirichlet kernel terms, used by some Demod methods; see FstatMethodType.
Definition: ComputeFstat.h:140
XLALComputeFstat() computed results structure.
Definition: ComputeFstat.h:202
AntennaPatternMatrix MmunuX[PULSAR_MAX_DETECTORS]
Per detector antenna pattern matrix , used in computing .
Definition: ComputeFstat.h:231
COMPLEX8 * Fb
Definition: ComputeFstat.h:260
AntennaPatternMatrix Mmunu
Antenna pattern matrix , used in computing .
Definition: ComputeFstat.h:228
REAL4 * twoFPerDet[PULSAR_MAX_DETECTORS]
If whatWasComputed & FSTATQ_2F_PER_DET is true, the values computed at numFreqBins frequencies space...
Definition: ComputeFstat.h:277
FstatQuantities whatWasComputed
Bit-field of which -statistic quantities were computed.
Definition: ComputeFstat.h:234
COMPLEX8 * FaPerDet[PULSAR_MAX_DETECTORS]
If whatWasComputed & FSTATQ_PARTS_PER_DET is true, the and values computed at numFreqBins frequenci...
Definition: ComputeFstat.h:287
UINT4 numFreqBins
Number of frequencies at which the were computed.
Definition: ComputeFstat.h:217
REAL4 * twoF
If whatWasComputed & FSTATQ_2F is true, the multi-detector values computed at numFreqBins frequencie...
Definition: ComputeFstat.h:242
COMPLEX8 * Fa
If whatWasComputed & FSTATQ_PARTS is true, the multi-detector and computed at numFreqBins frequenci...
Definition: ComputeFstat.h:259
COMPLEX8 * FbPerDet[PULSAR_MAX_DETECTORS]
Definition: ComputeFstat.h:288
PulsarDopplerParams doppler
Doppler parameters, including the starting frequency, at which the were computed.
Definition: ComputeFstat.h:206
Generic F-stat timing coefficients (times in seconds) [see https://dcc.ligo.org/LIGO-T1600531-v4 for ...
Definition: ComputeFstat.h:316
Struct to carry the -statistic method-specific timing model in terms of a list of variable names and...
Definition: ComputeFstat.h:335
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
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
UINT4 length
number of IFOs
Definition: LFTandTSutils.h:56
LIGOTimeGPSVector ** data
timestamps vector for each ifo
Definition: SFTfileIO.h:203
A collection of SFT vectors – one for each IFO in a multi-IFO search.
Definition: SFTfileIO.h:179
Multi-IFO container for SSB timings.
Definition: SSBtimes.h:67
SSBtimes ** data
array of SSBtimes (pointers)
Definition: SSBtimes.h:72
Type containing the 'Doppler-parameters' affecting the time-evolution of the phase.
REAL8 period
Binary: orbital period (sec)
LIGOTimeGPS tp
Binary: time of observed periapsis passage (in SSB)
PulsarSpins fkdot
Intrinsic spins: [Freq, f1dot, f2dot, ... ] where fkdot = d^kFreq/dt^k.
REAL8 Delta
Sky position: DEC (latitude) in equatorial coords and radians.
LIGOTimeGPS refTime
Reference time of pulsar parameters (in SSB!)
REAL8 Alpha
Sky position: RA (longitude) in equatorial coords and radians.
REAL8 ecc
Binary: orbital eccentricity.
REAL8 asini
Binary: projected, normalized orbital semi-major axis (s).
REAL8 argp
Binary: argument of periapsis (radians)
REAL4 * data
REAL8 * data
MultiCOMPLEX8TimeSeries * multiTimeSeries_DET
MultiCOMPLEX8TimeSeries * multiTimeSeries_SRC_a
AntennaPatternMatrix MmunuX[PULSAR_MAX_DETECTORS]
MultiCOMPLEX8TimeSeries * multiTimeSeries_SRC_b
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
enum @1 epoch