00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <math.h>
00031 #include <lal/LALSimulation.h>
00032 #include <lal/LALDetectors.h>
00033 #include <lal/LALComplex.h>
00034 #include <lal/DetResponse.h>
00035 #include <lal/Date.h>
00036 #include <lal/Units.h>
00037 #include <lal/TimeDelay.h>
00038 #include <lal/SkyCoordinates.h>
00039 #include <lal/TimeSeries.h>
00040 #include <lal/FrequencySeries.h>
00041 #include <lal/TimeFreqFFT.h>
00042 #include <lal/Window.h>
00043 #include "check_series_macros.h"
00044
00045
00046 #include <lal/LALRCSID.h>
00047 NRCSID(LALSIMULATIONC, "$Id:");
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 static unsigned long round_up_to_power_of_two(unsigned long x)
00065 {
00066 unsigned n;
00067
00068 x--;
00069
00070 for(n = 1; n && (x & (x + 1)); n *= 2)
00071 x |= x >> n;
00072
00073 return x + 1;
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 const LALDetector *XLALInstrumentNameToLALDetector(
00088 const char *string
00089 )
00090 {
00091 static const char func[] = "XLALInstrumentNameToLALDetector";
00092 int i;
00093
00094 for(i = 0; i < LAL_NUM_DETECTORS; i++)
00095 if(!strncmp(string, lalCachedDetectors[i].frDetector.prefix, 2))
00096 return &lalCachedDetectors[i];
00097
00098 XLALPrintError("%s(): error: can't identify instrument from string \"%s\"\n", func, string);
00099 XLAL_ERROR_NULL(func, XLAL_EDATA);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 #if 0
00113 REAL8TimeSeries * XLALSimQuasiPeriodicInjectionREAL8TimeSeries( REAL8TimeSeries *aplus, REAL8TimeSeries *across, REAL8TimeSeries *frequency, REAL8TimeSeries *phi, REAL8TimeSeries *psi, SkyPosition *position, LALDetector *detector, EphemerisData *ephemerides, LIGOTimeGPS *start, REAL8 deltaT, UINT4 length, COMPLEX16FrequencySeries *response )
00114 {
00115 REAL8 slowDeltaT = 600.0;
00116 UINT4 slowLength;
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 slowLength = floor(0.5 + (length*deltaT + 16.0)/slowDeltaT);
00127
00128
00129
00130
00131 fplus;
00132 fcross;
00133
00134
00135
00136
00137
00138
00139 for ( j = 0; j < injection->length; ++j ) {
00140 REAL8 dt;
00141 REAL8 fpl;
00142 REAL8 fcr;
00143 REAL8 apl;
00144 REAL8 acr;
00145 REAL8 freq;
00146 REAL8 phase;
00147 REAL8 pol;
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 injection->data->data[j] = fpl*apl*cos(phase) + fcr*acr*sin(phase);
00159
00160 }
00161
00162
00163
00164 }
00165 #endif
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 REAL8TimeSeries *XLALSimDetectorStrainREAL8TimeSeries(
00198 const REAL8TimeSeries *hplus,
00199 const REAL8TimeSeries *hcross,
00200 REAL8 right_ascension,
00201 REAL8 declination,
00202 REAL8 psi,
00203 LALDetector *detector
00204 )
00205 {
00206 static const char func[] = "XLALSimDetectorStrainREAL8TimeSeries";
00207 char name[13];
00208 REAL8TimeSeries *h;
00209 unsigned i;
00210
00211 LAL_CHECK_VALID_SERIES(hplus, NULL);
00212 LAL_CHECK_VALID_SERIES(hcross, NULL);
00213 LAL_CHECK_CONSISTENT_TIME_SERIES(hplus, hcross, NULL);
00214
00215
00216
00217 sprintf(name, "%2s injection", detector->frDetector.prefix);
00218
00219
00220
00221 h = XLALCreateREAL8TimeSeries(name, &hplus->epoch, hplus->f0, hplus->deltaT, &hplus->sampleUnits, hplus->data->length);
00222 if(!h)
00223 XLAL_ERROR_NULL(func, XLAL_EFUNC);
00224
00225
00226
00227
00228
00229 XLALGPSAdd(&h->epoch, XLALTimeDelayFromEarthCenter(detector->location, right_ascension, declination, &h->epoch));
00230
00231
00232
00233 for(i = 0; i < h->data->length; i++) {
00234 LIGOTimeGPS t = h->epoch;
00235 double fplus, fcross;
00236
00237 XLALGPSAdd(&t, i * h->deltaT);
00238 XLALComputeDetAMResponse(&fplus, &fcross, detector->response, right_ascension, declination, psi, XLALGreenwichMeanSiderealTime(&t));
00239
00240 h->data->data[i] = fplus * hplus->data->data[i] + fcross * hcross->data->data[i];
00241 }
00242
00243
00244
00245 return h;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 int XLALSimAddInjectionREAL8TimeSeries(
00267 REAL8TimeSeries *target,
00268 REAL8TimeSeries *h,
00269 const COMPLEX16FrequencySeries *response
00270 )
00271 {
00272 static const char func[] = "XLALSimAddInjectionREAL8TimeSeries";
00273 COMPLEX16FrequencySeries *tilde_h;
00274 REAL8FFTPlan *plan;
00275 REAL8Window *window;
00276
00277
00278
00279
00280 const unsigned aperiodicity_suppression_buffer = 32768;
00281 unsigned i;
00282 double start_sample_int;
00283 double start_sample_frac;
00284
00285
00286
00287
00288
00289
00290
00291
00292 if(h->deltaT != target->deltaT || h->f0 != target->f0) {
00293 XLALPrintError("%s(): error: input sample rates or heterodyne frequencies do not match\n", func);
00294 XLAL_ERROR(func, XLAL_EINVAL);
00295 }
00296
00297
00298
00299
00300
00301 i = round_up_to_power_of_two(h->data->length + 2 * aperiodicity_suppression_buffer);
00302 if(i < h->data->length) {
00303
00304 XLALPrintError("%s(): error: source time series too long\n", func);
00305 XLAL_ERROR(func, XLAL_EBADLEN);
00306 }
00307 i -= h->data->length;
00308 if(!XLALResizeREAL8TimeSeries(h, -(int) (i / 2), h->data->length + i))
00309 XLAL_ERROR(func, XLAL_EFUNC);
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 start_sample_frac = modf(XLALGPSDiff(&h->epoch, &target->epoch) / target->deltaT, &start_sample_int);
00321 if(start_sample_frac < -0.5) {
00322 start_sample_frac += 1.0;
00323 start_sample_int -= 1.0;
00324 } else if(start_sample_frac > +0.5) {
00325 start_sample_frac -= 1.0;
00326 start_sample_int += 1.0;
00327 }
00328
00329
00330
00331
00332
00333 tilde_h = XLALCreateCOMPLEX16FrequencySeries(NULL, &h->epoch, 0, 0, &lalDimensionlessUnit, h->data->length / 2 + 1);
00334 plan = XLALCreateForwardREAL8FFTPlan(h->data->length, 0);
00335 if(!tilde_h || !plan) {
00336 XLALDestroyCOMPLEX16FrequencySeries(tilde_h);
00337 XLALDestroyREAL8FFTPlan(plan);
00338 XLAL_ERROR(func, XLAL_EFUNC);
00339 }
00340 i = XLALREAL8TimeFreqFFT(tilde_h, h, plan);
00341 XLALDestroyREAL8FFTPlan(plan);
00342 if(i) {
00343 XLALDestroyCOMPLEX16FrequencySeries(tilde_h);
00344 XLAL_ERROR(func, XLAL_EFUNC);
00345 }
00346
00347
00348
00349
00350 for(i = 0; i < tilde_h->data->length; i++) {
00351 const double f = tilde_h->f0 + i * tilde_h->deltaF;
00352 COMPLEX16 fac;
00353
00354
00355
00356 fac = LAL_CEXP(LAL_CMUL_REAL(LAL_COMPLEX16_I, -LAL_TWOPI * f * start_sample_frac * target->deltaT));
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 if(response) {
00374 int j = floor((f - response->f0) / response->deltaF + 0.5);
00375 if(j < 0)
00376 j = 0;
00377 else if((unsigned) j > response->data->length - 1)
00378 j = response->data->length - 1;
00379 if(LAL_COMPLEX_EQ(response->data->data[j], LAL_COMPLEX16_ZERO))
00380 fac = LAL_COMPLEX16_ZERO;
00381 else
00382 fac = LAL_CDIV(fac, response->data->data[j]);
00383 }
00384
00385
00386
00387 tilde_h->data->data[i] = LAL_CMUL(tilde_h->data->data[i], fac);
00388 }
00389
00390
00391
00392
00393
00394
00395 if(response) {
00396
00397
00398 if(tilde_h->f0 == 0.0)
00399 tilde_h->data->data[0] = LAL_COMPLEX16_ZERO;
00400 tilde_h->data->data[tilde_h->data->length - 1] = LAL_COMPLEX16_ZERO;
00401 } else {
00402
00403
00404
00405 if(tilde_h->f0 == 0.0)
00406 tilde_h->data->data[0] = XLALCOMPLEX16Rect(LAL_CABS(tilde_h->data->data[0]), 0.0);
00407 tilde_h->data->data[tilde_h->data->length - 1] = XLALCOMPLEX16Rect(LAL_REAL(tilde_h->data->data[tilde_h->data->length - 1]), 0.0);
00408 }
00409
00410
00411
00412 plan = XLALCreateReverseREAL8FFTPlan(h->data->length, 0);
00413 if(!plan) {
00414 XLALDestroyCOMPLEX16FrequencySeries(tilde_h);
00415 XLAL_ERROR(func, XLAL_EFUNC);
00416 }
00417 i = XLALREAL8FreqTimeFFT(h, tilde_h, plan);
00418 XLALDestroyREAL8FFTPlan(plan);
00419 XLALDestroyCOMPLEX16FrequencySeries(tilde_h);
00420 if(i)
00421 XLAL_ERROR(func, XLAL_EFUNC);
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 if(fabs(h->deltaT - target->deltaT) / target->deltaT > 1e-12) {
00432 XLALPrintError("%s(): error: oops, internal sample rate mismatch\n", func);
00433 XLAL_ERROR(func, XLAL_EERR);
00434 }
00435 h->deltaT = target->deltaT;
00436
00437
00438
00439 h->epoch = target->epoch;
00440 XLALGPSAdd(&h->epoch, start_sample_int * target->deltaT);
00441
00442
00443
00444
00445
00446 if(!XLALResizeREAL8TimeSeries(h, aperiodicity_suppression_buffer / 2, h->data->length - aperiodicity_suppression_buffer))
00447 XLAL_ERROR(func, XLAL_EFUNC);
00448
00449
00450
00451
00452
00453
00454 window = XLALCreateTukeyREAL8Window(h->data->length, (double) (aperiodicity_suppression_buffer - 2) / h->data->length);
00455 if(!window)
00456 XLAL_ERROR(func, XLAL_EFUNC);
00457 for(i = 0; i < h->data->length; i++)
00458 h->data->data[i] *= window->data->data[i];
00459 XLALDestroyREAL8Window(window);
00460
00461
00462
00463 if(!XLALAddREAL8TimeSeries(target, h))
00464 XLAL_ERROR(func, XLAL_EFUNC);
00465
00466
00467
00468 return 0;
00469 }