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
CWMakeFakeData.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2013 Reinhard Prix
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
21/**
22 * \author Reinhard Prix
23 * \ingroup CWMakeFakeData_h
24 * \brief Functions to generate 'fake' data containing CW signals and/or Gaussian noise.
25 * These basically present a high-level wrapper API to the lower-level CW signal-generation
26 * functions in lalsuite.
27 */
28
29// ---------- includes
30#include <math.h>
31
32// GSL includes
33
34// LAL includes
35#include <lal/CWMakeFakeData.h>
36#include <lal/TimeSeries.h>
37#include <lal/GeneratePulsarSignal.h>
38#include <lal/TransientCW_utils.h>
39#include <lal/LALString.h>
40#include <lal/StringVector.h>
41#include <lal/Units.h>
42#include <lal/ConfigFile.h>
43#include <lal/LFTandTSutils.h>
44#include <fftw3.h>
45#include <lal/FFTWMutex.h>
46#include <lal/ExtrapolatePulsarSpins.h>
47#include <lal/ConfigFile.h>
48
49// ---------- local defines
50
51// ---------- local macro definitions
52#define SQ(x) ( (x) * (x) )
53// ---------- local type definitions
54
55// ---------- Global variables
56const REAL8 eps = 10 * LAL_REAL8_EPS;
57
58const char *const InjectionSourcesHelpString = "Source parameters to inject for simulated signal(s).\n"
59 "This is a comma-separated list of file patterns for configuration files,\n"
60 "or else direct configuration strings in the following format:\n"
61 " * Enclose with curly braces ('{}').\n"
62 " * Give pulsar parameters as key=value pairs with a '=' separator.\n"
63 " * Separate each key=value pair with a semicolon (';').\n"
64 "Available parameters are:\n"
65 " * Required parameters: Alpha, Delta, Freq, refTime\n"
66 " * Optional parameters:\n"
67 " - Injection amplitudes: either (h0, cosi) or (aPlus, aCross), psi, phi0\n"
68 " - Higher-order spindowns: f1dot, f2dot, ... f6dot\n"
69 " - Binary sources: orbitTp, orbitArgp, orbitasini, orbitEcc, orbitPeriod\n"
70 " - Transient injections: transientWindowType, transientStartTime, transientTau\n"
71 "Examples:\n"
72 " * '{Alpha=0; Delta=0; Freq=50; f1dot=1e-11; f2dot=0; refTime=1000000000; h0=1.00000000e-23; cosi=0; psi=0; phi0=0;}'\n"
73 " * 'file1.dat,someFiles*.txt,{Alpha=0;Delta=0;Freq=0;refTime=1000000000;},someOtherFiles[0-9].dat'\n\n";
74
75// ---------- local prototypes
76static UINT4 gcd( UINT4 numer, UINT4 denom );
77int XLALcorrect_phase( SFTtype *sft, LIGOTimeGPS tHeterodyne );
78int XLALCheckConfigFileWasFullyParsed( const char *fname, const LALParsedDataFile *cfgdata );
79
80// ==================== FUNCTION DEFINITIONS ====================
81
82/// \addtogroup CWMakeFakeData_h
83/// @{
84
85/**
86 * Generate fake 'CW' data, returned either as SFTVector or REAL4Timeseries or both,
87 * for given CW-signal ("pulsar") parameters and output parameters (frequency band etc)
88 */
89int
90XLALCWMakeFakeMultiData( MultiSFTVector **multiSFTs, ///< [out] pointer to optional SFT-vector for output
91 MultiREAL8TimeSeries **multiTseries, ///< [out] pointer to optional timeseries-vector for output
92 const PulsarParamsVector *injectionSources, ///< [in] (optional) array of sources inject
93 const CWMFDataParams *dataParams, ///< [in] parameters specifying the type of data to generate
94 const EphemerisData *edat ///< [in] ephemeris data
95 )
96{
97 XLAL_CHECK( ( multiSFTs == NULL ) || ( ( *multiSFTs ) == NULL ), XLAL_EINVAL );
98 XLAL_CHECK( ( multiTseries == NULL ) || ( ( *multiTseries ) == NULL ), XLAL_EINVAL );
99 XLAL_CHECK( ( multiSFTs != NULL ) || ( multiTseries != NULL ), XLAL_EINVAL );
100
102 XLAL_CHECK( edat != NULL, XLAL_EINVAL );
103
104 const MultiLIGOTimeGPSVector *multiTimestamps = dataParams->multiTimestamps;
105
106 // check multi-detector input
107 XLAL_CHECK( dataParams->multiIFO.length >= 1, XLAL_EINVAL );
108 UINT4 numDet = dataParams->multiIFO.length;
109 XLAL_CHECK( multiTimestamps->length == numDet, XLAL_EINVAL, "Inconsistent number of IFOs: detInfo says '%d', multiTimestamps says '%d'\n", numDet, multiTimestamps->length );
110 XLAL_CHECK( dataParams->multiNoiseFloor.length == numDet, XLAL_EINVAL );
111
112 // check Tsft, consistent over detectors
113 REAL8 Tsft = multiTimestamps->data[0]->deltaT;
114 XLAL_CHECK( Tsft > 0, XLAL_EINVAL, "Got invalid Tsft = %g must be > 0\n", Tsft );
115 for ( UINT4 X = 0; X < numDet; X ++ ) {
116 XLAL_CHECK( multiTimestamps->data[X]->deltaT == Tsft, XLAL_EINVAL, "Inconsistent Tsft, for Tsft[X=0]=%g, while Tsft[X=%d]=%g\n", Tsft, X, multiTimestamps->data[X]->deltaT );
117 }
118
119 // ----- prepare output containers, as required
120 MultiSFTVector *outMSFTs = NULL;
121 MultiREAL8TimeSeries *outMTS = NULL;
122 if ( multiSFTs != NULL ) {
123 XLAL_CHECK( ( outMSFTs = XLALCalloc( 1, sizeof( *outMSFTs ) ) ) != NULL, XLAL_ENOMEM );
124 XLAL_CHECK( ( outMSFTs->data = XLALCalloc( numDet, sizeof( outMSFTs->data[0] ) ) ) != NULL, XLAL_ENOMEM );
125 outMSFTs->length = numDet;
126 } // if multiSFTs
127 if ( multiTseries != NULL ) {
128 XLAL_CHECK( ( outMTS = XLALCalloc( 1, sizeof( *outMTS ) ) ) != NULL, XLAL_ENOMEM );
129 XLAL_CHECK( ( outMTS->data = XLALCalloc( numDet, sizeof( outMTS->data[0] ) ) ) != NULL, XLAL_ENOMEM );
130 outMTS->length = numDet;
131 } // if multiTseries
132
133 for ( UINT4 X = 0; X < numDet; X ++ ) {
134 SFTVector **svp = NULL;
135 REAL8TimeSeries **tsp = NULL;
136 if ( outMSFTs != NULL ) {
137 svp = &( outMSFTs->data[X] );
138 }
139 if ( outMTS != NULL ) {
140 tsp = &( outMTS->data[X] );
141 }
143
144 } // for X < numDet
145
146 // return multi-Timeseries if requested
147 if ( multiTseries ) {
148 ( *multiTseries ) = outMTS;
149 }
150 // return multi-SFTs if requested
151 if ( multiSFTs ) {
152 ( *multiSFTs ) = outMSFTs;
153 }
154
155 return XLAL_SUCCESS;
156
157} // XLALCWMakeFakeMultiData()
158
159/**
160 * Single-IFO version of XLALCWMakeFakeMultiData(), handling the actual
161 * work, but same input API. The 'detectorIndex' has the index of the detector
162 * to be used from the multi-IFO arrays.
163 */
164int
166 REAL8TimeSeries **Tseries,
169 UINT4 detectorIndex, /* index for current detector in dataParams */
170 const EphemerisData *edat
171 )
172{
173 XLAL_CHECK( ( SFTvect == NULL ) || ( ( *SFTvect ) == NULL ), XLAL_EINVAL );
174 XLAL_CHECK( ( Tseries == NULL ) || ( ( *Tseries ) == NULL ), XLAL_EINVAL );
175 XLAL_CHECK( ( SFTvect != NULL ) || ( Tseries != NULL ), XLAL_EINVAL );
176 XLAL_CHECK( edat != NULL, XLAL_EINVAL );
177
179 XLAL_CHECK( detectorIndex < dataParams->multiIFO.length, XLAL_EINVAL );
180 XLAL_CHECK( detectorIndex < dataParams->multiNoiseFloor.length, XLAL_EINVAL );
181 XLAL_CHECK( detectorIndex < dataParams->multiTimestamps->length, XLAL_EINVAL );
182 XLAL_CHECK( ( dataParams->inputMultiTS == NULL ) || ( detectorIndex < dataParams->inputMultiTS->length ), XLAL_EINVAL );
183
184 // initial default values fMin, sampling rate from caller input or timeseries
185 REAL8 fMin = dataParams->fMin;
186 REAL8 fBand = dataParams->Band;
187 REAL8 fSamp = 2.0 * fBand;
188 if ( dataParams->inputMultiTS != NULL ) {
189 const REAL8TimeSeries *ts = dataParams->inputMultiTS->data[detectorIndex];
190 XLAL_CHECK( ts != NULL, XLAL_EINVAL );
191 REAL8 dt = ts->deltaT;
192 fMin = ts->f0;
193 fSamp = 1.0 / dt;
194 fBand = 0.5 * fSamp;
195 XLAL_CHECK( ( dataParams->fMin >= fMin ) && ( dataParams->fMin + dataParams->Band <= fMin + fBand ), XLAL_EINVAL, "Requested fMin=%f and fBand=%f are not covered by what the input timeseries can provide (fMin=%f, fBand=%f).", dataParams->fMin, dataParams->Band, fMin, fBand );
196 }
197
198 const LIGOTimeGPSVector *timestamps = dataParams->multiTimestamps->data[detectorIndex];
199 const LALDetector *site = &dataParams->multiIFO.sites[detectorIndex];
201
202 // if SFT output requested: need *effective* fMin and Band consistent with SFT bins
203 // Note: this band is only used for internal data operations; ultimately SFTs covering
204 // the half-open interval dataParams->[fMin,fMin+Band) are returned to the user using
205 // XLALExtractStrictBandFromSFTVector()
206 if ( SFTvect != NULL ) {
207 UINT4 firstBinEff, numBinsEff;
208 XLAL_CHECK( XLALFindCoveringSFTBins( &firstBinEff, &numBinsEff, fMin, fBand, Tsft ) == XLAL_SUCCESS, XLAL_EFUNC );
209
210 REAL8 fBand_eff = ( numBinsEff - 1.0 ) / Tsft;
211 REAL8 fMin_eff = firstBinEff / Tsft;
212 REAL8 fMax = fMin + dataParams->Band;
213 REAL8 fMax_eff = fMin_eff + fBand_eff;
214 if ( ( fMin_eff != fMin ) || ( fBand_eff != fBand ) ) {
215 XLALPrintWarning( "Caller asked for Band [%.16g, %.16g] Hz, effective SFT-Band produced is [%.16g, %.16g] Hz\n",
216 fMin, fMax, fMin_eff, fMax_eff );
217 XLAL_CHECK( dataParams->inputMultiTS == NULL, XLAL_EINVAL, "Cannot expand effective frequency band with input timeseries given. Timeseries seems inconsistent with SFTs\n" );
218 fMin = fMin_eff; // (potentially) lower minimal frequency to fit SFT bins
219 fBand = fBand_eff;
220 fSamp = 2.0 * fBand_eff; // (potentially) higher sampling rate required to fit SFT bins
221 } // if (fMin_eff != fMin) || (fBand_eff != fBand)
222 } // if SFT-output requested
223
224 // characterize the output time-series
225 UINT4 n0_fSamp = ( UINT4 ) round( Tsft * fSamp );
226
227 // by construction, fSamp * Tsft = integer, but if there are gaps between SFTs,
228 // then we might have to sample at higher rates in order for all SFT-boundaries to
229 // fall on exact timesteps of the timeseries.
230 // ie we start from fsamp0 = n0_fSamp/Tsft, and then try to find the smallest
231 // n1_fSamp >= n0_fSamp, such that for fsamp1 = n1_fSamp/Tsft, for all gaps i: Dt_i * fsamp1 = int
232 UINT4 n1_fSamp;
234
235 if ( ( SFTvect != NULL ) && ( n1_fSamp != n0_fSamp ) ) {
236 REAL8 fSamp1 = n1_fSamp / Tsft; // increased sampling rate to fit all gaps
237 XLALPrintWarning( "GAPS: Initial SFT sampling frequency fSamp0= %d/%.0f = %g had to be increased to fSamp1 = %d/%.0f = %g\n",
238 n0_fSamp, Tsft, fSamp, n1_fSamp, Tsft, fSamp1 );
239 XLAL_CHECK( dataParams->inputMultiTS == NULL, XLAL_EINVAL, "Cannot expand effective frequency band with input timeseries given. Timeseries seems inconsistent with SFT timestamps\n" );
240 fSamp = fSamp1;
241 } // if higher effective sampling rate required
242
243 // ----- start-time and duration -----
244 LIGOTimeGPS XLAL_INIT_DECL( firstGPS );
245 LIGOTimeGPS XLAL_INIT_DECL( lastGPS );
247 // NOTE: use time-interval of timeseries (if given) otherwise timestamps (must be subset of timeseries)
248 if ( dataParams->inputMultiTS != NULL ) {
249 const REAL8TimeSeries *ts = dataParams->inputMultiTS->data[detectorIndex];
250 XLAL_CHECK( ts != NULL, XLAL_EINVAL );
251 firstGPS = ts->epoch;
252 duration = ts->data->length * ts->deltaT;
253 lastGPS = firstGPS;
254 XLALGPSAdd( &lastGPS, duration );
255 } else { // use input timestamps
256 firstGPS = timestamps->data[0];
257 lastGPS = timestamps->data [ timestamps->length - 1 ];
258 XLALGPSAdd( &lastGPS, Tsft );
259 duration = XLALGPSDiff( &lastGPS, &firstGPS );
260 }
261 REAL8 firstGPS_REAL8 = XLALGPSGetREAL8( &firstGPS );
262 REAL8 lastGPS_REAL8 = XLALGPSGetREAL8( &lastGPS );
263
264 // start with an empty output time-series
265 REAL4TimeSeries *Tseries_sum;
266 {
267 REAL8 numSteps = ceil( fSamp * duration );
268 XLAL_CHECK( numSteps < ( REAL8 )LAL_UINT4_MAX, XLAL_EDOM, "Sorry, time-series of %g samples too long to fit into REAL4TimeSeries (maxLen = %g)\n", numSteps, ( REAL8 )LAL_UINT4_MAX );
269 REAL8 dt = 1.0 / fSamp;
270 REAL8 fHeterodyne = fMin; // heterodyne signals at lower end of frequency-band
271 CHAR *detPrefix = XLALGetChannelPrefix( site->frDetector.name );
272 XLAL_CHECK( ( Tseries_sum = XLALCreateREAL4TimeSeries( detPrefix, &firstGPS, fHeterodyne, dt, &lalStrainUnit, ( UINT4 )numSteps ) ) != NULL, XLAL_EFUNC );
273 memset( Tseries_sum->data->data, 0, Tseries_sum->data->length * sizeof( Tseries_sum->data->data[0] ) );
274 XLALFree( detPrefix );
275 } // generate empty timeseries
276
277 // add CW signals, if any
278 UINT4 numPulsars = injectionSources ? injectionSources->length : 0;
279 for ( UINT4 iInj = 0; iInj < numPulsars; iInj ++ ) {
280 // truncate any transient-CW timeseries to the actual support of the transient signal,
281 // in order to make the generation more efficient, these 'partial timeseries'
282 // will then be added to the full timeseries
283 const PulsarParams *pulsarParams = &( injectionSources->data[iInj] );
284 UINT4 t0, t1;
286
287 // use latest possible start-time: max(t0,firstGPS), but not later than than lastGPS
288 LIGOTimeGPS XLAL_INIT_DECL( signalStartGPS );
289 if ( t0 <= firstGPS_REAL8 ) {
290 signalStartGPS = firstGPS;
291 } else if ( t0 >= lastGPS_REAL8 ) {
292 signalStartGPS = lastGPS;
293 } else { // firstGPS < t0 < lastGPS:
294 // make sure signal start-time is an integer multiple of deltaT from timeseries start
295 // to allow safe adding of resulting signal timeseries
296 REAL8 offs0_aligned = round( ( t0 - firstGPS_REAL8 ) * fSamp ) / fSamp;
297 signalStartGPS = firstGPS;
298 XLALGPSAdd( &signalStartGPS, offs0_aligned );
299 }
300
301 // use earliest possible end-time: min(t1,lastGPS), but not earlier than firstGPS
302 LIGOTimeGPS XLAL_INIT_DECL( signalEndGPS );
303 if ( t1 >= lastGPS_REAL8 ) {
304 signalEndGPS = lastGPS;
305 } else if ( t1 <= firstGPS_REAL8 ) {
306 signalEndGPS = firstGPS;
307 } else {
308 signalEndGPS.gpsSeconds = t1;
309 }
310
311 REAL8 fCoverMin, fCoverMax;
312 const PulsarSpins *fkdot = &( pulsarParams->Doppler.fkdot );
313 PulsarSpinRange XLAL_INIT_DECL( spinRange );
314 spinRange.refTime = pulsarParams->Doppler.refTime;
315 memcpy( spinRange.fkdot, fkdot, sizeof( spinRange.fkdot ) );
316 XLAL_INIT_MEM( spinRange.fkdotBand );
317
318 XLAL_CHECK( XLALCWSignalCoveringBand( &fCoverMin, &fCoverMax, &signalStartGPS, &signalEndGPS, &spinRange, pulsarParams->Doppler.asini, pulsarParams->Doppler.period, pulsarParams->Doppler.ecc ) == XLAL_SUCCESS, XLAL_EFUNC );
319 XLAL_CHECK( ( fCoverMin >= fMin ) && ( fCoverMax < fMin + fBand ), XLAL_EINVAL, "Error: injection signal %d:'%s' needs frequency band [%f,%f]Hz, injecting into [%f,%f]Hz\n",
320 iInj, pulsarParams->name, fCoverMin, fCoverMax, fMin, fMin + fBand );
321
322 REAL8 signalDuration = XLALGPSDiff( &signalEndGPS, &signalStartGPS );
323 XLAL_CHECK( signalDuration >= 0, XLAL_EFAILED, "Something went wrong, got negative signal duration = %g\n", signalDuration );
324 if ( signalDuration > 0 ) { // only need to do sth if transient-window had finite overlap with output TS
325 REAL4TimeSeries *Tseries_i = NULL;
326 XLAL_CHECK( ( Tseries_i = XLALGenerateCWSignalTS( pulsarParams, site, signalStartGPS, signalDuration, fSamp, fMin, edat, dataParams->sourceDeltaT ) ) != NULL, XLAL_EFUNC );
327
328 // since XLALAddREAL4TimeSeries() does not enforce strict sample alignment,
329 // we do our own safety check here
330 REAL8 Delta_epoch = XLALGPSDiff( &Tseries_sum->epoch, &Tseries_i->epoch );
331 REAL8 bin_mismatch = fabs( Delta_epoch / Tseries_sum->deltaT );
332 REAL8 mismatch = fabs( bin_mismatch - round( bin_mismatch ) ) * Tseries_sum->deltaT;
333 XLAL_CHECK( mismatch <= 1e-9, XLAL_EDATA, "Incompatible start-times when adding signal time series %d of %d, bins misaligned by %g seconds (%g bins).\n", iInj, numPulsars, mismatch, bin_mismatch );
334
335 XLAL_CHECK( ( Tseries_sum = XLALAddREAL4TimeSeries( Tseries_sum, Tseries_i ) ) != NULL, XLAL_EFUNC );
336 XLALDestroyREAL4TimeSeries( Tseries_i );
337 }
338 } // for iInj < numSources
339
340 /* add Gaussian noise if requested */
341 REAL8 sqrtSn = dataParams->multiNoiseFloor.sqrtSn[detectorIndex];
342 if ( sqrtSn > 0 ) {
343 REAL8 noiseSigma = sqrtSn * sqrt( 0.5 * fSamp );
344 INT4 randSeed = ( dataParams->randSeed == 0 ) ? 0 : ( dataParams->randSeed + detectorIndex ); // seed=0 means to use /dev/urandom, so don't touch it
345 XLAL_CHECK( XLALAddGaussianNoise( Tseries_sum, noiseSigma, randSeed ) == XLAL_SUCCESS, XLAL_EFUNC );
346 }
347
348 // convert final signal+Gaussian-noise timeseries into REAL8 precision:
349 REAL8TimeSeries *outTS;
350 XLAL_CHECK( ( outTS = XLALConvertREAL4TimeSeriesToREAL8( Tseries_sum ) ) != NULL, XLAL_EFUNC );
351 XLALDestroyREAL4TimeSeries( Tseries_sum );
352
353 // add input noise time-series here if given
354 if ( dataParams->inputMultiTS != NULL ) {
355 // since XLALAddREAL8TimeSeries() does not enforce strict sample alignment,
356 // we do our own safety check here
357 REAL8 Delta_epoch = XLALGPSDiff( &outTS->epoch, &dataParams->inputMultiTS->data[detectorIndex]->epoch );;
358 REAL8 bin_mismatch = fabs( Delta_epoch / outTS->deltaT );
359 REAL8 mismatch = fabs( bin_mismatch - round( bin_mismatch ) ) * outTS->deltaT;
360 XLAL_CHECK( mismatch <= 1e-9, XLAL_EDATA, "Incompatible start-times when adding input noise time-series, bins misaligned by %g seconds (%g bins).\n", mismatch, bin_mismatch );
361 XLAL_CHECK( ( outTS = XLALAddREAL8TimeSeries( outTS, dataParams->inputMultiTS->data[detectorIndex] ) ) != NULL, XLAL_EFUNC );
362 }
363
364 // turn final timeseries into SFTs, if requested
365 if ( SFTvect != NULL ) {
366 // compute SFTs from timeseries
367 SFTVector *sftVect;
368 XLAL_CHECK( ( sftVect = XLALMakeSFTsFromREAL8TimeSeries( outTS, timestamps, dataParams->SFTWindowType, dataParams->SFTWindowParam ) ) != NULL, XLAL_EFUNC );
369
370 // extract requested band
371 XLAL_CHECK( ( ( *SFTvect ) = XLALExtractStrictBandFromSFTVector( sftVect, dataParams->fMin, dataParams->Band ) ) != NULL, XLAL_EFUNC );
372 XLALDestroySFTVector( sftVect );
373 } // if SFTvect
374
375 // return timeseries if requested
376 if ( Tseries != NULL ) {
377 ( *Tseries ) = outTS;
378 } else {
380 }
381
382 return XLAL_SUCCESS;
383
384} // XLALCWMakeFakeData()
385
386
387/**
388 * Generate a (heterodyned) REAL4 timeseries of a CW signal for given pulsarParams,
389 * site, start-time, duration, and sampling-rate
390 *
391 * NOTE: this is mostly an API-wrapper to the more 'old-style' function
392 * XLALGeneratePulsarSignal() [which will become deprecated in the future],
393 * extended for the option to generate transient-CW signals
394 */
396XLALGenerateCWSignalTS( const PulsarParams *pulsarParams, ///< input CW pulsar-signal parameters
397 const LALDetector *site, ///< detector
398 LIGOTimeGPS startTime, ///< time-series start-time GPS
399 REAL8 duration, ///< time-series duration to generate
400 REAL8 fSamp, ///< sampling frequency
401 REAL8 fHet, ///< heterodyning frequency
402 const EphemerisData *edat, ///< ephemeris data
403 REAL8 sourceDeltaT ///< source-frame sampling period (optional: 0 == previous internal defaults)
404 )
405{
406 XLAL_CHECK_NULL( pulsarParams != NULL, XLAL_EINVAL );
407 XLAL_CHECK_NULL( site != NULL, XLAL_EINVAL );
409 XLAL_CHECK_NULL( fSamp > 0, XLAL_EDOM );
410 XLAL_CHECK_NULL( fHet >= 0, XLAL_EDOM );
411
412 // translate amplitude params
413 REAL8 aPlus = pulsarParams->Amp.aPlus;
414 REAL8 aCross = pulsarParams->Amp.aCross;
415 // translate 'modern' fkdot into 'old-style' spindown-vector
416 UINT4 s_max;
417 for ( s_max = PULSAR_MAX_SPINS - 1; s_max > 0; s_max -- ) {
418 if ( pulsarParams->Doppler.fkdot[s_max] != 0 ) {
419 break;
420 }
421 } // for s_max = max ... 0
422 REAL8Vector *spindown = NULL;
423 if ( s_max > 0 ) {
424 XLAL_CHECK_NULL( ( spindown = XLALCreateREAL8Vector( s_max ) ) != NULL, XLAL_EFUNC );
425 for ( UINT4 s = 0; s < s_max; s ++ ) {
426 spindown->data[s] = pulsarParams->Doppler.fkdot[s + 1];
427 }
428 }
429
430 /*----------------------------------------
431 * fill old-style PulsarSignalParams struct
432 *----------------------------------------*/
434 params.pulsar.refTime = pulsarParams->Doppler.refTime;
435 params.pulsar.position.system = COORDINATESYSTEM_EQUATORIAL;
436 params.pulsar.position.longitude = pulsarParams->Doppler.Alpha;
437 params.pulsar.position.latitude = pulsarParams->Doppler.Delta;
438 params.pulsar.aPlus = aPlus;
439 params.pulsar.aCross = aCross;
440 params.pulsar.phi0 = pulsarParams->Amp.phi0;
441 params.pulsar.psi = pulsarParams->Amp.psi;
442 params.pulsar.f0 = pulsarParams->Doppler.fkdot[0];
443 params.pulsar.spindown = spindown;
444 params.orbit.tp = pulsarParams->Doppler.tp;
445 params.orbit.argp = pulsarParams->Doppler.argp;
446 params.orbit.asini = pulsarParams->Doppler.asini;
447 params.orbit.ecc = pulsarParams->Doppler.ecc;
448 params.orbit.period = pulsarParams->Doppler.period;
449 params.transfer = NULL;
450 params.ephemerides = edat;
451 params.fHeterodyne = fHet;
452 params.sourceDeltaT = sourceDeltaT;
453
454 // detector-specific settings
455 params.startTimeGPS = startTime;
456 params.duration = ceil( duration );
457 params.samplingRate = fSamp;
458 params.site = site;
459
460 /*----------------------------------------
461 * generate the signal time-series
462 *----------------------------------------*/
463 REAL4TimeSeries *Tseries;
464 XLAL_CHECK_NULL( ( Tseries = XLALGeneratePulsarSignal( &params ) ) != NULL, XLAL_EFUNC );
465 // ----- free internal memory
466 XLALDestroyREAL8Vector( spindown );
467
468 // ----- apply transient-CW window
470
471 return Tseries;
472
473} // XLALGenerateCWSignalTS()
474
475
476///
477/// Make SFTs from given REAL8TimeSeries at given timestamps, potentially applying a time-domain window on each timestretch first
478///
479SFTVector *
480XLALMakeSFTsFromREAL8TimeSeries( const REAL8TimeSeries *timeseries, //!< input time-series
481 const LIGOTimeGPSVector *timestamps, //!< timestamps to produce SFTs for (can be NULL), if given must all lies within timeseries' time-span
482 const char *windowType, //!< optional time-domain window function to apply before FFTing
483 REAL8 windowParam //!< window parameter, if any
484 )
485{
486 XLAL_CHECK_NULL( timeseries != NULL, XLAL_EINVAL, "Invalid NULL input 'timeseries'\n" );
487 XLAL_CHECK_NULL( timestamps != NULL, XLAL_EINVAL, "Invalid NULL input 'timestamps'\n" );
488
489 REAL8 dt = timeseries->deltaT; // timeseries timestep */
491 REAL8 df = 1.0 / Tsft; // SFT frequency spacing
492
493 // make sure that number of timesamples/SFT is an integer (up to possible rounding error 'eps')
494 REAL8 timestepsSFT0 = Tsft / dt;
495 UINT4 timestepsSFT = lround( timestepsSFT0 );
496 XLAL_CHECK_NULL( fabs( timestepsSFT0 - timestepsSFT ) / timestepsSFT0 < eps, XLAL_ETOL,
497 "Inconsistent sampling-step (dt=%g) and Tsft=%g: must be integer multiple Tsft/dt = %g >= %g\n",
498 dt, Tsft, timestepsSFT0, eps );
499
500 // prepare window function if requested
501 REAL8Window *window = NULL;
502 if ( windowType != NULL ) {
503 XLAL_CHECK_NULL( ( window = XLALCreateNamedREAL8Window( windowType, windowParam, timestepsSFT ) ) != NULL, XLAL_EFUNC );
504 }
505
506 // ---------- Prepare FFT ----------
507 REAL8Vector *timeStretchCopy; // input array of length N
508 XLAL_CHECK_NULL( ( timeStretchCopy = XLALCreateREAL8Vector( timestepsSFT ) ) != NULL, XLAL_EFUNC, "XLALCreateREAL4Vector(%d) failed.\n", timestepsSFT );
509 UINT4 numSFTBins = timestepsSFT / 2 + 1; // number of positive frequency-bins + 'DC' to be stored in SFT
510 fftw_complex *fftOut; // output array of length N/2 + 1
511 XLAL_CHECK_NULL( ( fftOut = fftw_malloc( numSFTBins * sizeof( fftOut[0] ) ) ) != NULL, XLAL_ENOMEM, "fftw_malloc(%d*sizeof(complex)) failed\n", numSFTBins );
512 fftw_plan fftplan; // FFTW plan
514 XLAL_CHECK_NULL( ( fftplan = fftw_plan_dft_r2c_1d( timestepsSFT, timeStretchCopy->data, fftOut, FFTW_ESTIMATE ) ) != NULL, XLAL_EFUNC ); // FIXME: or try FFTW_MEASURE
516
517 LIGOTimeGPS tStart = timeseries->epoch;
518
519 // get last possible start-time for an SFT
520 REAL8 duration = round( timeseries->data->length * dt ); // rounded to seconds
521 LIGOTimeGPS tLast = tStart;
522 XLALGPSAdd( &tLast, duration - Tsft );
523
524 // check that all timestamps lie within [tStart, tLast]
525 for ( UINT4 i = 0; i < timestamps->length; i ++ ) {
526 char buf1[256], buf2[256];
527 XLAL_CHECK_NULL( XLALGPSDiff( &tStart, &( timestamps->data[i] ) ) <= 0, XLAL_EDOM, "Timestamp i=%d: %s before start-time %s\n",
528 i, XLALGPSToStr( buf1, &( timestamps->data[i] ) ), XLALGPSToStr( buf2, &tStart ) );
529 XLAL_CHECK_NULL( XLALGPSDiff( &tLast, &( timestamps->data[i] ) ) >= 0, XLAL_EDOM, "Timestamp i=%d: %s after last start-time %s\n",
530 i, XLALGPSToStr( buf1, &( timestamps->data[i] ) ), XLALGPSToStr( buf2, &tLast ) );
531 }
532
534
535 // prepare output SFT-vector
536 SFTVector *sftvect;
537 XLAL_CHECK_NULL( ( sftvect = XLALCreateSFTVector( numSFTs, numSFTBins ) ) != NULL, XLAL_EFUNC,
538 "XLALCreateSFTVector(numSFTs=%d, numBins=%d) failed.\n", numSFTs, numSFTBins );
539
540 // main loop: apply FFT to the requested time-stretches and store in output SFTs
541 for ( UINT4 iSFT = 0; iSFT < numSFTs; iSFT++ ) {
542 SFTtype *thisSFT = &( sftvect->data[iSFT] ); // point to current SFT-slot to store output in
543
544 // find the start-bin for this SFT in the time-series
545 REAL8 offset = XLALGPSDiff( &( timestamps->data[iSFT] ), &tStart );
546 INT4 offsetBins = lround( offset / dt );
547
548 // copy timeseries-data for that SFT into local buffer
549 memcpy( timeStretchCopy->data, timeseries->data->data + offsetBins, timeStretchCopy->length * sizeof( timeStretchCopy->data[0] ) );
550
551 // window the current time series stretch if required
552 REAL8 sigma_window = 1;
553 if ( window != NULL ) {
554 sigma_window = sqrt( window->sumofsquares / window->data->length );
555 for ( UINT4 iBin = 0; iBin < timeStretchCopy->length; iBin++ ) {
556 timeStretchCopy->data[iBin] *= window->data->data[iBin];
557 }
558 } // if window
559
560 // FFT this time-stretch
561 fftw_execute( fftplan );
562
563 // fill the header of the i'th output SFT */
564 strcpy( thisSFT->name, timeseries->name );
565 thisSFT->epoch = timestamps->data[iSFT];
566 thisSFT->f0 = timeseries->f0; // SFT starts at heterodyning frequency
567 thisSFT->deltaF = df;
568
569 // normalize DFT-data to conform to SFT specification ==> multiply DFT by (dt/sigma{window})
570 // the SFT normalization in case of windowing follows the conventions detailed in \cite SFT-spec
571 REAL8 norm = dt / sigma_window;
572 for ( UINT4 k = 0; k < numSFTBins ; k ++ ) {
573 thisSFT->data->data[k] = ( COMPLEX8 )( norm * fftOut[k] );
574 }
575
576 // correct heterodyning-phase, IF NECESSARY: ie if (fHet * tStart) is not an integer, such that phase-corr = multiple of 2pi
577 if ( ( ( INT4 )timeseries->f0 != timeseries->f0 ) || ( timeseries->epoch.gpsNanoSeconds != 0 ) || ( thisSFT->epoch.gpsNanoSeconds != 0 ) ) {
578 XLAL_CHECK_NULL( XLALcorrect_phase( thisSFT, timeseries->epoch ) == XLAL_SUCCESS, XLAL_EFUNC );
579 }
580
581 } // for iSFT < numSFTs
582
583 // free memory
584 fftw_free( fftOut );
586 fftw_destroy_plan( fftplan );
588 XLALDestroyREAL8Vector( timeStretchCopy );
589 XLALDestroyREAL8Window( window );
590
591 return sftvect;
592
593} // XLALMakeSFTsFromREAL8TimeSeries()
594
595
596
597/**
598 * Find the smallest sampling rate of the form fsamp = n / Tsft, with n>=n0,
599 * such that all gap sizes Dt_i between SFTs of the given timestamps are also
600 * exactly resolved, ie. that Dt_i * fsamp = integer, for all i
601 *
602 * The smallest allowed sampling rate is the user-specified fsamp0 = n0 / Tsft,
603 * which guarantees by construction that fSamp0 * Tsft = n0 = integer
604 * This sampling rate would be valid if there are no gaps between SFTs,
605 * so it's only in cases of gaps that are non-integer multiples of Tsft that we'll
606 * (potentially) have to increase the sampling rate.
607 *
608 * NOTE: This approach replaces the old mfdv4 habit of 'nudging' noise SFTs start-times
609 * to fall on integer timesteps of the fsamp0 timeseries. The purpose of this function
610 * is to avoid this behaviour, by appropriately increasing the sampling rate
611 * as required.
612 *
613 * NOTE2: we only allow integer-second gaps, everything else will be
614 * rejected with an error-message.
615 *
616 * NOTE3: Tsft=timestamps->deltaT must be integer seconds, everything else is rejected
617 * with an error as well
618 */
619int
620XLALFindSmallestValidSamplingRate( UINT4 *n1, //< [out] minimal valid sampling rate n1/Tsft
621 UINT4 n0, //< [in] minimal sampling rate n0/Tsft
622 const LIGOTimeGPSVector *timestamps //< [in] start-timestamps and length Tsft of SFTs
623 )
624{
625 XLAL_CHECK( n1 != NULL, XLAL_EINVAL );
626 XLAL_CHECK( n0 > 0, XLAL_EINVAL );
628 REAL8 TsftREAL = timestamps->deltaT;
629 XLAL_CHECK( TsftREAL == round( TsftREAL ), XLAL_EDOM, "Only exact integer-second Tsft allowed, got Tsft = %.16g s\n", TsftREAL );
630 UINT4 Tsft = ( UINT4 )TsftREAL;
632
633 // NOTE: all 'valid' sampling rates are of the form fSamp = n / Tsft, where n >= n0,
634 // therefore we label sampling rates by their index 'n'. The purpose is to find the
635 // smallest 'valid' n, which is the max of the required 'n' over all gaps
636 UINT4 nCur = n0;
637
638 // ----- We just step through the vector and figure out for each gap if we need to
639 // decrease the stepsize Tsft/n from the previous value
641
642 for ( UINT4 i = 1; i < numSFTs; i ++ ) {
643 LIGOTimeGPS *t1 = &( timestamps->data[i] );
644 LIGOTimeGPS *t0 = &( timestamps->data[i - 1] );
645
646 INT4 nsdiff = t1->gpsNanoSeconds - t0->gpsNanoSeconds;
647 XLAL_CHECK( nsdiff == 0, XLAL_EDOM, "Only integer-second gaps allowed, found %d ns excess in gap between i=%d and i-1\n", nsdiff, i );
648
649 INT4 gap_i0 = t1->gpsSeconds - t0->gpsSeconds;
650 XLAL_CHECK( gap_i0 > 0, XLAL_EDOM, "Timestamps must be sorted in increasing order, found negative gap %d s between i=%d and i-1\n", gap_i0, i );
651
652 // now reduce gap to remainder wrt Tsft
653 INT4 gap_i = gap_i0 % Tsft;
654
655 if ( ( ( INT8 )gap_i * nCur ) % Tsft == 0 ) {
656 continue;
657 }
658
659 // otherwise:
660 // solve for required new smaller step-size 'dt = Tsft/nNew' to fit integer cycles
661 // both into Tsft (by construction) and into (gap_i mod Tsft), with nNew > nCur
662 //
663 // gap[i] == (t[i+1] - t[i]) mod Tsft
664 // such that 0 <= gap[i] < Tsft
665 // we want integers nNew, m , such that nNew > nCur, and m < nNew, with
666 // nNew * dtNew = Tsft AND m * dtNew = gap[i]
667 // ==> m / nNew = gap[i] / Tsft
668 // This could be solved easily by rounding nCur to next highest
669 // multiple of Tsft: nNew' = ceil(nCur/Tsft) * Tsft > nCur
670 // but this can be wasteful if the fraction simplifies: so we compute
671 // the greatest common divisor 'g'
672 // g = gcd(gap[i], Tsft), and then use
673 // nNew = ceil ( nCur * g / Tsft ) * Tsft / g > nCur
674
675 UINT4 g = gcd( gap_i, Tsft );
676 REAL8 Tg = TsftREAL / g;
677 UINT4 nNew = ( UINT4 ) ceil( nCur / Tg ) * Tg;
678
679 XLAL_CHECK( nNew > nCur, XLAL_ETOL, "This seems wrong: nNew = %d !> nCur = %d, but should be greater!\n", nNew, nCur );
680 XLALPrintInfo( "Need to increase from fSamp = %d/Tsft = %g to fSamp = %d / Tsft = %g\n", nCur, nCur / TsftREAL, nNew, nNew / TsftREAL );
681
682 nCur = nNew;
683
684 } // for i < numSFTs
685
686
687 // our final minimal valid sampling rate is therefore n1/Tsft
688 ( *n1 ) = nCur;
689
690 return XLAL_SUCCESS;
691
692} // XLALFindSmallestValidSamplingRate()
693
694
695/* Find greatest common divisor between two numbers,
696 * where numer <= denom
697 * this is an implementation of the Euclidean Algorithm,
698 * taken from John's UnitNormalize.c, and extended to UINT4's
699 *
700 * For reference, see also
701 * https://en.wikipedia.org/wiki/Euclidean_algorithm#Implementations
702 */
703static UINT4
705{
706 UINT4 next_numer, next_denom, rmdr;
707
708 next_numer = numer;
709 next_denom = denom;
710 while ( next_denom != 0 ) {
711 rmdr = next_numer % next_denom;
712 next_numer = next_denom;
713 next_denom = rmdr;
714 }
715 return next_numer;
716} // gcd
717
718/**
719 * Create *zero-initialized* PulsarParamsVector for numPulsars
720 */
723{
725 XLAL_CHECK_NULL( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_ENOMEM );
726
727 ret->length = numPulsars;
728 if ( numPulsars > 0 ) {
729 XLAL_CHECK_NULL( ( ret->data = XLALCalloc( numPulsars, sizeof( ret->data[0] ) ) ) != NULL, XLAL_ENOMEM );
730 }
731
732 return ret;
733
734} // XLALCreatePulsarParamsVector()
735
736/**
737 * Destructor for PulsarParamsVector type
738 */
739void
741{
742 if ( ppvect == NULL ) {
743 return;
744 }
745
746 if ( ppvect->data != NULL ) {
747 XLALFree( ppvect->data );
748 }
749
750 XLALFree( ppvect );
751
752 return;
753} // XLALDestroyPulsarParamsVector()
754
755
756/**
757 * Function to parse a config-file-type string (or section thereof)
758 * into a PulsarParams struct.
759 *
760 * NOTE: The section-name is optional, and can be given as NULL,
761 * in which case the top of the file (ie the "default section")
762 * is used.
763 *
764 * NOTE2: eventually ATNF/TEMPO2-style 'par-file' variables will also
765 * be understood by this function, but we start out with a simpler version
766 * that just deals with our 'CW-style' input variable for now
767 *
768 * NOTE3: The config-file must be of a special "SourceParamsIO" form,
769 * defining the following required and optional parameters:
770 *
771 * REQUIRED:
772 * Alpha, Delta, Freq, refTime (unless refTimeDef != NULL)
773 *
774 * OPTIONAL:
775 * f1dot, f2dot, f3dot, f4dot, f5dot, f6dot
776 * {h0, cosi} or {aPlus, aCross}, psi, phi0
777 * transientWindowType, transientStartTime, transientTau
778 *
779 * Other config-variables found in the file will ... ?? error or accept?
780 */
781int
782XLALReadPulsarParams( PulsarParams *pulsarParams, ///< [out] pulsar parameters to fill in from config string
783 LALParsedDataFile *cfgdata, ///< [in] pre-parsed "SourceParamsIO" config-file contents
784 const CHAR *secName, ///< [in] section-name to use from config-file string (can be NULL)
785 const LIGOTimeGPS *refTimeDef ///< [in] default reference time if refTime is not given
786 )
787{
788 XLAL_CHECK( pulsarParams != NULL, XLAL_EINVAL );
789 XLAL_CHECK( cfgdata != NULL, XLAL_EINVAL );
790
791 XLAL_INIT_MEM( ( *pulsarParams ) ); // wipe input struct clean
792
793 // ---------- PulsarAmplitudeParams ----------
794 // ----- h0, cosi
795 REAL8 h0 = 0;
796 BOOLEAN have_h0;
797 REAL8 cosi = 0;
798 BOOLEAN have_cosi;
799 XLAL_CHECK( XLALReadConfigREAL8Variable( &h0, cfgdata, secName, "h0", &have_h0 ) == XLAL_SUCCESS, XLAL_EFUNC );
800 XLAL_CHECK( XLALReadConfigREAL8Variable( &cosi, cfgdata, secName, "cosi", &have_cosi ) == XLAL_SUCCESS, XLAL_EFUNC );
801 // ----- ALTERNATIVE: aPlus, aCross
802 REAL8 aPlus = 0;
803 BOOLEAN have_aPlus;
804 REAL8 aCross = 0;
805 BOOLEAN have_aCross;
806 XLAL_CHECK( XLALReadConfigREAL8Variable( &aPlus, cfgdata, secName, "aPlus", &have_aPlus ) == XLAL_SUCCESS, XLAL_EFUNC );
807 XLAL_CHECK( XLALReadConfigREAL8Variable( &aCross, cfgdata, secName, "aCross", &have_aCross ) == XLAL_SUCCESS, XLAL_EFUNC );
808
809 // if h0 then also need cosi, and vice-versa
810 XLAL_CHECK( ( have_h0 && have_cosi ) || ( !have_h0 && !have_cosi ), XLAL_EINVAL );
811 // if aPlus then also need aCross, and vice-versa
812 XLAL_CHECK( ( have_aPlus && have_aCross ) || ( !have_aPlus && !have_aCross ), XLAL_EINVAL );
813 // {h0,cosi} or {aPlus, aCross} mutually exclusive sets
814 XLAL_CHECK( !( have_h0 && have_aPlus ), XLAL_EINVAL );
815
816 if ( have_h0 ) { /* translate {h_0, cosi} into A_{+,x}*/
817 XLAL_CHECK( h0 >= 0, XLAL_EDOM );
818 XLAL_CHECK( ( cosi >= -1 ) && ( cosi <= 1 ), XLAL_EDOM );
819 aPlus = 0.5 * h0 * ( 1.0 + SQ( cosi ) );
820 aCross = h0 * cosi;
821 } //if {h0, cosi}
822 pulsarParams->Amp.aPlus = aPlus;
823 pulsarParams->Amp.aCross = aCross;
824
825 // ----- psi
826 REAL8 psi = 0;
827 BOOLEAN have_psi;
828 XLAL_CHECK( XLALReadConfigREAL8Variable( &psi, cfgdata, secName, "psi", &have_psi ) == XLAL_SUCCESS, XLAL_EFUNC );
829 pulsarParams->Amp.psi = psi;
830
831 // ----- phi0
832 REAL8 phi0 = 0;
833 BOOLEAN have_phi0;
834 XLAL_CHECK( XLALReadConfigREAL8Variable( &phi0, cfgdata, secName, "phi0", &have_phi0 ) == XLAL_SUCCESS, XLAL_EFUNC );
835 pulsarParams->Amp.phi0 = phi0;
836
837 // ---------- PulsarDopplerParams ----------
838
839 // ----- refTime
840 LIGOTimeGPS refTime_GPS;
841 BOOLEAN have_refTime;
842 XLAL_CHECK( XLALReadConfigEPOCHVariable( &refTime_GPS, cfgdata, secName, "refTime", &have_refTime ) == XLAL_SUCCESS, XLAL_EFUNC );
843 if ( have_refTime ) {
844 pulsarParams->Doppler.refTime = refTime_GPS;
845 } else if ( refTimeDef != NULL ) {
846 pulsarParams->Doppler.refTime = *refTimeDef;
847 } else {
848 XLAL_ERROR( XLAL_EINVAL, "missing value refTime, and no default is available" );
849 }
850
851 // ----- Alpha
852 REAL8 Alpha_Rad = 0;
853 BOOLEAN have_Alpha;
854 XLAL_CHECK( XLALReadConfigRAJVariable( &Alpha_Rad, cfgdata, secName, "Alpha", &have_Alpha ) == XLAL_SUCCESS, XLAL_EFUNC );
855 XLAL_CHECK( have_Alpha, XLAL_EINVAL, "missing required value Alpha" );
856
857 XLAL_CHECK( ( Alpha_Rad >= 0 ) && ( Alpha_Rad < LAL_TWOPI ), XLAL_EDOM );
858 pulsarParams->Doppler.Alpha = Alpha_Rad;
859
860 // ----- Delta
861 REAL8 Delta_Rad = 0;
862 BOOLEAN have_Delta;
863 XLAL_CHECK( XLALReadConfigDECJVariable( &Delta_Rad, cfgdata, secName, "Delta", &have_Delta ) == XLAL_SUCCESS, XLAL_EFUNC );
864 XLAL_CHECK( have_Delta, XLAL_EINVAL, "missing required value Delta" );
865
866 XLAL_CHECK( ( Delta_Rad >= -LAL_PI_2 ) && ( Delta_Rad <= LAL_PI_2 ), XLAL_EDOM );
867 pulsarParams->Doppler.Delta = Delta_Rad;
868
869 // ----- fkdot
870 // Freq
871 REAL8 Freq = 0;
872 BOOLEAN have_Freq;
873 XLAL_CHECK( XLALReadConfigREAL8Variable( &Freq, cfgdata, secName, "Freq", &have_Freq ) == XLAL_SUCCESS, XLAL_EFUNC );
874 XLAL_CHECK( have_Freq, XLAL_EINVAL, "missing required value Freq" );
875
876 XLAL_CHECK( Freq > 0, XLAL_EDOM );
877 pulsarParams->Doppler.fkdot[0] = Freq;
878
879 // f1dot
880 REAL8 f1dot = 0;
881 BOOLEAN have_f1dot;
882 XLAL_CHECK( XLALReadConfigREAL8Variable( &f1dot, cfgdata, secName, "f1dot", &have_f1dot ) == XLAL_SUCCESS, XLAL_EFUNC );
883 pulsarParams->Doppler.fkdot[1] = f1dot;
884 // f2dot
885 REAL8 f2dot = 0;
886 BOOLEAN have_f2dot;
887 XLAL_CHECK( XLALReadConfigREAL8Variable( &f2dot, cfgdata, secName, "f2dot", &have_f2dot ) == XLAL_SUCCESS, XLAL_EFUNC );
888 pulsarParams->Doppler.fkdot[2] = f2dot;
889 // f3dot
890 REAL8 f3dot = 0;
891 BOOLEAN have_f3dot;
892 XLAL_CHECK( XLALReadConfigREAL8Variable( &f3dot, cfgdata, secName, "f3dot", &have_f3dot ) == XLAL_SUCCESS, XLAL_EFUNC );
893 pulsarParams->Doppler.fkdot[3] = f3dot;
894 // f4dot
895 REAL8 f4dot = 0;
896 BOOLEAN have_f4dot;
897 XLAL_CHECK( XLALReadConfigREAL8Variable( &f4dot, cfgdata, secName, "f4dot", &have_f4dot ) == XLAL_SUCCESS, XLAL_EFUNC );
898 pulsarParams->Doppler.fkdot[4] = f4dot;
899 // f5dot
900 REAL8 f5dot = 0;
901 BOOLEAN have_f5dot;
902 XLAL_CHECK( XLALReadConfigREAL8Variable( &f5dot, cfgdata, secName, "f5dot", &have_f5dot ) == XLAL_SUCCESS, XLAL_EFUNC );
903 pulsarParams->Doppler.fkdot[5] = f5dot;
904 // f6dot
905 REAL8 f6dot = 0;
906 BOOLEAN have_f6dot;
907 XLAL_CHECK( XLALReadConfigREAL8Variable( &f6dot, cfgdata, secName, "f6dot", &have_f6dot ) == XLAL_SUCCESS, XLAL_EFUNC );
908 pulsarParams->Doppler.fkdot[6] = f6dot;
909
910 // ----- orbit
911 LIGOTimeGPS orbitTp;
912 BOOLEAN have_orbitTp;
913 XLAL_CHECK( XLALReadConfigEPOCHVariable( &orbitTp, cfgdata, secName, "orbitTp", &have_orbitTp ) == XLAL_SUCCESS, XLAL_EFUNC );
914 REAL8 orbitArgp = 0;
915 BOOLEAN have_orbitArgp;
916 XLAL_CHECK( XLALReadConfigREAL8Variable( &orbitArgp, cfgdata, secName, "orbitArgp", &have_orbitArgp ) == XLAL_SUCCESS, XLAL_EFUNC );
917 REAL8 orbitasini = 0 /* isolated pulsar */;
918 BOOLEAN have_orbitasini;
919 XLAL_CHECK( XLALReadConfigREAL8Variable( &orbitasini, cfgdata, secName, "orbitasini", &have_orbitasini ) == XLAL_SUCCESS, XLAL_EFUNC );
920 REAL8 orbitEcc = 0;
921 BOOLEAN have_orbitEcc;
922 XLAL_CHECK( XLALReadConfigREAL8Variable( &orbitEcc, cfgdata, secName, "orbitEcc", &have_orbitEcc ) == XLAL_SUCCESS, XLAL_EFUNC );
923 REAL8 orbitPeriod = 0;
924 BOOLEAN have_orbitPeriod;
925 XLAL_CHECK( XLALReadConfigREAL8Variable( &orbitPeriod, cfgdata, secName, "orbitPeriod", &have_orbitPeriod ) == XLAL_SUCCESS, XLAL_EFUNC );
926
927 if ( have_orbitasini || have_orbitEcc || have_orbitPeriod || have_orbitArgp || have_orbitTp ) {
928 XLAL_CHECK( orbitasini >= 0, XLAL_EDOM );
929 XLAL_CHECK( ( orbitasini == 0 ) || ( have_orbitPeriod && ( orbitPeriod > 0 ) && have_orbitTp ), XLAL_EINVAL, "If orbitasini>0 then we also need 'orbitPeriod>0' and 'orbitTp'\n" );
930 XLAL_CHECK( ( orbitEcc >= 0 ) && ( orbitEcc <= 1 ), XLAL_EDOM );
931
932 /* fill in orbital parameter structure */
933 pulsarParams->Doppler.tp = orbitTp;
934 pulsarParams->Doppler.argp = orbitArgp;
935 pulsarParams->Doppler.asini = orbitasini;
936 pulsarParams->Doppler.ecc = orbitEcc;
937 pulsarParams->Doppler.period = orbitPeriod;
938
939 } // if have non-trivial orbit
940
941 // ---------- transientWindow_t ----------
942
943 // ----- type
944 char *transientWindowType = NULL;
945 BOOLEAN have_transientWindowType;
946 XLAL_CHECK( XLALReadConfigSTRINGVariable( &transientWindowType, cfgdata, secName, "transientWindowType", &have_transientWindowType ) == XLAL_SUCCESS, XLAL_EFUNC );
947 // ----- t0
948 UINT4 transientStartTime = 0;
949 BOOLEAN have_transientStartTime;
950 XLAL_CHECK( XLALReadConfigUINT4Variable( &transientStartTime, cfgdata, secName, "transientStartTime", &have_transientStartTime ) == XLAL_SUCCESS, XLAL_EFUNC );
951 // ----- tau (still keeping deprecated Days variant for backwards compatibility, for now)
952 UINT4 transientTau = 0;
953 BOOLEAN have_transientTau;
954 XLAL_CHECK( XLALReadConfigUINT4Variable( &transientTau, cfgdata, secName, "transientTau", &have_transientTau ) == XLAL_SUCCESS, XLAL_EFUNC );
955 REAL8 transientTauDays = 0;
956 BOOLEAN have_transientTauDays;
957 XLAL_CHECK( XLALReadConfigREAL8Variable( &transientTauDays, cfgdata, secName, "transientTauDays", &have_transientTauDays ) == XLAL_SUCCESS, XLAL_EFUNC );
958
959 int twtype = TRANSIENT_NONE;
960 if ( have_transientWindowType ) {
961 XLAL_CHECK( ( twtype = XLALParseTransientWindowName( transientWindowType ) ) >= 0, XLAL_EFUNC );
962 XLALFree( transientWindowType );
963 }
964 pulsarParams->Transient.type = twtype;
965
966 if ( pulsarParams->Transient.type != TRANSIENT_NONE ) {
967 XLAL_CHECK( have_transientStartTime && ( have_transientTau || have_transientTauDays ), XLAL_EINVAL, "For transientWindowType!=None, we also need transientStartTime and either transientTau (deprecated) or transientTau." );
968 XLAL_CHECK( !( have_transientTau && have_transientTauDays ), XLAL_EINVAL, "Cannot have both transientTau and transientTauDays; the latter is deprecated." );
969
970 pulsarParams->Transient.t0 = transientStartTime;
971 if ( have_transientTauDays ) {
972 XLAL_CHECK( transientTauDays > 0, XLAL_EDOM );
973 printf( "Warning: Option transientTauDays is deprecated, please switch to using transientTau [UINT4, in seconds] instead.\n" );
974 pulsarParams->Transient.tau = ( UINT4 ) round( transientTauDays * 86400 );
975 } else {
976 pulsarParams->Transient.tau = transientTau;
977 }
978 } /* if transient window != none */
979 else {
980 XLAL_CHECK( !( have_transientStartTime || have_transientTau || have_transientTauDays ), XLAL_EINVAL, "Cannot use transientStartTime, transientTau or transientTauDays without transientWindowType!" );
981 }
982
983 return XLAL_SUCCESS;
984} // XLALParsePulsarParams()
985
986
987/**
988 * Parse a given 'CWsources' config file for PulsarParams, return vector
989 * of all pulsar definitions found [using sections]
990 */
992XLALPulsarParamsFromFile( const char *fname, ///< [in] 'CWsources' config file name
993 const LIGOTimeGPS *refTimeDef ///< [in] default reference time if refTime is not given
994 )
995{
996 XLAL_CHECK_NULL( fname != NULL, XLAL_EINVAL );
997
998 LALParsedDataFile *cfgdata = NULL;
1000
1001 LALStringVector *sections;
1002 XLAL_CHECK_NULL( ( sections = XLALListConfigFileSections( cfgdata ) ) != NULL, XLAL_EFUNC );
1003
1004 UINT4 numPulsars = sections->length; // currently only single-section defs supported! FIXME
1005
1006 PulsarParamsVector *sources;
1007 XLAL_CHECK_NULL( ( sources = XLALCreatePulsarParamsVector( numPulsars ) ) != NULL, XLAL_EFUNC );
1008
1009 for ( UINT4 i = 0; i < numPulsars; i ++ ) {
1010 const char *sec_i = sections->data[i];
1011
1012 if ( strcmp( sec_i, "default" ) == 0 ) { // special handling of 'default' section
1013 sec_i = NULL;
1014 }
1015 XLAL_CHECK_NULL( XLALReadPulsarParams( &sources->data[i], cfgdata, sec_i, refTimeDef ) == XLAL_SUCCESS, XLAL_EFUNC );
1016
1017 // ----- source naming convention: 'filename:section'
1018 snprintf( sources->data[i].name, sizeof( sources->data[i].name ), "%s:%s", fname, sections->data[i] );
1019 sources->data[i].name[sizeof( sources->data[i].name ) - 1] = '\0';
1020
1021 } // for i < numPulsars
1022
1023 XLALDestroyStringVector( sections );
1024
1026 XLALDestroyParsedDataFile( cfgdata );
1027
1028 return sources;
1029
1030} // XLALPulsarParamsFromFile()
1031
1032
1033// internal helper function: check that config-file was fully parsed (no leftover un-parsed lines),
1034// throw error if not and list unparsed entries
1035int
1036XLALCheckConfigFileWasFullyParsed( const char *fname, const LALParsedDataFile *cfgdata )
1037{
1038 XLAL_CHECK( cfgdata != NULL, XLAL_EINVAL );
1039
1040 UINT4Vector *n_unread = XLALConfigFileGetUnreadEntries( cfgdata );
1042
1043 if ( n_unread != NULL ) {
1044 XLALPrintError( "ERROR: Pulsar params config file '%s' contained '%d' unknown entries:\n", fname, n_unread->length );
1045 for ( UINT4 i = 0; i < n_unread->length; i ++ ) {
1046 XLALPrintError( "%s'%s'", i > 0 ? ", " : "", cfgdata->lines->tokens[ n_unread->data[i] ] );
1047 }
1048 XLALPrintError( "\n" );
1050 }
1051
1052 return XLAL_SUCCESS;
1053
1054} // XLALCheckConfigFileWasFullyParsed()
1055
1056
1057/**
1058 * Function to determine the PulsarParamsVector input from a user-input defining CW sources.
1059 *
1060 * This option supports a dual-type feature: if any string in the list is of the form '{...}', then
1061 * it determines the *contents* of a config-file, otherwise the name-pattern of config-files to be parsed by XLALFindFiles(),
1062 * NOTE: when specifying file-contents, options can be separated by ';' and/or newlines)
1063 */
1065XLALPulsarParamsFromUserInput( const LALStringVector *UserInput, ///< [in] user-input CSV list defining 'CW sources'
1066 const LIGOTimeGPS *refTimeDef ///< [in] default reference time if refTime is not given
1067 )
1068{
1069 XLAL_CHECK_NULL( UserInput, XLAL_EINVAL );
1070 XLAL_CHECK_NULL( UserInput->length > 0, XLAL_EINVAL );
1071
1072 PulsarParamsVector *allSources = NULL;
1073
1074 for ( UINT4 l = 0; l < UserInput->length; l ++ ) {
1075 const char *thisInput = UserInput->data[l];
1076
1077 if ( thisInput[0] != '{' ) { // if it's an actual file-specification
1078 LALStringVector *file_list;
1079 XLAL_CHECK_NULL( ( file_list = XLALFindFiles( &thisInput[0] ) ) != NULL, XLAL_EFUNC );
1080 UINT4 numFiles = file_list->length;
1081 for ( UINT4 i = 0; i < numFiles; i ++ ) {
1082 PulsarParamsVector *sources_i;
1083 XLAL_CHECK_NULL( ( sources_i = XLALPulsarParamsFromFile( file_list->data[i], refTimeDef ) ) != NULL, XLAL_EFUNC );
1084
1085 XLAL_CHECK_NULL( ( allSources = XLALPulsarParamsVectorAppend( allSources, sources_i ) ) != NULL, XLAL_EFUNC );
1086 XLALDestroyPulsarParamsVector( sources_i );
1087 } // for i < numFiles
1088
1089 XLALDestroyStringVector( file_list );
1090
1091 } // if file-pattern given
1092 else {
1093 UINT4 len = strlen( thisInput );
1094 XLAL_CHECK_NULL( ( thisInput[0] == '{' ) && ( thisInput[len - 1] == '}' ), XLAL_EINVAL, "Invalid file-content input:\n%s\n", thisInput );
1095 char *buf;
1096 XLAL_CHECK_NULL( ( buf = XLALStringDuplicate( &thisInput[1] ) ) != NULL, XLAL_EFUNC );
1097 len = strlen( buf );
1098 buf[len - 1] = 0; // remove trailing '}'
1099
1100 LALParsedDataFile *cfgdata = NULL;
1102 XLALFree( buf );
1103
1104 PulsarParamsVector *addSource;
1105 XLAL_CHECK_NULL( ( addSource = XLALCreatePulsarParamsVector( 1 ) ) != NULL, XLAL_EFUNC );
1106
1107 XLAL_CHECK_NULL( XLALReadPulsarParams( &addSource->data[0], cfgdata, NULL, refTimeDef ) == XLAL_SUCCESS, XLAL_EFUNC );
1108 strncpy( addSource->data[0].name, "direct-string-input", sizeof( addSource->data[0].name ) );
1109
1111 XLALDestroyParsedDataFile( cfgdata );
1112
1113 XLAL_CHECK_NULL( ( allSources = XLALPulsarParamsVectorAppend( allSources, addSource ) ) != NULL, XLAL_EFUNC );
1114 XLALDestroyPulsarParamsVector( addSource );
1115
1116 } // if direct config-string given
1117
1118 } // for l < len(UserInput)
1119
1120 return allSources;
1121
1122} // XLALPulsarParamsFromUserInput()
1123
1124/**
1125 * Append the given PulsarParamsVector 'add' to the vector 'list' ( which can be NULL), return resulting list
1126 * with new elements 'add' appended at the end of 'list'.
1127 */
1130{
1131 XLAL_CHECK_NULL( add != NULL, XLAL_EINVAL );
1132
1133 PulsarParamsVector *ret;
1134 if ( list == NULL ) {
1135 XLAL_CHECK_NULL( ( ret = XLALCalloc( 1, sizeof( *ret ) ) ) != NULL, XLAL_ENOMEM );
1136 } else {
1137 ret = list;
1138 }
1139
1140 UINT4 oldlen = ret->length;
1141 UINT4 addlen = add->length;
1142 UINT4 newlen = oldlen + addlen;
1143 ret->length = newlen;
1144 XLAL_CHECK_NULL( ( ret->data = XLALRealloc( ret->data, newlen * sizeof( ret->data[0] ) ) ) != NULL, XLAL_ENOMEM );
1145 memcpy( ret->data + oldlen, add->data, addlen * sizeof( ret->data[0] ) );
1146 // we have to properly copy the 'name' string fields
1147 for ( UINT4 i = 0; i < addlen; i ++ ) {
1148 strncpy( ret->data[oldlen + i].name, add->data[i].name, sizeof( ret->data[oldlen + i].name ) );
1149 }
1150
1151 return ret;
1152
1153} // XLALPulsarParamsVectorAppend()
1154
1155/**
1156 * Write a PulsarParamsVector to a FITS file
1157 */
1158int
1160{
1161 XLAL_CHECK( file != NULL, XLAL_EFAULT );
1162 XLAL_CHECK( tableName != NULL, XLAL_EFAULT );
1163 XLAL_CHECK( list != NULL, XLAL_EFAULT );
1164
1165 // Begin FITS table
1166 XLAL_CHECK( XLALFITSTableOpenWrite( file, tableName, "list of injections" ) == XLAL_SUCCESS, XLAL_EFUNC );
1167
1168 // Describe FITS table
1175 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, GPSTime, Doppler.refTime, "refTime" ) == XLAL_SUCCESS, XLAL_EFUNC );
1176 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, REAL8, Doppler.Alpha, "Alpha [rad]" ) == XLAL_SUCCESS, XLAL_EFUNC );
1177 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, REAL8, Doppler.Delta, "Delta [rad]" ) == XLAL_SUCCESS, XLAL_EFUNC );
1178 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, REAL8, Doppler.fkdot[0], "Freq [Hz]" ) == XLAL_SUCCESS, XLAL_EFUNC );
1179 for ( size_t k = 1; k < PULSAR_MAX_SPINS; ++k ) {
1180 char col_name[64];
1181 snprintf( col_name, sizeof( col_name ), "f%zudot [Hz/s^%zu]", k, k );
1182 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, REAL8, Doppler.fkdot[k], col_name ) == XLAL_SUCCESS, XLAL_EFUNC );
1183 }
1184 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, REAL8, Doppler.asini, "orbitasini [s]" ) == XLAL_SUCCESS, XLAL_EFUNC );
1185 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, REAL8, Doppler.period, "orbitPeriod [s]" ) == XLAL_SUCCESS, XLAL_EFUNC );
1187 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, GPSTime, Doppler.tp, "orbitTp" ) == XLAL_SUCCESS, XLAL_EFUNC );
1188 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, REAL8, Doppler.argp, "orbitArgp [rad]" ) == XLAL_SUCCESS, XLAL_EFUNC );
1189 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, UINT4, Transient.type, "transientWindowType" ) == XLAL_SUCCESS, XLAL_EFUNC );
1190 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, UINT4, Transient.t0, "transientStartTime" ) == XLAL_SUCCESS, XLAL_EFUNC );
1191 XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, UINT4, Transient.tau, "transientTau" ) == XLAL_SUCCESS, XLAL_EFUNC );
1192
1193 // Write FITS table
1194 for ( size_t i = 0; i < list->length; ++i ) {
1196 }
1197
1198 return XLAL_SUCCESS;
1199
1200} // XLALFITSWritePulsarParamsVector()
1201
1202/**
1203 * Destructor for a CWMFDataParams type
1204 *
1205 * \note: This is mostly useful for the SWIG wrappers
1206 */
1207void
1209{
1210 if ( params ) {
1211 fflush( stdout );
1212 XLALDestroyMultiTimestamps( params->multiTimestamps );
1213 XLALDestroyMultiREAL8TimeSeries( params->inputMultiTS );
1214 XLALFree( params );
1215 }
1216} // XLALDestroyCWMFDataParams()
1217
1218/// @}
const REAL8 eps
int XLALReadConfigSTRINGVariable(CHAR **varp, LALParsedDataFile *cfgdata, const CHAR *secName, const CHAR *varName, BOOLEAN *wasRead)
#define LAL_FFTW_WISDOM_UNLOCK
#define LAL_FFTW_WISDOM_LOCK
int XLALFITSTableWriteRow(FITSFile UNUSED *file, const void UNUSED *record)
Definition: FITSFileIO.c:2550
int XLALFITSTableOpenWrite(FITSFile UNUSED *file, const CHAR UNUSED *name, const CHAR UNUSED *comment)
Definition: FITSFileIO.c:2162
int k
const char * name
Definition: SearchTiming.c:93
const WeaveSearchTimingDenominator denom
Definition: SearchTiming.c:95
LIGOTimeGPSVector * timestamps
int l
double e
int XLALFindSmallestValidSamplingRate(UINT4 *n1, UINT4 n0, const LIGOTimeGPSVector *timestamps)
Find the smallest sampling rate of the form fsamp = n / Tsft, with n>=n0, such that all gap sizes Dt_...
int XLALCWMakeFakeData(SFTVector **SFTvect, REAL8TimeSeries **Tseries, const PulsarParamsVector *injectionSources, const CWMFDataParams *dataParams, UINT4 detectorIndex, const EphemerisData *edat)
Single-IFO version of XLALCWMakeFakeMultiData(), handling the actual work, but same input API.
PulsarParamsVector * XLALPulsarParamsVectorAppend(PulsarParamsVector *list, const PulsarParamsVector *add)
Append the given PulsarParamsVector 'add' to the vector 'list' ( which can be NULL),...
PulsarParamsVector * XLALCreatePulsarParamsVector(UINT4 numPulsars)
Create zero-initialized PulsarParamsVector for numPulsars.
int XLALReadPulsarParams(PulsarParams *pulsarParams, LALParsedDataFile *cfgdata, const CHAR *secName, const LIGOTimeGPS *refTimeDef)
Function to parse a config-file-type string (or section thereof) into a PulsarParams struct.
static UINT4 gcd(UINT4 numer, UINT4 denom)
int XLALCheckConfigFileWasFullyParsed(const char *fname, const LALParsedDataFile *cfgdata)
SFTVector * XLALMakeSFTsFromREAL8TimeSeries(const REAL8TimeSeries *timeseries, const LIGOTimeGPSVector *timestamps, const char *windowType, REAL8 windowParam)
Make SFTs from given REAL8TimeSeries at given timestamps, potentially applying a time-domain window o...
PulsarParamsVector * XLALPulsarParamsFromUserInput(const LALStringVector *UserInput, const LIGOTimeGPS *refTimeDef)
Function to determine the PulsarParamsVector input from a user-input defining CW sources.
const char *const InjectionSourcesHelpString
void XLALDestroyPulsarParamsVector(PulsarParamsVector *ppvect)
Destructor for PulsarParamsVector type.
int XLALFITSWritePulsarParamsVector(FITSFile *file, const CHAR *tableName, const PulsarParamsVector *list)
Write a PulsarParamsVector to a FITS file.
#define SQ(x)
Functions to generate 'fake' data containing CW signals and/or Gaussian noise. These basically presen...
void XLALDestroyCWMFDataParams(CWMFDataParams *params)
Destructor for a CWMFDataParams type.
REAL4TimeSeries * XLALGenerateCWSignalTS(const PulsarParams *pulsarParams, const LALDetector *site, LIGOTimeGPS startTime, REAL8 duration, REAL8 fSamp, REAL8 fHet, const EphemerisData *edat, REAL8 sourceDeltaT)
Generate a (heterodyned) REAL4 timeseries of a CW signal for given pulsarParams, site,...
PulsarParamsVector * XLALPulsarParamsFromFile(const char *fname, const LIGOTimeGPS *refTimeDef)
Parse a given 'CWsources' config file for PulsarParams, return vector of all pulsar definitions found...
int XLALCWMakeFakeMultiData(MultiSFTVector **multiSFTs, MultiREAL8TimeSeries **multiTseries, const PulsarParamsVector *injectionSources, const CWMFDataParams *dataParams, const EphemerisData *edat)
Generate fake 'CW' data, returned either as SFTVector or REAL4Timeseries or both, for given CW-signal...
int XLALParseDataFileContent(LALParsedDataFile **cfgdata, const CHAR *string)
int XLALParseDataFile(LALParsedDataFile **cfgdata, const CHAR *fname)
UINT4Vector * XLALConfigFileGetUnreadEntries(const LALParsedDataFile *cfgdata)
LALStringVector * XLALListConfigFileSections(const LALParsedDataFile *cfgdata)
void XLALDestroyParsedDataFile(LALParsedDataFile *cfgdata)
char * XLALGPSToStr(char *s, const LIGOTimeGPS *t)
int XLALCWSignalCoveringBand(REAL8 *minCoverFreq, REAL8 *maxCoverFreq, const LIGOTimeGPS *time1, const LIGOTimeGPS *time2, const PulsarSpinRange *spinRange, const REAL8 binaryMaxAsini, const REAL8 binaryMinPeriod, const REAL8 binaryMaxEcc)
Determines a frequency band which covers the frequency evolution of a band of CW signals between two ...
#define XLAL_FITS_TABLE_COLUMN_BEGIN(record_type)
Definition: FITSFileIO.h:239
#define XLAL_FITS_TABLE_COLUMN_ADD_NAMED(file, type, field, col_name)
Definition: FITSFileIO.h:246
#define XLAL_FITS_TABLE_COLUMN_ADD_ARRAY(file, type, field)
Definition: FITSFileIO.h:249
struct tagFITSFile FITSFile
Representation of a FITS file.
Definition: FITSFileIO.h:54
REAL4TimeSeries * XLALGeneratePulsarSignal(const PulsarSignalParams *params)
Generate a time-series at the detector for a given pulsar.
void XLALDestroyMultiREAL8TimeSeries(MultiREAL8TimeSeries *multiTS)
Destroy a MultiREAL8TimeSeries, NULL-robust.
int XLALAddGaussianNoise(REAL4TimeSeries *inSeries, REAL4 sigma, INT4 seed)
Generate Gaussian noise with standard-deviation sigma, add it to inSeries.
int XLALcorrect_phase(SFTtype *sft, LIGOTimeGPS tHeterodyne)
Yousuke's phase-correction function, taken from makefakedata_v2.
#define LAL_PI_2
#define LAL_UINT4_MAX
#define LAL_REAL8_EPS
#define LAL_TWOPI
unsigned char BOOLEAN
#define XLAL_INIT_MEM(x)
double REAL8
#define XLAL_INIT_DECL(var,...)
int64_t INT8
char CHAR
uint32_t UINT4
float complex COMPLEX8
int32_t INT4
void * XLALCalloc(size_t m, size_t n)
void * XLALRealloc(void *p, size_t n)
void XLALFree(void *p)
char char * XLALStringDuplicate(const char *s)
REAL8 PulsarSpins[PULSAR_MAX_SPINS]
Typedef for fixed-size array holding GW frequency and derivatives fk = d^k Freq/dt^k|(tau_ref)
#define PULSAR_MAX_SPINS
maximal number of spin-parameters (Freq + spindowns) we can handle
@ TRANSIENT_NONE
Note: in this case the window-parameters will be ignored, and treated as rect={data},...
void XLALDestroySFTVector(SFTVector *vect)
XLAL interface to destroy an SFTVector.
Definition: SFTtypes.c:300
CHAR * XLALGetChannelPrefix(const CHAR *name)
Find the valid CW detector prefix.
Definition: SFTnaming.c:203
int XLALFindCoveringSFTBins(UINT4 *firstBin, UINT4 *numBins, REAL8 fMinIn, REAL8 BandIn, REAL8 Tsft)
Return the 'effective' frequency-band [fMinEff, fMaxEff] = [firstBin, lastBin] * 1/Tsft,...
Definition: SFTtypes.c:106
LALStringVector * XLALFindFiles(const CHAR *globstring)
Returns a list of filenames matching the input argument, which may be one of the following:
Definition: FindFiles.c:61
void XLALDestroyMultiTimestamps(MultiLIGOTimeGPSVector *multiTS)
Destroy a MultiLIGOTimeGPSVector timestamps vector.
SFTVector * XLALCreateSFTVector(UINT4 numSFTs, UINT4 numBins)
XLAL function to create an SFTVector of numSFT SFTs with SFTlen frequency-bins (which will be allocat...
Definition: SFTtypes.c:230
SFTVector * XLALExtractStrictBandFromSFTVector(const SFTVector *inSFTs, REAL8 fMin, REAL8 Band)
Return a copy of a vector of SFTs containing only the bins in [fMin, fMin+Band).
Definition: SFTtypes.c:658
COORDINATESYSTEM_EQUATORIAL
void XLALDestroyStringVector(LALStringVector *vect)
REAL4TimeSeries * XLALCreateREAL4TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
REAL4TimeSeries * XLALAddREAL4TimeSeries(REAL4TimeSeries *arg1, const REAL4TimeSeries *arg2)
REAL8TimeSeries * XLALConvertREAL4TimeSeriesToREAL8(const REAL4TimeSeries *series)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
REAL8TimeSeries * XLALAddREAL8TimeSeries(REAL8TimeSeries *arg1, const REAL8TimeSeries *arg2)
void XLALDestroyREAL4TimeSeries(REAL4TimeSeries *series)
int XLALParseTransientWindowName(const char *windowName)
Parse a transient window name string into the corresponding transientWindowType.
int XLALGetTransientWindowTimespan(UINT4 *t0, UINT4 *t1, transientWindow_t transientWindow)
Helper-function to determine the total timespan of a transient CW window, ie.
int XLALApplyTransientWindow(REAL4TimeSeries *series, transientWindow_t transientWindow)
apply a "transient CW window" described by TransientWindowParams to the given timeseries
const LALUnit lalStrainUnit
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
REAL8Window * XLALCreateNamedREAL8Window(const char *windowName, REAL8 beta, UINT4 length)
void XLALDestroyREAL8Window(REAL8Window *window)
#define xlalErrno
int int int XLALPrintInfo(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
int int XLALPrintWarning(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_CHECK_NULL(assertion,...)
XLAL_ENOMEM
XLAL_EDATA
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_ETOL
XLAL_EDOM
XLAL_EINVAL
XLAL_EFAILED
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
REAL8 XLALGPSDiff(const LIGOTimeGPS *t1, const LIGOTimeGPS *t0)
ts
double t0
CHAR name[LALNameLength]
COMPLEX8Sequence * data
A vector of COMPLEX8FrequencySeries.
COMPLEX8FrequencySeries * data
Pointer to the data array.
COMPLEX8 * data
Struct controlling all the aspects of the fake data (time-series + SFTs) to be produced by XLALCWMake...
This structure contains all information about the center-of-mass positions of the Earth and Sun,...
TokenList * lines
INT4 gpsNanoSeconds
A vector of 'timestamps' of type LIGOTimeGPS.
Definition: SFTfileIO.h:188
REAL8 deltaT
'length' of each timestamp (e.g.
Definition: SFTfileIO.h:194
LIGOTimeGPS * data
array of timestamps
Definition: SFTfileIO.h:193
UINT4 length
number of timestamps
Definition: SFTfileIO.h:192
A collection of (multi-IFO) LIGOTimeGPSVector time-stamps vectors.
Definition: SFTfileIO.h:198
A collection of (multi-IFO) REAL8 time-series.
REAL8TimeSeries ** data
Pointer to the data array.
UINT4 length
Number of elements in array.
A collection of SFT vectors – one for each IFO in a multi-IFO search.
Definition: SFTfileIO.h:179
UINT4 length
number of ifos
Definition: SFTfileIO.h:183
SFTVector ** data
sftvector for each ifo
Definition: SFTfileIO.h:184
REAL8 aCross
Signal amplitude (cross)
REAL8 psi
polarization angle psi
REAL8 aPlus
Signal amplitude (plus)
REAL8 phi0
initial signal-phase (at some reference time)
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)
Type defining the parameters of a pulsar-source of CW Gravitational waves.
PulsarAmplitudeParams Amp
'Amplitude-parameters': h0, cosi, phi0, psi
CHAR name[LALNameLength]
'name' for this sources, can be an empty string
transientWindow_t Transient
Transient window-parameters (start-time, duration, window-type)
PulsarDopplerParams Doppler
'Phase-evolution parameters': {skypos, fkdot, orbital params }
Straightforward vector type of N PulsarParams structs.
PulsarParams * data
array of pulsar-signal parameters
UINT4 length
number of pulsar-signals
Input parameters to GeneratePulsarSignal(), defining the source and the time-series.
Contains a "spin-range", ie spins and corresponding bands at a given (SSB) reference GPS-time .
REAL4Sequence * data
LIGOTimeGPS epoch
REAL4 * data
REAL8Sequence * data
LIGOTimeGPS epoch
CHAR name[LALNameLength]
REAL8 * data
REAL8Sequence * data
REAL8 sumofsquares
CHAR ** tokens
UINT4 * data
double duration
double psi
UINT4 t0
GPS start-time 't0'.
UINT4 tau
transient timescale tau in seconds
transientWindowType_t type
window-type: none, rectangular, exponential, ....
enum @4 site
double df