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
templates.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2010 -- 2014 Evan Goetz
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20#include <lal/Window.h>
21#include <lal/VectorOps.h>
22#include <lal/SinCosLUT.h>
23
24#include "templates.h"
25#include "vectormath.h"
26#include "statistics.h"
27#include "TwoSpectSpecFunc.h"
28
29
30/**
31 * Allocate a new TwoSpectTemplate
32 * \param [in] length Length of the template
33 * \return Pointer to TwoSpectTemplate
34 */
36{
37
38 TwoSpectTemplate *template = NULL;
39 XLAL_CHECK_NULL( ( template = XLALMalloc( sizeof( *template ) ) ) != NULL, XLAL_ENOMEM );
40
41 XLAL_CHECK_NULL( ( template->templatedata = XLALCreateREAL4VectorAligned( length, 32 ) ) != NULL, XLAL_EFUNC );
42 XLAL_CHECK_NULL( ( template->pixellocations = XLALCreateINT4Vector( length ) ) != NULL, XLAL_EFUNC );
43
44 memset( template->templatedata->data, 0, sizeof( REAL4 )*length );
45 memset( template->pixellocations->data, 0, sizeof( INT4 )*length );
46
47 template->f0 = 0.0;
48 template->period = 0.0;
49 template->moddepth = 0.0;
50
51 return template;
52
53} /* createTwoSpectTemplate() */
54
55
56/**
57 * Reset the values in a TwoSpectTemplate
58 * \param [in] template Pointer to a TwoSpectTemplate
59 */
61{
62
63 INT4 length = ( INT4 )template->templatedata->length;
64 memset( template->templatedata->data, 0, sizeof( REAL4 )*length );
65 memset( template->pixellocations->data, 0, sizeof( INT4 )*length );
66
67 template->f0 = 0.0;
68 template->period = 0.0;
69 template->moddepth = 0.0;
70
71} /* resetTwoSpectTemplate() */
72
73
74/**
75 * Free a TwoSpectTemplate
76 * \param [in] template Pointer to a TwoSpectTemplate
77 */
79{
80 if ( template ) {
81 XLALDestroyREAL4VectorAligned( template->templatedata );
82 XLALDestroyINT4Vector( template->pixellocations );
83 XLALFree( ( TwoSpectTemplate * )template );
84 }
85} /* destroyTwoSpectTemplate() */
86
87
88/**
89 * Create a TwoSpectTemplateVector
90 * \param [in] length The number of templates in the vector
91 * \param [in] templateLength The maximum number of pixels in a template
92 * \return Pointer to a TwoSpectTemplateVector
93 */
94TwoSpectTemplateVector *createTwoSpectTemplateVector( const UINT4 length, const UINT4 templateLength )
95{
97 XLAL_CHECK_NULL( ( vector = XLALMalloc( sizeof( *vector ) ) ) != NULL, XLAL_ENOMEM );
98
99 vector->length = length;
100 vector->data = NULL;
101 if ( vector->length > 0 ) {
102 XLAL_CHECK_NULL( ( vector->data = XLALMalloc( vector->length * sizeof( *vector->data ) ) ) != NULL, XLAL_ENOMEM );
103 for ( UINT4 ii = 0; ii < vector->length; ii++ ) {
104 XLAL_CHECK_NULL( ( vector->data[ii] = createTwoSpectTemplate( templateLength ) ) != NULL, XLAL_EFUNC );
105 }
106 }
107
108 vector->Tsft = 0.0;
109 vector->SFToverlap = 0.0;
110 vector->Tobs = 0.0;
111
112 return vector;
113}
114
115
116/**
117 * Free a TwoSpectTemplateVector
118 * \param [in] vector Pointer to the TwoSpectTemplateVector
119 */
121{
122 if ( vector == NULL ) {
123 return;
124 }
125 if ( ( !vector->length || !vector->data ) && ( vector->length || vector->data ) ) {
127 }
128 if ( vector->data ) {
129 for ( UINT4 ii = 0; ii < vector->length; ii++ ) {
130 destroyTwoSpectTemplate( vector->data[ii] );
131 }
132 XLALFree( vector->data );
133 }
134 vector->data = NULL;
135 XLALFree( vector );
136 return;
137}
138
139
140/**
141 * Generate a TwoSpectTemplateVector containing the template data
142 * \param [in] Pmin Minimum orbital period (s)
143 * \param [in] Pmax Maximum orbital period (s)
144 * \param [in] dfmin Minimum modulation depth (Hz)
145 * \param [in] dfmax Maximum modulation depth (Hz)
146 * \param [in] Tsft Timespan of SFTs (s)
147 * \param [in] SFToverlap Overlap of SFTs (s)
148 * \param [in] Tobs Observation time (s)
149 * \param [in] maxvectorlength Limit the number of templates generated to be the maximum value specified here
150 * \param [in] minTemplateLength The minimum number of pixels in a template
151 * \param [in] maxTemplateLength The maximum number of pixels in a template
152 * \param [in] vectormathflag Flag specifying what type of vector math to use: 0 = none, 1 = SSE, 2 = AVX (for SSE and AVX, must compile using correct flags and instructions allowed on the CPU)
153 * \param [in] exactflag Flag specifying to use exact templates: 1 = enabled, 0 = disabled
154 * \return Pointer to a TwoSpectTemplateVector
155 */
156TwoSpectTemplateVector *generateTwoSpectTemplateVector( const REAL8 Pmin, const REAL8 Pmax, const REAL8 dfmin, const REAL8 dfmax, const REAL8 Tsft, const REAL8 SFToverlap, const REAL8 Tobs, const UINT4 maxvectorlength, const UINT4 minTemplateLength, const UINT4 maxTemplateLength, const UINT4 vectormathflag, const BOOLEAN exactflag )
157{
159 XLAL_CHECK_NULL( ( vector = createTwoSpectTemplateVector( maxvectorlength, maxTemplateLength ) ) != NULL, XLAL_EFUNC );
160
161 vector->Tsft = Tsft;
162 vector->SFToverlap = SFToverlap;
163 vector->Tobs = Tobs;
164
165 UINT4 numdfvals = ( UINT4 )( floor( 2.0 * Tsft * ( dfmax - dfmin ) ) ) + 1, numtemplatesgenerated = 0;
166 REAL8 alpha0 = 45.0 * ( Tsft / 1800.0 ) + 30.0;
167
168 UINT4 numffts = ( UINT4 )floor( Tobs / ( Tsft - SFToverlap ) - 1 );
169 REAL4FFTPlan *plan = NULL;
170 XLAL_CHECK_NULL( ( plan = XLALCreateForwardREAL4FFTPlan( numffts, 1 ) ) != NULL, XLAL_EFUNC );
171
172 REAL8Vector *dfvals = NULL;
173 XLAL_CHECK_NULL( ( dfvals = XLALCreateREAL8Vector( numdfvals ) ) != NULL, XLAL_EFUNC );
174 for ( UINT4 ii = 0; ii < numdfvals; ii++ ) {
175 dfvals->data[ii] = dfmin + 0.5 * ii / Tsft;
176 }
177 for ( UINT4 ii = 0; ii < numdfvals; ii++ ) {
178 REAL8 P = Pmax;
179 while ( P >= Pmin && P >= 2.0 * dfvals->data[ii]*Tsft * Tsft && numtemplatesgenerated < vector->length ) {
180 if ( !exactflag ) {
181 XLAL_CHECK_NULL( makeTemplateGaussians2( vector->data[numtemplatesgenerated], 0.0, P, dfvals->data[ii], Tsft, SFToverlap, Tobs, minTemplateLength, vectormathflag ) == XLAL_SUCCESS, XLAL_EFUNC );
182 } else {
183 XLAL_CHECK_NULL( makeTemplate2( vector->data[numtemplatesgenerated], 0.0, P, dfvals->data[ii], Tsft, SFToverlap, Tobs, minTemplateLength, vectormathflag, plan ) == XLAL_SUCCESS, XLAL_EFUNC );
184 }
185 numtemplatesgenerated++;
186 if ( numtemplatesgenerated == vector->length ) {
187 break;
188 }
189
190 if ( !exactflag ) {
191 XLAL_CHECK_NULL( makeTemplateGaussians2( vector->data[numtemplatesgenerated], 0.5, P, dfvals->data[ii], Tsft, SFToverlap, Tobs, minTemplateLength, vectormathflag ) == XLAL_SUCCESS, XLAL_EFUNC );
192 } else {
193 XLAL_CHECK_NULL( makeTemplate2( vector->data[numtemplatesgenerated], 0.5, P, dfvals->data[ii], Tsft, SFToverlap, Tobs, minTemplateLength, vectormathflag, plan ) == XLAL_SUCCESS, XLAL_EFUNC );
194 }
195 numtemplatesgenerated++;
196 if ( numtemplatesgenerated == vector->length ) {
197 break;
198 }
199
200 REAL8 dP = P * P / ( alpha0 * Tobs * sqrt( dfvals->data[ii] ) ) * ( 1 + P / ( alpha0 * Tobs ) );
201 P -= dP;
202 }
203 if ( numtemplatesgenerated == vector->length ) {
204 break;
205 }
206 }
207
208 XLALDestroyREAL8Vector( dfvals );
210
211 fprintf( stderr, "Templates generated = %d\n", numtemplatesgenerated );
212 return vector;
213}
214
215
216/**
217 * Write a TwoSpectTemplateVector to binary file
218 * \param [in] vector Pointer to the TwoSpectTemplateVector
219 * \param [in] filename String of the filename
220 * \return Status value
221 */
223{
224 XLAL_CHECK( vector != NULL && filename != NULL, XLAL_EINVAL );
225
226 FILE *fp = NULL;
227 XLAL_CHECK( ( fp = fopen( filename, "wb" ) ) != NULL, XLAL_EIO, "Couldn't fopen %s for writing\n", filename );
228 XLAL_CHECK( fwrite( &( vector->length ), sizeof( UINT4 ), 1, fp ) == 1, XLAL_EIO );
229 XLAL_CHECK( fwrite( &( vector->data[0]->templatedata->length ), sizeof( UINT4 ), 1, fp ) == 1, XLAL_EIO );
230 XLAL_CHECK( fwrite( &( vector->Tsft ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
231 XLAL_CHECK( fwrite( &( vector->SFToverlap ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
232 XLAL_CHECK( fwrite( &( vector->Tobs ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
233 for ( UINT4 ii = 0; ii < vector->length; ii++ ) {
234 XLAL_CHECK( fwrite( vector->data[ii]->templatedata->data, sizeof( REAL4 ), vector->data[ii]->templatedata->length, fp ) == vector->data[ii]->templatedata->length, XLAL_EIO );
235 XLAL_CHECK( fwrite( vector->data[ii]->pixellocations->data, sizeof( INT4 ), vector->data[ii]->pixellocations->length, fp ) == vector->data[ii]->pixellocations->length, XLAL_EIO );
236 XLAL_CHECK( fwrite( &( vector->data[ii]->f0 ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
237 XLAL_CHECK( fwrite( &( vector->data[ii]->period ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
238 XLAL_CHECK( fwrite( &( vector->data[ii]->moddepth ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
239 }
240 fclose( fp );
241
242 return XLAL_SUCCESS;
243}
244
245/**
246 * Read a TwoSpectTemplateVector from a binary file
247 * \param [in] filename String of the filename
248 * \return Pointer to a new TwoSpectTemplateVector
249 */
251{
253
255 UINT4 vectorlength, templatelength;
256 FILE *fp = NULL;
257 XLAL_CHECK_NULL( ( fp = fopen( filename, "rb" ) ) != NULL, XLAL_EIO, "Couldn't fopen %s for reading\n", filename );
258
259 XLAL_CHECK_NULL( fread( &vectorlength, sizeof( UINT4 ), 1, fp ) == 1, XLAL_EIO );
260 XLAL_CHECK_NULL( fread( &templatelength, sizeof( UINT4 ), 1, fp ) == 1, XLAL_EIO );
261 XLAL_CHECK_NULL( ( vector = createTwoSpectTemplateVector( vectorlength, templatelength ) ) != NULL, XLAL_EFUNC );
262 XLAL_CHECK_NULL( fread( &( vector->Tsft ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
263 XLAL_CHECK_NULL( fread( &( vector->SFToverlap ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
264 XLAL_CHECK_NULL( fread( &( vector->Tobs ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
265 for ( UINT4 ii = 0; ii < vectorlength; ii++ ) {
266 XLAL_CHECK_NULL( fread( vector->data[ii]->templatedata->data, sizeof( REAL4 ), templatelength, fp ) == templatelength, XLAL_EIO );
267 XLAL_CHECK_NULL( fread( vector->data[ii]->pixellocations->data, sizeof( INT4 ), templatelength, fp ) == templatelength, XLAL_EIO );
268 XLAL_CHECK_NULL( fread( &( vector->data[ii]->f0 ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
269 XLAL_CHECK_NULL( fread( &( vector->data[ii]->period ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
270 XLAL_CHECK_NULL( fread( &( vector->data[ii]->moddepth ), sizeof( REAL8 ), 1, fp ) == 1, XLAL_EIO );
271 }
272 fclose( fp );
273
274 return vector;
275}
276
277
278/**
279 * \brief Make an estimated template based on FFT of train of Gaussians
280 *
281 * This is eq. 18 of E. Goetz and K. Riles (2011). This handles spillages of power into neighboring frequency bins a little
282 * more gracefully. Numerical stability issues mean that we need to compute exp(log(eq. 18)) = eq. 18
283 * exp(log(eq. 18)) = exp(log(4*pi*sigma^2) - sigma^2*omegapr^2) * (1+cos(delta*omegapr)) * exp(log(1-cos(N*P*omegapr))-log(P*omegapr))
284 * \param [out] output Pointer to TwoSpectTemplate
285 * \param [in] input An input candidate structure
286 * \param [in] params Pointer to UserInput_t
287 * \return Status value
288 */
290{
291 XLAL_CHECK( output != NULL && params != NULL, XLAL_EINVAL );
292 XLAL_CHECK( input.period != 0.0 && input.moddepth != 0.0, XLAL_EINVAL, "Invalid input (%f, %f, %f)\n", input.fsig, input.period, input.moddepth );
293
294 REAL8 freqbin = input.fsig * params->Tsft;
295 INT4 roundedbinval = ( INT4 )round( freqbin );
296 REAL8 offset = freqbin - roundedbinval;
297
298 INT4 ffdatabin0 = ( INT4 )round( ( params->fmin - params->dfmax ) * params->Tsft ) - 6;
299 INT4 sigbin0 = roundedbinval - ffdatabin0;
300
301 UINT4 numffts = ( UINT4 )floor( params->Tobs / ( params->Tsft - params->SFToverlap ) - 1 );
302 UINT4 numfprbins = ( UINT4 )floorf( 0.5 * numffts ) + 1;
303
304 XLAL_CHECK( makeTemplateGaussians2( output, offset, input.period, input.moddepth, params->Tsft, params->SFToverlap, params->Tobs, params->minTemplateLength, ( UINT4 )params->vectorMath ) == XLAL_SUCCESS, XLAL_EFUNC );
305
306 for ( UINT4 ii = 0; ii < output->pixellocations->length; ii++ ) {
307 output->pixellocations->data[ii] += sigbin0 * numfprbins;
308 }
309
310 //makeTemplateGaussians2 sets moddepth and P but not fsig, so we do that here
311 output->f0 = input.fsig;
312
313 return XLAL_SUCCESS;
314
315}
316
317
318/**
319 * \brief Convert an arbitrary frequency bin template into a template for a specific frequency bin.
320 *
321 * When using this function, the input template should be generated first using makeTemplate*2 functions.
322 * Then call this function with a specific bin center frequency.
323 * The input template can contain an offset up to half a frequency bin in order to generate any frequency of a template.
324 * The output template must be at most as long as the input template. For shorter lengths, only the first output->templatedata->length values are kept
325 * \param [in,out] output Pointer to a TwoSpectTemplate for a specific frequency bin
326 * \param [in] input Pointer to a TwoSpectTemplate for an arbitrary frequency bin
327 * \param [in] freq Frequency of a bin centered signal
328 * \param [in] params Pointer to a UserInput_t struct
329 */
331{
332 XLAL_CHECK( output != NULL && input != NULL && params != NULL && freq >= params->fmin && freq < params->fmin + params->fspan, XLAL_EINVAL );
333
335
336 UINT4 numffts = ( UINT4 )floor( params->Tobs / ( params->Tsft - params->SFToverlap ) - 1 );
337 UINT4 numfprbins = ( UINT4 )floorf( 0.5 * numffts ) + 1;
338
339 memcpy( output->templatedata->data, input->templatedata->data, sizeof( REAL4 )*output->templatedata->length );
340 memcpy( output->pixellocations->data, input->pixellocations->data, sizeof( INT4 )*output->pixellocations->length );
341 output->f0 = freq + input->f0 / params->Tsft;
342 output->period = input->period;
343 output->moddepth = input->moddepth;
344
345 REAL8 freqbin = freq * params->Tsft;
346 INT4 roundedbinval = ( INT4 )round( freqbin );
347 INT4 ffdatabin0 = ( INT4 )round( ( params->fmin - params->dfmax ) * params->Tsft ) - 6;
348 INT4 sigbin0 = roundedbinval - ffdatabin0;
349 for ( UINT4 ii = 0; ii < output->pixellocations->length; ii++ ) {
350 output->pixellocations->data[ii] += sigbin0 * numfprbins;
351 }
352
353 return XLAL_SUCCESS;
354}
355
356
357/**
358 * \brief Make an estimated template based on FFT of train of Gaussians
359 *
360 * This is eq. 18 of E. Goetz and K. Riles (2011). This handles spillages of power into neighboring frequency bins a little
361 * more gracefully. Numerical stability issues mean that we need to compute exp(log(eq. 18)) = eq. 18
362 * exp(log(eq. 18)) = exp(log(4*pi*sigma^2) - sigma^2*omegapr^2) * (1+cos(delta*omegapr)) * exp(log(1-cos(N*P*omegapr))-log(P*omegapr))
363 * \param [in,out] output Pointer to TwoSpectTemplate
364 * \param [in] offset Amount of offset from bin centered signal (-0.5 <= offset <= 0.5)
365 * \param [in] P Orbital period (seconds)
366 * \param [in] deltaf Modulation depth of the signal (Hz)
367 * \param [in] Tsft Length of an SFT (s)
368 * \param [in] SFToverlap SFT overlap (s)
369 * \param [in] Tobs Observation time (s)
370 * \param [in] minTemplateLength Minimum number of pixels in a template
371 * \param [in] vectormathflag Flag indicating to use vector math: 0 = none, 1 = SSE, 2 = AVX (must compile for vector math appropriately and CPU must have those instructions)
372 * \return Status value
373 */
374INT4 makeTemplateGaussians2( TwoSpectTemplate *output, const REAL8 offset, const REAL8 P, const REAL8 deltaf, const REAL8 Tsft, const REAL8 SFToverlap, const REAL8 Tobs, const UINT4 minTemplateLength, const UINT4 vectormathflag )
375{
376
377 XLAL_CHECK( output != NULL, XLAL_EINVAL );
378 XLAL_CHECK( offset <= 0.5 && offset >= -0.5 && P != 0.0 && deltaf != 0.0, XLAL_EINVAL, "Invalid input (%f, %f, %f)\n", offset, P, deltaf );
379
380 UINT4 numffts = ( UINT4 )floor( Tobs / ( Tsft - SFToverlap ) - 1 );
381 UINT4 numfprbins = ( UINT4 )floorf( 0.5 * numffts ) + 1;
382
383 //Set data for output template
384 output->f0 = offset;
385 output->period = P;
386 output->moddepth = deltaf;
387
388 //Reset the data values to zero, just in case
389 memset( output->templatedata->data, 0, sizeof( REAL4 )*output->templatedata->length );
390
391 INT4 N = ( INT4 )floor( Tobs / P ); //Number of Gaussians = observation time / period
392 REAL8 periodf = 1.0 / P;
393
394 //Create second FFT frequencies and other useful values
395 REAL4VectorAligned *fpr = NULL;
396 XLAL_CHECK( ( fpr = XLALCreateREAL4VectorAligned( numfprbins, 32 ) ) != NULL, XLAL_EFUNC );
397 for ( UINT4 ii = 0; ii < fpr->length; ii++ ) {
398 fpr->data[ii] = ( REAL4 )ii * ( 1.0 / Tobs );
399 }
400
401 //For speed, we will precompute a number of useful vectors described by their names
402 //This part is the allocation
403 REAL4VectorAligned *omegapr = NULL, *omegapr_squared = NULL, *cos_ratio = NULL;
404 XLAL_CHECK( ( omegapr = XLALCreateREAL4VectorAligned( fpr->length, 32 ) ) != NULL, XLAL_EFUNC );
405 XLAL_CHECK( ( omegapr_squared = XLALCreateREAL4VectorAligned( fpr->length, 32 ) ) != NULL, XLAL_EFUNC );
406 XLAL_CHECK( ( cos_ratio = XLALCreateREAL4VectorAligned( fpr->length, 32 ) ) != NULL, XLAL_EFUNC );
407
408 //Doing the precomputation of the useful values
410 XLAL_CHECK( XLALVectorMultiplyREAL4( omegapr_squared->data, omegapr->data, omegapr->data, omegapr->length ) == XLAL_SUCCESS, XLAL_EFUNC );
411 if ( N * P * omegapr->data[omegapr->length - 1] < 2.147483647e9 ) {
412 for ( UINT4 ii = 0; ii < fpr->length; ii++ ) {
413 REAL4 tempSinValue = 0.0, cos_omegapr_times_period = 0.0, cos_N_times_omegapr_times_period = 0.0;
414 XLAL_CHECK( XLALSinCosLUT( &tempSinValue, &cos_omegapr_times_period, P * omegapr->data[ii] ) == XLAL_SUCCESS, XLAL_EFUNC );
415 XLAL_CHECK( XLALSinCosLUT( &tempSinValue, &cos_N_times_omegapr_times_period, N * P * omegapr->data[ii] ) == XLAL_SUCCESS, XLAL_EFUNC );
416 if ( cos_N_times_omegapr_times_period > 1.0 ) {
417 cos_N_times_omegapr_times_period = 1.0;
418 }
419 if ( cos_omegapr_times_period > 1.0 ) {
420 cos_omegapr_times_period = 1.0;
421 }
422 if ( cos_N_times_omegapr_times_period < -1.0 ) {
423 cos_N_times_omegapr_times_period = -1.0;
424 }
425 if ( cos_omegapr_times_period < -1.0 ) {
426 cos_omegapr_times_period = -1.0;
427 }
428 if ( cos_N_times_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) && cos_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) ) {
429 cos_ratio->data[ii] = ( 1.0 - cos_N_times_omegapr_times_period ) / ( 1.0 - cos_omegapr_times_period );
430 } else if ( cos_N_times_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) ) {
431 REAL8 fmodval = fmod( P * omegapr->data[ii], LAL_TWOPI );
432 cos_ratio->data[ii] = 2.0 * ( 1.0 - cos_N_times_omegapr_times_period ) / ( fmodval * fmodval );
433 } else if ( cos_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) ) {
434 REAL8 fmodval = fmod( N * P * omegapr->data[ii], LAL_TWOPI );
435 cos_ratio->data[ii] = 0.5 * fmodval * fmodval / ( 1.0 - cos_omegapr_times_period );
436 } else {
437 cos_ratio->data[ii] = ( REAL4 )( N * N );
438 }
439 }
440 } else if ( P * omegapr->data[omegapr->length - 1] < 2.147483647e9 ) {
441 for ( UINT4 ii = 0; ii < fpr->length; ii++ ) {
442 REAL4 tempSinValue = 0.0, cos_omegapr_times_period = 0.0;
443 XLAL_CHECK( XLALSinCosLUT( &tempSinValue, &cos_omegapr_times_period, P * omegapr->data[ii] ) == XLAL_SUCCESS, XLAL_EFUNC );
444 if ( cos_omegapr_times_period > 1.0 ) {
445 cos_omegapr_times_period = 1.0;
446 }
447 if ( cos_omegapr_times_period < -1.0 ) {
448 cos_omegapr_times_period = -1.0;
449 }
450 REAL4 cos_N_times_omegapr_times_period = cosf( ( REAL4 )( N * P * omegapr->data[ii] ) );
451 if ( cos_N_times_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) && cos_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) ) {
452 cos_ratio->data[ii] = ( 1.0 - cos_N_times_omegapr_times_period ) / ( 1.0 - cos_omegapr_times_period );
453 } else if ( cos_N_times_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) ) {
454 REAL8 fmodval = fmod( P * omegapr->data[ii], LAL_TWOPI );
455 cos_ratio->data[ii] = 2.0 * ( 1.0 - cos_N_times_omegapr_times_period ) / ( fmodval * fmodval );
456 } else if ( cos_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) ) {
457 REAL8 fmodval = fmod( N * P * omegapr->data[ii], LAL_TWOPI );
458 cos_ratio->data[ii] = 0.5 * fmodval * fmodval / ( 1.0 - cos_omegapr_times_period );
459 } else {
460 cos_ratio->data[ii] = ( REAL4 )( N * N );
461 }
462 }
463 } else {
464 for ( UINT4 ii = 0; ii < fpr->length; ii++ ) {
465 REAL4 cos_omegapr_times_period = cosf( ( REAL4 )( P * omegapr->data[ii] ) );
466 REAL4 cos_N_times_omegapr_times_period = cosf( ( REAL4 )( N * P * omegapr->data[ii] ) );
467 if ( cos_N_times_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) && cos_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) ) {
468 cos_ratio->data[ii] = ( 1.0 - cos_N_times_omegapr_times_period ) / ( 1.0 - cos_omegapr_times_period );
469 } else if ( cos_N_times_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) ) {
470 REAL8 fmodval = fmod( P * omegapr->data[ii], LAL_TWOPI );
471 cos_ratio->data[ii] = 2.0 * ( 1.0 - cos_N_times_omegapr_times_period ) / ( fmodval * fmodval );
472 } else if ( cos_omegapr_times_period <= ( 1.0 - 100.0 * LAL_REAL4_EPS ) ) {
473 REAL8 fmodval = fmod( N * P * omegapr->data[ii], LAL_TWOPI );
474 cos_ratio->data[ii] = 0.5 * fmodval * fmodval / ( 1.0 - cos_omegapr_times_period );
475 } else {
476 cos_ratio->data[ii] = ( REAL4 )( N * N );
477 }
478 }
479 }
480
481 //Determine span of the template
482 REAL8 binamplitude = deltaf * Tsft;
483 REAL8 binmin = -binamplitude + offset;
484 REAL8 binmax = binamplitude + offset;
485 INT4 templatemin = ( INT4 )round( binmin ), templatemax = ( INT4 )round( binmax );
486 if ( templatemin > binmin ) {
487 templatemin--;
488 }
489 if ( templatemin - binmin >= -0.5 ) {
490 templatemin--;
491 }
492 if ( templatemax < binmax ) {
493 templatemax++;
494 }
495 if ( templatemax - binmax <= 0.5 ) {
496 templatemax++;
497 }
498 UINT4 templatespan = ( UINT4 )( templatemax - templatemin ) + 1;
499 REAL8 disttominbin = binmin - templatemin, disttomaxbin = templatemax - binmax, disttomidbin = offset - templatemin;
500
501 //Determine the weighting scale for the leakage bins and the distance between Gaussians := phi_actual
502 REAL4VectorAligned *scale = NULL, *phi_actual = NULL;
503 XLAL_CHECK( ( scale = XLALCreateREAL4VectorAligned( templatespan, 32 ) ) != NULL, XLAL_EFUNC );
504 XLAL_CHECK( ( phi_actual = XLALCreateREAL4VectorAligned( templatespan, 32 ) ) != NULL, XLAL_EFUNC );
505 memset( scale->data, 0, templatespan * sizeof( REAL4 ) );
506 memset( phi_actual->data, 0, templatespan * sizeof( REAL4 ) );
507 for ( UINT4 ii = 0; ii < scale->length; ii++ ) {
508 if ( ii != 0 && ii != scale->length - 1 ) {
509 scale->data[ii] = 1.0;
510 } else if ( ii == 0 ) {
511 scale->data[ii] = sqsincxoverxsqminusone( disttominbin );
513 } else {
514 scale->data[ii] = sqsincxoverxsqminusone( disttomaxbin );
516 }
517
518 if ( fabs( ii - disttomidbin ) / ( deltaf * Tsft ) <= 1.0 ) {
519 phi_actual->data[ii] = 0.5 * P - asin( fabs( ii - disttomidbin ) / ( deltaf * Tsft ) ) * LAL_1_PI * P;
520 }
521 }
522
523 //Make sigmas for each frequency
524 //First, allocate vectors
525 REAL4VectorAligned *sigmas = NULL, *wvals = NULL, *binvals = NULL, *bindiffvals = NULL, *absbindiffvals = NULL;
526 REAL4VectorAlignedArray *allsigmas = NULL, *weightvals = NULL;
527 XLAL_CHECK( ( sigmas = XLALCreateREAL4VectorAligned( templatespan, 32 ) ) != NULL, XLAL_EFUNC );
528 XLAL_CHECK( ( wvals = XLALCreateREAL4VectorAligned( ( UINT4 )floor( 30.0 * P / Tsft ), 32 ) ) != NULL, XLAL_EFUNC );
529 XLAL_CHECK( ( allsigmas = createREAL4VectorAlignedArray( wvals->length, sigmas->length, 32 ) ) != NULL, XLAL_EFUNC );
530 XLAL_CHECK( ( weightvals = createREAL4VectorAlignedArray( wvals->length, sigmas->length, 32 ) ) != NULL, XLAL_EFUNC );
531 XLAL_CHECK( ( binvals = XLALCreateREAL4VectorAligned( sigmas->length, 32 ) ) != NULL, XLAL_EFUNC );
532 for ( UINT4 jj = 0; jj < binvals->length; jj++ ) {
533 binvals->data[jj] = -( ( REAL4 )jj + templatemin );
534 }
535 XLAL_CHECK( ( bindiffvals = XLALCreateREAL4VectorAligned( binvals->length, 32 ) ) != NULL, XLAL_EFUNC );
536 XLAL_CHECK( ( absbindiffvals = XLALCreateREAL4VectorAligned( binvals->length, 32 ) ) != NULL, XLAL_EFUNC );
537
538 //Here is where the sigmas are computed. It is a weighted average. t = (ii+1)*in->Tsft*0.5
539 REAL4 sin2pix = 0.0, cos2pix = 0.0;
540 for ( UINT4 ii = 0; ii < wvals->length; ii++ ) {
541 //calculate sin and cos of 2*pi*t/P and then the bin the signal is in and the signal velocity
542 XLAL_CHECK( XLALSinCos2PiLUT( &sin2pix, &cos2pix, periodf * ( ( ii + 1 )*Tsft * 0.5 ) ) == XLAL_SUCCESS, XLAL_EFUNC );
543 if ( cos2pix > 1.0 ) {
544 cos2pix = 1.0;
545 } else if ( cos2pix < -1.0 ) {
546 cos2pix = -1.0;
547 }
548 REAL4 sigbin = ( deltaf * cos2pix ) * Tsft + offset;
549 REAL4 sigbinvelocity = fabs( -deltaf * sin2pix * Tsft * Tsft * LAL_PI * periodf );
550
551 //Compute bin diff values
552 XLAL_CHECK( XLALVectorShiftREAL4( bindiffvals->data, sigbin, binvals->data, bindiffvals->length ) == XLAL_SUCCESS, XLAL_EFUNC );
553 XLAL_CHECK( VectorAbsREAL4( absbindiffvals, bindiffvals, vectormathflag ) == XLAL_SUCCESS, XLAL_EFUNC );
554
555 //if the velocity approaches zero, the sigma calculation will diverge (which it should do) but this is bad numerically, so we cap it
556 if ( sigbinvelocity < 1.0e-4 ) {
557 sigbinvelocity = 1.0e-4;
558 }
559
560 //REAL4 sigma = 0.5*Tsft * (0.5346 * powf(sigbinvelocity, -1.0213f)); //Derived fit from simulation
561 REAL4 sigma = 0.5 * Tsft * ( 0.5979 / ( sigbinvelocity - 3.2895e-5 ) ); //Could think about using this fit in the future
562
563 //set all weightvals in each vector to zero
564 memset( weightvals->data[ii]->data, 0, sizeof( REAL4 )*weightvals->data[ii]->length );
565
566 REAL4 threshold = 1.75;
567 for ( UINT4 jj = 0; jj < sigmas->length; jj++ ) {
568 if ( absbindiffvals->data[jj] < threshold ) {
569 weightvals->data[ii]->data[jj] = sqsincxoverxsqminusone( bindiffvals->data[jj] );
571 }
572 }
573 XLAL_CHECK( XLALVectorScaleREAL4( allsigmas->data[ii]->data, sigma, weightvals->data[ii]->data, sigmas->length ) == XLAL_SUCCESS, XLAL_EFUNC );
574
575 } /* for ii < wvals->length */
576 for ( UINT4 ii = 0; ii < sigmas->length; ii++ ) {
577 REAL8 wavesigma = 0.0;
578 REAL8 totalw = 0.0;
579 for ( UINT4 jj = 0; jj < wvals->length; jj++ ) {
580 if ( weightvals->data[jj]->data[ii] != 0.0 ) {
581 wavesigma += allsigmas->data[jj]->data[ii];
582 totalw += weightvals->data[jj]->data[ii];
583 }
584 }
585 sigmas->data[ii] = ( REAL4 )( wavesigma / totalw );
586 } /* for ii < sigmas->length */
587
588 //Allocate more useful data vectors. These get computed for each different first FFT frequency bin in the F-F plane
589 REAL4VectorAligned *exp_neg_sigma_sq_times_omega_pr_sq = NULL, *sin_phi_times_omega_pr = NULL, *cos_phi_times_omega_pr = NULL, *phi_times_fpr = NULL, *datavector = NULL;
590 XLAL_CHECK( ( exp_neg_sigma_sq_times_omega_pr_sq = XLALCreateREAL4VectorAligned( omegapr_squared->length, 32 ) ) != NULL, XLAL_EFUNC );
591 XLAL_CHECK( ( sin_phi_times_omega_pr = XLALCreateREAL4VectorAligned( omegapr->length, 32 ) ) != NULL, XLAL_EFUNC );
592 XLAL_CHECK( ( cos_phi_times_omega_pr = XLALCreateREAL4VectorAligned( omegapr->length, 32 ) ) != NULL, XLAL_EFUNC );
593 XLAL_CHECK( ( phi_times_fpr = XLALCreateREAL4VectorAligned( fpr->length, 32 ) ) != NULL, XLAL_EFUNC );
594 XLAL_CHECK( ( datavector = XLALCreateREAL4VectorAligned( fpr->length, 32 ) ) != NULL, XLAL_EFUNC );
595
596 //Create template. We are going to do exp(log(Eq. 18))
597 REAL8 sum = 0.0;
598 REAL4 log4pi = 2.53102424697f;
599 for ( UINT4 ii = 0; ii < sigmas->length; ii++ ) {
600 INT4 bins2middlebin = ii + templatemin; //Number of frequency bins away from the "central frequency bin" of the template
601
602 memset( datavector->data, 0, sizeof( REAL4 )*datavector->length );
603
604 //Scaling factor for leakage
605 REAL4 scale1 = sqrtf( ( REAL4 )( 1.0 / ( 1.0 + expf( ( REAL4 )( -phi_actual->data[ii] * phi_actual->data[ii] * 0.5 / ( sigmas->data[ii] * sigmas->data[ii] ) ) ) ) ) );
606
607 //pre-factor
608 //REAL8 prefact0 = scale1 * 2.0 * LAL_TWOPI * sigmas->data[ii] * sigmas->data[ii];
609 //REAL4 prefact0 = log(scale1 * 2.0 * LAL_TWOPI * sigmas->data[ii] * sigmas->data[ii]); //We are going to do exp(log(Eq. 18))
610 REAL4 prefact0 = log4pi + 2.0 * logf( ( REAL4 )( scale1 * sigmas->data[ii] ) );
611
612 if ( vectormathflag == 1 || vectormathflag == 2 ) {
613 //Compute exp(log(4*pi*s*s*exp(-s*s*omegapr_squared))) = exp(log(4*pi*s*s)-s*s*omegapr_squared)
614 XLAL_CHECK( XLALVectorScaleREAL4( exp_neg_sigma_sq_times_omega_pr_sq->data, -sigmas->data[ii]*sigmas->data[ii], omegapr_squared->data, omegapr_squared->length ) == XLAL_SUCCESS, XLAL_EFUNC );
615 XLAL_CHECK( XLALVectorShiftREAL4( exp_neg_sigma_sq_times_omega_pr_sq->data, prefact0, exp_neg_sigma_sq_times_omega_pr_sq->data, exp_neg_sigma_sq_times_omega_pr_sq->length ) == XLAL_SUCCESS, XLAL_EFUNC );
616 UINT4 truncationLength = 1;
617 while ( truncationLength < omegapr_squared->length && exp_neg_sigma_sq_times_omega_pr_sq->data[truncationLength] > -88.0 ) {
618 truncationLength++;
619 }
620 XLAL_CHECK( XLALVectorExpREAL4( exp_neg_sigma_sq_times_omega_pr_sq->data, exp_neg_sigma_sq_times_omega_pr_sq->data, truncationLength ) == XLAL_SUCCESS, XLAL_EFUNC );
621
622 //Compute phi_actual*fpr
623 XLAL_CHECK( XLALVectorScaleREAL4( phi_times_fpr->data, phi_actual->data[ii], fpr->data, truncationLength ) == XLAL_SUCCESS, XLAL_EFUNC );
624
625 //Start computing the datavector values
626 INT4 maxindex = max_index_in_range( phi_times_fpr, 0, truncationLength - 1 );
627 if ( phi_times_fpr->data[maxindex] <= 2.147483647e9 ) {
628 //Compute cos(2*pi*phi_actual*fpr) using LUT and SSE
629 XLAL_CHECK( XLALVectorSinCos2PiREAL4( sin_phi_times_omega_pr->data, cos_phi_times_omega_pr->data, phi_times_fpr->data, truncationLength ) == XLAL_SUCCESS, XLAL_EFUNC );
630 } else {
631 //Compute cos(2*pi*phi_actual*fpr) without using LUT
632 for ( UINT4 jj = 0; jj < truncationLength; jj++ ) {
633 cos_phi_times_omega_pr->data[jj] = cosf( ( REAL4 )LAL_TWOPI * phi_times_fpr->data[jj] );
634 }
635 }
636 //datavector = cos(phi_actual*omega_pr) + 1.0
637 XLAL_CHECK( XLALVectorShiftREAL4( datavector->data, 1.0, cos_phi_times_omega_pr->data, truncationLength ) == XLAL_SUCCESS, XLAL_EFUNC );
638 //datavector = prefact0 * exp(-s*s*omega_pr*omega_pr) * [cos(phi_actual*omega_pr) + 1.0]
639 XLAL_CHECK( XLALVectorMultiplyREAL4( datavector->data, datavector->data, exp_neg_sigma_sq_times_omega_pr_sq->data, truncationLength ) == XLAL_SUCCESS, XLAL_EFUNC );
640 //datavector = scale * exp(-s*s*omega_pr*omega_pr) * [cos(phi_actual*omega_pr) + 1.0]
641 XLAL_CHECK( XLALVectorScaleREAL4( datavector->data, scale->data[ii], datavector->data, truncationLength ) == XLAL_SUCCESS, XLAL_EFUNC );
642 //datavector *= cos_ratio
643 XLAL_CHECK( XLALVectorMultiplyREAL4( datavector->data, datavector->data, cos_ratio->data, truncationLength ) == XLAL_SUCCESS, XLAL_EFUNC );
644 } else {
645 for ( UINT4 jj = 0; jj < omegapr_squared->length; jj++ ) {
646 //Do all or nothing if the exponential is too negative
647 if ( ( prefact0 - sigmas->data[ii]*sigmas->data[ii]*omegapr_squared->data[jj] ) > -88.0 ) {
648 exp_neg_sigma_sq_times_omega_pr_sq->data[jj] = expf( ( REAL4 )( prefact0 - sigmas->data[ii] * sigmas->data[ii] * omegapr_squared->data[jj] ) );
649 XLAL_CHECK( XLALSinCos2PiLUT( &sin2pix, &cos2pix, phi_actual->data[ii]*fpr->data[jj] ) == XLAL_SUCCESS, XLAL_EFUNC );
650 if ( cos2pix > 1.0 ) {
651 cos2pix = 1.0;
652 } else if ( cos2pix < -1.0 ) {
653 cos2pix = -1.0;
654 }
655 cos_phi_times_omega_pr->data[jj] = ( REAL4 )cos2pix;
656 datavector->data[jj] = scale->data[ii] * exp_neg_sigma_sq_times_omega_pr_sq->data[jj] * ( cos_phi_times_omega_pr->data[jj] + 1.0 ) * cos_ratio->data[jj];
657 }
658 /* Don't need to compute the else because the datavector was set to zero in the outer for loop */
659 } /* for jj = 0 --> omegapr_squared->length */
660 } /* use SSE or not */
661
662 //Now loop through the second FFT frequencies, starting with index 4
663 for ( UINT4 jj = 4; jj < omegapr->length; jj++ ) {
664 //Sum up the weights in total
665 sum += ( REAL8 )( datavector->data[jj] );
666
667 //Compare with weakest top bins and if larger, launch a search to find insertion spot (insertion sort)
668 if ( datavector->data[jj] > output->templatedata->data[output->templatedata->length - 1] ) {
669 insertionSort_template( output, datavector->data[jj], bins2middlebin * fpr->length + jj );
670 }
671 } /* for jj < omegapr->length */
672 } /* for ii < sigmas->length */
673
674 //Normalize
675 REAL4 invsum = ( REAL4 )( 1.0 / sum );
676 XLAL_CHECK( XLALVectorScaleREAL4( output->templatedata->data, invsum, output->templatedata->data, output->templatedata->length ) == XLAL_SUCCESS, XLAL_EFUNC );
677
678 //Truncate weights when they don't add much to the total sum of weights
679 sum = 0.0;
680 for ( UINT4 ii = 0; ii < minTemplateLength; ii++ ) {
681 sum += ( REAL8 )output->templatedata->data[ii];
682 }
683 UINT4 counter = minTemplateLength;
684 while ( counter < output->templatedata->length && output->templatedata->data[counter] >= epsval_float( ( REAL4 )sum ) ) {
685 sum += ( REAL8 )output->templatedata->data[counter];
686 counter++;
687 }
688 for ( /* last counter val */; counter < output->templatedata->length; counter++ ) {
689 output->templatedata->data[counter] = 0.0;
690 }
691
692 //Destroy variables
693 XLALDestroyREAL4VectorAligned( phi_actual );
697 XLALDestroyREAL4VectorAligned( bindiffvals );
698 XLALDestroyREAL4VectorAligned( absbindiffvals );
700 destroyREAL4VectorAlignedArray( weightvals );
704 XLALDestroyREAL4VectorAligned( omegapr_squared );
706 XLALDestroyREAL4VectorAligned( exp_neg_sigma_sq_times_omega_pr_sq );
707 XLALDestroyREAL4VectorAligned( phi_times_fpr );
708 XLALDestroyREAL4VectorAligned( sin_phi_times_omega_pr );
709 XLALDestroyREAL4VectorAligned( cos_phi_times_omega_pr );
710 XLALDestroyREAL4VectorAligned( datavector );
711
712 return XLAL_SUCCESS;
713
714} /* makeTemplateGaussians() */
715
716
717/**
718 * \brief Make an template based on FFT of sinc squared functions
719 *
720 * This is eq. 20 of E. Goetz and K. Riles (2011)
721 * \param [out] output Pointer to TwoSpectTemplate
722 * \param [in] input An input candidate structure
723 * \param [in] params Pointer to UserInput_t
724 * \param [in] plan Pointer to REAL4FFTPlan
725 * \return Status value
726 */
727INT4 makeTemplate( TwoSpectTemplate *output, const candidate input, const UserInput_t *params, const REAL4FFTPlan *plan )
728{
729
730 XLAL_CHECK( output != NULL && params != NULL && plan != NULL, XLAL_EINVAL );
731
732 REAL8 freqbin = input.fsig * params->Tsft;
733 INT4 roundedbinval = ( INT4 )round( freqbin );
734 REAL8 offset = freqbin - roundedbinval;
735
736 INT4 ffdatabin0 = ( INT4 )round( ( params->fmin - params->dfmax ) * params->Tsft ) - 6;
737 INT4 sigbin0 = roundedbinval - ffdatabin0;
738
739 UINT4 numffts = ( UINT4 )floor( params->Tobs / ( params->Tsft - params->SFToverlap ) - 1 );
740 UINT4 numfprbins = ( UINT4 )floorf( 0.5 * numffts ) + 1;
741
742 XLAL_CHECK( makeTemplate2( output, offset, input.period, input.moddepth, params->Tsft, params->SFToverlap, params->Tobs, params->minTemplateLength, ( UINT4 )params->vectorMath, plan ) == XLAL_SUCCESS, XLAL_EFUNC );
743
744 for ( UINT4 ii = 0; ii < output->pixellocations->length; ii++ ) {
745 output->pixellocations->data[ii] += sigbin0 * numfprbins;
746 }
747
748 output->f0 = input.fsig;
749
750 return XLAL_SUCCESS;
751
752}
753
754
755/**
756 * \brief Make an template based on FFT of sinc squared functions
757 *
758 * This is eq. 20 of E. Goetz and K. Riles (2011)
759 * \param [in,out] output Pointer to TwoSpectTemplate
760 * \param [in] offset Amount of offset from bin centered signal (-0.5 <= offset <= 0.5)
761 * \param [in] P Orbital period (seconds)
762 * \param [in] deltaf Modulation depth of the signal (Hz)
763 * \param [in] Tsft Length of an SFT (s)
764 * \param [in] SFToverlap SFT overlap (s)
765 * \param [in] Tobs Observation time (s)
766 * \param [in] minTemplateLength Minimum number of pixels in a template
767 * \param [in] vectormathflag Flag indicating to use vector math: 0 = none, 1 = SSE, 2 = AVX (must compile for vector math appropriately and CPU must have those instructions)
768 * \param [in] plan Pointer to REAL4FFTPlan
769 * \return Status value
770 */
771INT4 makeTemplate2( TwoSpectTemplate *output, const REAL8 offset, const REAL8 P, const REAL8 deltaf, const REAL8 Tsft, const REAL8 SFToverlap, const REAL8 Tobs, const UINT4 minTemplateLength, const UINT4 vectormathflag, const REAL4FFTPlan *plan )
772{
773 XLAL_CHECK( output != NULL && plan != NULL, XLAL_EINVAL );
774
775 output->f0 = offset;
776 output->period = P;
777 output->moddepth = deltaf;
778
779 //Reset to zero, just in case
780 memset( output->templatedata->data, 0, sizeof( REAL4 )*output->templatedata->length );
781
782 UINT4 numffts = ( UINT4 )floor( Tobs / ( Tsft - SFToverlap ) - 1 );
783 UINT4 numfprbins = ( UINT4 )floorf( 0.5 * numffts ) + 1;
784
785 //Determine span of the template
786 REAL8 binamplitude = deltaf * Tsft;
787 REAL8 binmin = -binamplitude + offset;
788 REAL8 binmax = binamplitude + offset;
789 INT4 templatemin = ( INT4 )round( binmin ), templatemax = ( INT4 )round( binmax );
790 if ( templatemin > binmin ) {
791 templatemin--;
792 }
793 if ( templatemin - binmin >= -0.5 ) {
794 templatemin--;
795 }
796 if ( templatemax < binmax ) {
797 templatemax++;
798 }
799 if ( templatemax - binmax <= 0.5 ) {
800 templatemax++;
801 }
802 UINT4 templatespan = ( UINT4 )( templatemax - templatemin ) + 1;
803
804 REAL8 periodf = 1.0 / P;
805
806 REAL4VectorAligned *psd1 = NULL;
807 alignedREAL8Vector *freqbins = NULL, *bindiffs = NULL;
808 XLAL_CHECK( ( psd1 = XLALCreateREAL4VectorAligned( templatespan * numffts, 32 ) ) != NULL, XLAL_EFUNC );
809 XLAL_CHECK( ( freqbins = createAlignedREAL8Vector( templatespan, 32 ) ) != NULL, XLAL_EFUNC );
810 XLAL_CHECK( ( bindiffs = createAlignedREAL8Vector( templatespan, 32 ) ) != NULL, XLAL_EFUNC );
811 memset( psd1->data, 0, sizeof( REAL4 )*psd1->length );
812
813 //Bin numbers of the frequencies
814 for ( UINT4 ii = 0; ii < templatespan; ii++ ) {
815 freqbins->data[ii] = ( REAL8 )( templatemin + ( INT4 )ii );
816 }
817
818 //Determine the signal modulation in bins with time at center of coherence time and create
819 //Hann windowed PSDs
820 REAL8 PSDprefact = 2.0 / 3.0;
821 REAL4VectorAligned *t = NULL, *sigbin_sin2PiPeriodfT = NULL, *cos2PiPeriodfT = NULL;
822 XLAL_CHECK( ( t = XLALCreateREAL4VectorAligned( numffts, 32 ) ) != NULL, XLAL_EFUNC );
823 XLAL_CHECK( ( sigbin_sin2PiPeriodfT = XLALCreateREAL4VectorAligned( numffts, 32 ) ) != NULL, XLAL_EFUNC );
824 XLAL_CHECK( ( cos2PiPeriodfT = XLALCreateREAL4VectorAligned( numffts, 32 ) ) != NULL, XLAL_EFUNC );
825 for ( UINT4 ii = 0; ii < numffts; ii++ ) {
826 t->data[ii] = 0.5 * Tsft * ( ii + 1 ); //Assumed 50% overlapping SFTs
827 }
828 XLAL_CHECK( XLALVectorScaleREAL4( t->data, periodf, t->data, t->length ) == XLAL_SUCCESS, XLAL_EFUNC );
829 XLAL_CHECK( XLALVectorSinCos2PiREAL4( sigbin_sin2PiPeriodfT->data, cos2PiPeriodfT->data, t->data, t->length ) == XLAL_SUCCESS, XLAL_EFUNC );
830 XLAL_CHECK( XLALVectorScaleREAL4( sigbin_sin2PiPeriodfT->data, binamplitude, sigbin_sin2PiPeriodfT->data, sigbin_sin2PiPeriodfT->length ) == XLAL_SUCCESS, XLAL_EFUNC );
831 XLAL_CHECK( XLALVectorShiftREAL4( sigbin_sin2PiPeriodfT->data, offset, sigbin_sin2PiPeriodfT->data, sigbin_sin2PiPeriodfT->length ) == XLAL_SUCCESS, XLAL_EFUNC );
833 XLALDestroyREAL4VectorAligned( cos2PiPeriodfT );
834 for ( UINT4 ii = 0; ii < numffts; ii++ ) {
835 REAL8 sigbin = sigbin_sin2PiPeriodfT->data[ii];
836 XLAL_CHECK( VectorShiftREAL8( bindiffs, freqbins, -sigbin, vectormathflag ) == XLAL_SUCCESS, XLAL_EFUNC );
837 for ( UINT4 jj = 0; jj < templatespan; jj++ ) {
838 //Create PSD values organized by f0 => psd1->data[0...numffts-1], sft1 => psd1->data[numffts...2*numffts-1]
839 //Restricting to +/- 1.75 bins means >99.9% of the total power is included in the template calculation
840 if ( fabs( bindiffs->data[jj] ) <= 1.75 ) {
841 psd1->data[ii + jj * numffts] = sqsincxoverxsqminusone( bindiffs->data[jj] ) * PSDprefact;
843 }
844 } /* for jj < numfbins */
845 } /* for ii < numffts */
846 XLALDestroyREAL4VectorAligned( sigbin_sin2PiPeriodfT );
847
848 //Do the second FFT
849 REAL4VectorAligned *x = NULL, *psd = NULL, *windowdata = NULL;
850 REAL4Window *win = NULL;
851 XLAL_CHECK( ( x = XLALCreateREAL4VectorAligned( numffts, 32 ) ) != NULL, XLAL_EFUNC );
852 XLAL_CHECK( ( psd = XLALCreateREAL4VectorAligned( numfprbins, 32 ) ) != NULL, XLAL_EFUNC );
853 XLAL_CHECK( ( windowdata = XLALCreateREAL4VectorAligned( x->length, 32 ) ) != NULL, XLAL_EFUNC );
854 XLAL_CHECK( ( win = XLALCreateHannREAL4Window( x->length ) ) != NULL, XLAL_EFUNC );
855 memcpy( windowdata->data, win->data->data, x->length * sizeof( REAL4 ) );
856 REAL8 winFactor = 8.0 / 3.0, secPSDfactor = winFactor / x->length * 0.5 * Tsft, sum = 0.0;
857 BOOLEAN doSecondFFT;
858 //First loop over frequencies
859 for ( UINT4 ii = 0; ii < templatespan; ii++ ) {
860 //Set doSecondFFT check flag to 0. Value becomes 1 if we are to do the second FFT
861 doSecondFFT = 0;
862
863 INT4 bins2middlebin = ii + templatemin; //Number of frequency bins away from the "central frequency bin" of the template
864
865 //Next, loop over times and check to see if we need to do second FFT
866 //Sum up the power in the row and see if it exceeds 5.0*(sinc(3.0)/(3.0^2-1))^2
867 REAL4 rowpowersum = 0.0;
868 for ( UINT4 jj = 0; jj < x->length; jj++ ) {
869 rowpowersum += psd1->data[ii * numffts + jj];
870 }
871 if ( rowpowersum > 1.187167e-34 ) {
872 doSecondFFT = 1;
873 }
874
875 //If we are to do the second FFT then do it!
876 if ( doSecondFFT ) {
877 //Obtain and window the time series
878 memcpy( x->data, &( psd1->data[ii * numffts] ), sizeof( REAL4 )*x->length );
879 XLAL_CHECK( XLALVectorMultiplyREAL4( x->data, x->data, windowdata->data, x->length ) == XLAL_SUCCESS, XLAL_EFUNC );
880
881 //Do the FFT
883
884 //Scale the data points by 1/N and window factor and (1/fs)
885 //Order of vector is by second frequency then first frequency
886 XLAL_CHECK( XLALVectorScaleREAL4( psd->data, secPSDfactor, psd->data, psd->length ) == XLAL_SUCCESS, XLAL_EFUNC );
887
888 //Ignore the DC to 3rd frequency bins in sum
889 for ( UINT4 jj = 4; jj < psd->length; jj++ ) {
890 sum += ( REAL8 )psd->data[jj]; //sum up the total weight
891
892 //Sort the weights, insertion sort technique
893 if ( psd->data[jj] > output->templatedata->data[output->templatedata->length - 1] ) {
894 insertionSort_template( output, psd->data[jj], bins2middlebin * psd->length + jj );
895 }
896 } /* for jj < psd->length */
897 } /* if doSecondFFT */
898 } /* if ii < numfbins */
899
900 //Normalize
901 REAL4 invsum = ( REAL4 )( 1.0 / sum );
902 XLAL_CHECK( XLALVectorScaleREAL4( output->templatedata->data, invsum, output->templatedata->data, output->templatedata->length ) == XLAL_SUCCESS, XLAL_EFUNC );
903
904 //Truncate weights if they don't contribute much to the sum
905 sum = 0.0;
906 for ( UINT4 ii = 0; ii < minTemplateLength; ii++ ) {
907 sum += ( REAL8 )output->templatedata->data[ii];
908 }
909 UINT4 counter = minTemplateLength;
910 while ( counter < output->templatedata->length && output->templatedata->data[counter] >= epsval_float( ( REAL4 )sum ) ) {
911 sum += ( REAL8 )output->templatedata->data[counter];
912 counter++;
913 }
914 for ( /* last counter val */; counter < output->templatedata->length; counter++ ) {
915 output->templatedata->data[counter] = 0.0;
916 }
917
918 //Destroy stuff
920 destroyAlignedREAL8Vector( freqbins );
921 destroyAlignedREAL8Vector( bindiffs );
925 XLALDestroyREAL4VectorAligned( windowdata );
926
927 return XLAL_SUCCESS;
928
929}
930
931
932/**
933 * Insertion sort for the template weights
934 * \param [out] output Pointer to TwoSpectTemplate
935 * \param [in] weight Pixel weight
936 * \param [in] pixelloc Index of the pixel in the REAL4VectorAligned of the frequency-frequency plane
937 */
938void insertionSort_template( TwoSpectTemplate *output, const REAL4 weight, const INT4 pixelloc )
939{
940
941 INT4 insertionpoint = output->templatedata->length - 1;
942 INT4 numbertomove = 0;
943 while ( insertionpoint > 0 && weight > output->templatedata->data[insertionpoint - 1] ) {
944 insertionpoint--;
945 numbertomove++;
946 }
947
948 if ( insertionpoint < ( INT4 )output->templatedata->length - 1 ) {
949 memmove( &( output->templatedata->data[insertionpoint + 1] ), &( output->templatedata->data[insertionpoint] ), sizeof( REAL4 )*numbertomove );
950 memmove( &( output->pixellocations->data[insertionpoint + 1] ), &( output->pixellocations->data[insertionpoint] ), sizeof( INT4 )*numbertomove );
951 }
952
953 output->templatedata->data[insertionpoint] = weight;
954 output->pixellocations->data[insertionpoint] = pixelloc;
955
956} /* insertionSort_template() */
957
958
959/**
960 * Calculate sin(pi*x)/(pi*x)/(x^2-1)
961 * \param x Value from which to compute
962 */
964{
965 if ( fabs( x * x - 1.0 ) < 1.0e-8 ) {
966 return -0.5;
967 }
968 if ( fabs( x ) < 1.0e-8 ) {
969 return -1.0;
970 }
971 REAL8 pix = LAL_PI * x;
972 //return sin(pix)/(pix*(x*x-1.0));
973 REAL4 sinpix = 0.0, cospix = 0.0;
974 XLAL_CHECK_REAL8( XLALSinCosLUT( &sinpix, &cospix, pix ) == XLAL_SUCCESS, XLAL_EFUNC );
975 if ( sinpix > 1.0 ) {
976 sinpix = 1.0;
977 } else if ( sinpix < -1.0 ) {
978 sinpix = -1.0;
979 }
980 return sinpix / ( pix * ( x * x - 1.0 ) );
981} /* sincxoverxsqminusone() */
982
983
984/**
985 * Calculate [sin(pi*x)/(pi*x)/(x^2-1)]^2
986 * \param x Value from which to compute
987 */
989{
992 return val * val;
993} /* sqsincxoverxsqminusone() */
#define fprintf
REAL4 epsval_float(REAL4 val)
const double scale
multiplicative scaling factor of the coordinate
UINT4 max_index_in_range(const REAL4VectorAligned *vector, const UINT4 startlocation, const UINT4 lastlocation)
Determine the index value of the maximum value between elements of a REAL4VectorAligned (inclusive)
#define LAL_PI
#define LAL_1_PI
#define LAL_TWOPI
#define LAL_REAL4_EPS
unsigned char BOOLEAN
double REAL8
char CHAR
uint32_t UINT4
int32_t INT4
float REAL4
void * XLALMalloc(size_t n)
void XLALFree(void *p)
REAL4FFTPlan * XLALCreateForwardREAL4FFTPlan(UINT4 size, int measurelvl)
void XLALDestroyREAL4FFTPlan(REAL4FFTPlan *plan)
int XLALREAL4PowerSpectrum(REAL4Vector *_LAL_RESTRICT_ spec, const REAL4Vector *_LAL_RESTRICT_ data, const REAL4FFTPlan *plan)
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
INT4Vector * XLALCreateINT4Vector(UINT4 length)
void XLALDestroyINT4Vector(INT4Vector *vector)
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
int XLALVectorScaleREAL4(REAL4 *out, REAL4 scalar, const REAL4 *in, const UINT4 len)
void XLALDestroyREAL4VectorAligned(REAL4VectorAligned *in)
REAL4VectorAligned * XLALCreateREAL4VectorAligned(const UINT4 length, const UINT4 align)
int XLALVectorSinCos2PiREAL4(REAL4 *out1, REAL4 *out2, const REAL4 *in, const UINT4 len)
int XLALVectorExpREAL4(REAL4 *out, const REAL4 *in, const UINT4 len)
int XLALVectorMultiplyREAL4(REAL4 *out, const REAL4 *in1, const REAL4 *in2, const UINT4 len)
int XLALVectorShiftREAL4(REAL4 *out, REAL4 scalar, const REAL4 *in, const UINT4 len)
void XLALDestroyREAL4Window(REAL4Window *window)
REAL4Window * XLALCreateHannREAL4Window(UINT4 length)
#define XLAL_ERROR_VOID(...)
#define xlalErrno
#define XLAL_CHECK(assertion,...)
#define XLAL_CHECK_REAL8(assertion,...)
#define XLAL_CHECK_NULL(assertion,...)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFUNC
XLAL_EIO
XLAL_EINVAL
psd
int N
INT4 * data
REAL4VectorAligned ** data
REAL8 * data
INT4Vector * pixellocations
REAL4VectorAligned * templatedata
REAL8 moddepth
REAL8 period
INT4 makeTemplate(TwoSpectTemplate *output, const candidate input, const UserInput_t *params, const REAL4FFTPlan *plan)
Make an template based on FFT of sinc squared functions.
Definition: templates.c:727
INT4 writeTwoSpectTemplateVector(const TwoSpectTemplateVector *vector, const CHAR *filename)
Write a TwoSpectTemplateVector to binary file.
Definition: templates.c:222
void insertionSort_template(TwoSpectTemplate *output, const REAL4 weight, const INT4 pixelloc)
Insertion sort for the template weights.
Definition: templates.c:938
TwoSpectTemplateVector * generateTwoSpectTemplateVector(const REAL8 Pmin, const REAL8 Pmax, const REAL8 dfmin, const REAL8 dfmax, const REAL8 Tsft, const REAL8 SFToverlap, const REAL8 Tobs, const UINT4 maxvectorlength, const UINT4 minTemplateLength, const UINT4 maxTemplateLength, const UINT4 vectormathflag, const BOOLEAN exactflag)
Generate a TwoSpectTemplateVector containing the template data.
Definition: templates.c:156
void resetTwoSpectTemplate(TwoSpectTemplate *template)
Reset the values in a TwoSpectTemplate.
Definition: templates.c:60
TwoSpectTemplateVector * createTwoSpectTemplateVector(const UINT4 length, const UINT4 templateLength)
Create a TwoSpectTemplateVector.
Definition: templates.c:94
INT4 makeTemplate2(TwoSpectTemplate *output, const REAL8 offset, const REAL8 P, const REAL8 deltaf, const REAL8 Tsft, const REAL8 SFToverlap, const REAL8 Tobs, const UINT4 minTemplateLength, const UINT4 vectormathflag, const REAL4FFTPlan *plan)
Make an template based on FFT of sinc squared functions.
Definition: templates.c:771
TwoSpectTemplate * createTwoSpectTemplate(const UINT4 length)
Allocate a new TwoSpectTemplate.
Definition: templates.c:35
void destroyTwoSpectTemplateVector(TwoSpectTemplateVector *vector)
Free a TwoSpectTemplateVector.
Definition: templates.c:120
TwoSpectTemplateVector * readTwoSpectTemplateVector(const CHAR *filename)
Read a TwoSpectTemplateVector from a binary file.
Definition: templates.c:250
REAL8 sqsincxoverxsqminusone(const REAL8 x)
Calculate [sin(pi*x)/(pi*x)/(x^2-1)]^2.
Definition: templates.c:988
REAL8 sincxoverxsqminusone(const REAL8 x)
Calculate sin(pi*x)/(pi*x)/(x^2-1)
Definition: templates.c:963
void destroyTwoSpectTemplate(TwoSpectTemplate *template)
Free a TwoSpectTemplate.
Definition: templates.c:78
INT4 makeTemplateGaussians2(TwoSpectTemplate *output, const REAL8 offset, const REAL8 P, const REAL8 deltaf, const REAL8 Tsft, const REAL8 SFToverlap, const REAL8 Tobs, const UINT4 minTemplateLength, const UINT4 vectormathflag)
Make an estimated template based on FFT of train of Gaussians.
Definition: templates.c:374
INT4 convertTemplateForSpecificFbin(TwoSpectTemplate *output, const TwoSpectTemplate *input, const REAL8 freq, const UserInput_t *params)
Convert an arbitrary frequency bin template into a template for a specific frequency bin.
Definition: templates.c:330
INT4 makeTemplateGaussians(TwoSpectTemplate *output, const candidate input, const UserInput_t *params)
Make an estimated template based on FFT of train of Gaussians.
Definition: templates.c:289
INT4 VectorAbsREAL4(REAL4VectorAligned *output, REAL4VectorAligned *input, INT4 vectorMath)
Definition: vectormath.c:427
INT4 VectorShiftREAL8(alignedREAL8Vector *output, alignedREAL8Vector *input, REAL8 shift, INT4 vectorMath)
Definition: vectormath.c:269
void destroyAlignedREAL8Vector(alignedREAL8Vector *vector)
Definition: vectormath.c:67
REAL4VectorAlignedArray * createREAL4VectorAlignedArray(const UINT4 length, const UINT4 vectorLength, const size_t align)
Definition: vectormath.c:99
void destroyREAL4VectorAlignedArray(REAL4VectorAlignedArray *array)
Definition: vectormath.c:110
alignedREAL8Vector * createAlignedREAL8Vector(UINT4 length, const size_t align)
Definition: vectormath.c:55