LALPulsar  6.1.0.1-89842e6
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
56 const REAL8 eps = 10 * LAL_REAL8_EPS;
57 
58 const 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
76 static UINT4 gcd( UINT4 numer, UINT4 denom );
77 int XLALcorrect_phase( SFTtype *sft, LIGOTimeGPS tHeterodyne );
78 int 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  */
89 int
90 XLALCWMakeFakeMultiData( 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 
101  XLAL_CHECK( dataParams != NULL, XLAL_EINVAL );
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  */
164 int
166  REAL8TimeSeries **Tseries,
168  const CWMFDataParams *dataParams,
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 
178  XLAL_CHECK( dataParams != NULL, XLAL_EINVAL );
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 );
246  REAL8 duration;
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  */
396 XLALGenerateCWSignalTS( 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 ///
479 SFTVector *
480 XLALMakeSFTsFromREAL8TimeSeries( 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  */
619 int
620 XLALFindSmallestValidSamplingRate( 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;
631  XLAL_CHECK( Tsft > 0, XLAL_EINVAL );
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  */
703 static UINT4
704 gcd( UINT4 numer, UINT4 denom )
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 {
724  PulsarParamsVector *ret;
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  */
739 void
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  */
781 int
782 XLALReadPulsarParams( 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  */
992 XLALPulsarParamsFromFile( 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;
999  XLAL_CHECK_NULL( XLALParseDataFile( &cfgdata, fname ) == XLAL_SUCCESS, XLAL_EFUNC );
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
1035 int
1036 XLALCheckConfigFileWasFullyParsed( const char *fname, const LALParsedDataFile *cfgdata )
1037 {
1038  XLAL_CHECK( cfgdata != NULL, XLAL_EINVAL );
1039 
1040  UINT4Vector *n_unread = XLALConfigFileGetUnreadEntries( cfgdata );
1041  XLAL_CHECK( xlalErrno == 0, XLAL_EFUNC );
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  */
1065 XLALPulsarParamsFromUserInput( 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 
1110  XLAL_CHECK_NULL( XLALCheckConfigFileWasFullyParsed( "{command-line}", cfgdata ) == XLAL_SUCCESS, XLAL_EINVAL );
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  */
1158 int
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
1172  XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, REAL8, Amp.phi0, "phi0 [rad]" ) == XLAL_SUCCESS, XLAL_EFUNC );
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 );
1186  XLAL_CHECK( XLAL_FITS_TABLE_COLUMN_ADD_NAMED( file, REAL8, Doppler.ecc, "orbitEcc" ) == 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  */
1207 void
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 s
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...
UINT4Vector * XLALConfigFileGetUnreadEntries(const LALParsedDataFile *cfgdata)
int XLALParseDataFileContent(LALParsedDataFile **cfgdata, const CHAR *string)
int XLALParseDataFile(LALParsedDataFile **cfgdata, const CHAR *fname)
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)
REAL8TimeSeries * XLALConvertREAL4TimeSeriesToREAL8(const REAL4TimeSeries *series)
REAL8TimeSeries * XLALAddREAL8TimeSeries(REAL8TimeSeries *arg1, const REAL8TimeSeries *arg2)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
void XLALDestroyREAL4TimeSeries(REAL4TimeSeries *series)
REAL4TimeSeries * XLALAddREAL4TimeSeries(REAL4TimeSeries *arg1, const REAL4TimeSeries *arg2)
REAL4TimeSeries * XLALCreateREAL4TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
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, ...
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