LALBurst 2.0.7.1-eeff03c
GenerateBurst.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007 Jolien Creighton, Patrick Brady, Saikat Ray-Majumder,
3 * Xavier Siemens, Teviet Creighton, Kipp Cannon
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with with program; see the file COPYING. If not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 */
20
21
22/*
23 * ============================================================================
24 *
25 * Preamble
26 *
27 * ============================================================================
28 */
29
30
31#include <math.h>
32#include <string.h>
33#include <gsl/gsl_rng.h>
34#include <gsl/gsl_randist.h>
35#include <lal/Date.h>
36#include <lal/GenerateBurst.h>
37#include <lal/Units.h>
38#include <lal/LALConstants.h>
39#include <lal/LALDatatypes.h>
40#include <lal/LALDetectors.h>
41#include <lal/LALSimBurst.h>
42#include <lal/LALSimulation.h>
43#include <lal/LIGOMetadataTables.h>
44#include <lal/LIGOMetadataUtils.h>
45#include <lal/TimeFreqFFT.h>
46#include <lal/TimeSeries.h>
47#include <lal/FrequencySeries.h>
48
49/*
50 * ============================================================================
51 *
52 * sim_burst Nexus
53 *
54 * ============================================================================
55 */
56
57
58/**
59 * Generate the + and x time series for a single sim_burst table row.
60 * Note: only the row pointed to by sim_burst is processed, the linked
61 * list is not iterated over. The hplus and hcross time series objects
62 * will be allocated by this function. The time-at-geocentre is applied,
63 * but the time shift offset must be applied separately. delta_t is the
64 * sample interval for the time series. The return value is 0 on success,
65 * non-0 on failure.
66 */
68 REAL8TimeSeries **hplus,
69 REAL8TimeSeries **hcross,
70 const SimBurst *sim_burst,
71 double delta_t
72)
73{
74 if(!strcmp(sim_burst->waveform, "BTLWNB")) {
75 // E_{GW}/r^{2} is in M_{sun} / pc^{2}, so we multiply by
76 // (M_{sun} c^2) to convert to energy/pc^{2}, and divide by
77 // (distance/pc)^{2} to convert to energy/distance^{2},
78 // which is then multiplied by (4 G / c^3) to convert to a
79 // value of \int \dot{h}^{2} \diff t. From the values of
80 // the LAL constants, the total factor multiplying
81 // egw_over_rsquared is 1.8597e-21.
82
83 double int_hdot_squared_dt = sim_burst->egw_over_rsquared * LAL_GMSUN_SI * 4 / LAL_C_SI / LAL_PC_SI / LAL_PC_SI;
84
85 /* the waveform number is interpreted as the seed for GSL's
86 * Mersenne twister random number generator */
87 gsl_rng *rng = gsl_rng_alloc(gsl_rng_mt19937);
88 if(!rng) {
89 XLALPrintError("%s(): failure creating random number generator\n", __func__);
91 }
92 gsl_rng_set(rng, sim_burst->waveform_number);
93
94 XLALPrintInfo("%s(): BTLWNB @ %9d.%09u s (GPS): f = %.16g Hz, df = %.16g Hz, dt = %.16g s, hdot^2 = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->frequency, sim_burst->bandwidth, sim_burst->duration, int_hdot_squared_dt);
95 if(XLALGenerateBandAndTimeLimitedWhiteNoiseBurst(hplus, hcross, sim_burst->duration, sim_burst->frequency, sim_burst->bandwidth, sim_burst->pol_ellipse_e, sim_burst->pol_ellipse_angle, int_hdot_squared_dt, delta_t, rng)) {
96 gsl_rng_free(rng);
98 }
99 gsl_rng_free(rng);
100 } else if(!strcmp(sim_burst->waveform, "StringCusp")) {
101 XLALPrintInfo("%s(): string cusp @ %9d.%09u s (GPS): A = %.16g, fhigh = %.16g Hz\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->amplitude, sim_burst->frequency);
102 if(XLALGenerateStringCusp(hplus, hcross, sim_burst->amplitude, sim_burst->frequency, delta_t))
104 } else if(!strcmp(sim_burst->waveform, "StringKink")) {
105 XLALPrintInfo("%s(): string kink @ %9d.%09u s (GPS): A = %.16g, fhigh = %.16g Hz\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->amplitude, sim_burst->frequency);
106 if(XLALGenerateStringKink(hplus, hcross, sim_burst->amplitude, sim_burst->frequency, delta_t))
108 } else if(!strcmp(sim_burst->waveform, "StringKinkKink")) {
109 XLALPrintInfo("%s(): string kinkkink @ %9d.%09u s (GPS): A = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->amplitude);
110 if(XLALGenerateStringKinkKink(hplus, hcross, sim_burst->amplitude, delta_t))
112 } else if(!strcmp(sim_burst->waveform, "SineGaussian")) {
113 XLALPrintInfo("%s(): sine-Gaussian @ %9d.%09u s (GPS): f = %.16g Hz, Q = %.16g, hrss = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->frequency, sim_burst->q, sim_burst->hrss);
114 if(XLALSimBurstSineGaussian(hplus, hcross, sim_burst->q, sim_burst->frequency, sim_burst->hrss, sim_burst->pol_ellipse_e, sim_burst->pol_ellipse_angle, delta_t))
116 } else if(!strcmp(sim_burst->waveform, "Gaussian")) {
117 XLALPrintInfo("%s(): Gaussian @ %9d.%09u s (GPS): duration = %.16g, hrss = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->duration, sim_burst->hrss);
118 if(XLALSimBurstGaussian(hplus, hcross, sim_burst->duration, sim_burst->hrss, delta_t))
120 } else if(!strcmp(sim_burst->waveform, "Impulse")) {
121 XLALPrintInfo("%s(): impulse @ %9d.%09u s (GPS): hpeak = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->amplitude);
122 if(XLALGenerateImpulseBurst(hplus, hcross, sim_burst->amplitude, delta_t))
124 } else if(!strcmp(sim_burst->waveform, "Cherenkov")) {
125 XLALPrintInfo("%s(): Cherenkov @ %9d.%09u s (GPS): length = %.16g\n", __func__, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, sim_burst->bandwidth);
126 if(XLALSimBurstCherenkovRadiation(hplus, hcross, sim_burst->bandwidth, sim_burst->amplitude, delta_t))
128 } else {
129 /* unrecognized waveform */
130 XLALPrintError("%s(): error: unrecognized waveform \"%s\"\n", __func__, sim_burst->waveform);
132 }
133
134 /* add the time of the injection at the geocentre to the start
135 * times of the h+ and hx time series. after this, their epochs
136 * mark the start of those time series at the geocentre. */
137
138 if(!XLALGPSAddGPS(&(*hcross)->epoch, &sim_burst->time_geocent_gps) ||
139 !XLALGPSAddGPS(&(*hplus)->epoch, &sim_burst->time_geocent_gps)) {
140 XLALPrintError("%s(): bad geocentre time or waveform too long\n", __func__);
143 *hplus = *hcross = NULL;
145 }
146
147 /* done */
148
149 return 0;
150}
151
152
153/**
154 * Wrapper to iterate over the entries in a sim_burst linked list and
155 * inject them into a time series. Passing NULL for the response disables
156 * it (input time series is strain).
157 */
159 REAL8TimeSeries *series,
160 const SimBurst *sim_burst,
161 const TimeSlide *time_slide_table_head,
162 const COMPLEX16FrequencySeries *response
163)
164{
165 /* to be deduced from the time series' channel name */
166 const LALDetector *detector;
167 /* FIXME: fix the const entanglement so as to get rid of this */
168 LALDetector detector_copy;
169 /* + and x time series for injection waveform */
170 REAL8TimeSeries *hplus = NULL;
171 REAL8TimeSeries *hcross = NULL;
172 /* injection time series as added to detector's */
174 /* skip injections whose geocentre times are more than this many
175 * seconds outside of the target time series */
176 const double injection_window = 100.0;
177
178 /* turn the first two characters of the channel name into a
179 * detector */
180
182 if(!detector)
184 XLALPrintInfo("%s(): channel name is '%s', instrument appears to be '%s'\n", __func__, series->name, detector->frDetector.prefix);
185 detector_copy = *detector;
186
187 /* iterate over injections */
188
189 for(; sim_burst; sim_burst = sim_burst->next) {
190 LIGOTimeGPS time_geocent_gps;
191 const TimeSlide *time_slide_row;
192
193 /* determine the offset to be applied to this injection */
194
195 time_slide_row = XLALTimeSlideConstGetByIDAndInstrument(time_slide_table_head, sim_burst->time_slide_id, detector->frDetector.prefix);
196 if(!time_slide_row) {
197 XLALPrintError("%s(): cannot find time shift offset for injection 'sim_burst:simulation_id:%ld'. need 'time_slide:time_slide_id:%ld' for instrument '%s'", __func__, sim_burst->simulation_id, sim_burst->time_slide_id, detector->frDetector.prefix);
199 }
200
201 /* skip injections whose "times" are too far outside of the
202 * target time series */
203
204 time_geocent_gps = sim_burst->time_geocent_gps;
205 XLALGPSAdd(&time_geocent_gps, -time_slide_row->offset);
206 if(XLALGPSDiff(&series->epoch, &time_geocent_gps) > injection_window || XLALGPSDiff(&time_geocent_gps, &series->epoch) > (series->data->length * series->deltaT + injection_window))
207 continue;
208 XLALPrintInfo("%s(): injection 'sim_burst:simulation_id:%ld' in '%s' at %d.%09u s (GPS) will be shifted by %.16g s to %d.%09u s (GPS)\n", __func__, sim_burst->simulation_id, series->name, sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, -time_slide_row->offset, time_geocent_gps.gpsSeconds, time_geocent_gps.gpsNanoSeconds);
209
210 /* construct the h+ and hx time series for the injection
211 * waveform. */
212
213 if(XLALGenerateSimBurst(&hplus, &hcross, sim_burst, series->deltaT))
215#if 0
216 {
217 char name[100];
218 FILE *f;
219 unsigned i;
220 sprintf(name, "%d.%09u_%s.txt", sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, series->name);
221 f = fopen(name, "w");
222 for(i = 0; i < hplus->data->length; i++) {
223 LIGOTimeGPS t = hplus->epoch;
224 XLALGPSAdd(&t, i * hplus->deltaT);
225 fprintf(f, "%.16g %.16g %.16g\n", XLALGPSGetREAL8(&t), hplus->data->data[i], hcross->data->data[i]);
226 }
227 fclose(f);
228 }
229#endif
230
231 /* project the wave onto the detector to produce the strain
232 * in the detector. */
233
234 h = XLALSimDetectorStrainREAL8TimeSeries(hplus, hcross, sim_burst->ra, sim_burst->dec, sim_burst->psi, &detector_copy);
237 hplus = hcross = NULL;
238 if(!h)
240
241 /* shift the waveform by the time slide offset */
242
243 XLALGPSAdd(&h->epoch, -time_slide_row->offset);
244#if 0
245 {
246 char name[100];
247 FILE *f;
248 unsigned i;
249 sprintf(name, "%d.%09u_%s.txt", sim_burst->time_geocent_gps.gpsSeconds, sim_burst->time_geocent_gps.gpsNanoSeconds, series->name);
250 f = fopen(name, "w");
251 for(i = 0; i < h->data->length; i++) {
252 LIGOTimeGPS t = h->epoch;
253 XLALGPSAdd(&t, i * h->deltaT);
254 fprintf(f, "%d.%09u %.16g\n", t.gpsSeconds, t.gpsNanoSeconds, h->data->data[i]);
255 }
256 fclose(f);
257 }
258#endif
259
260 /* add the injection strain time series to the detector
261 * data */
262
263 if(XLALSimAddInjectionREAL8TimeSeries(series, h, response)) {
266 }
268 }
269
270 /* done */
271
272 return 0;
273}
const TimeSlide * XLALTimeSlideConstGetByIDAndInstrument(const TimeSlide *, long, const char *)
#define fprintf
const char *const name
double i
const char * detector
#define LAL_C_SI
#define LAL_GMSUN_SI
#define LAL_PC_SI
int XLALSimBurstSineGaussian(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, REAL8 Q, REAL8 centre_frequency, REAL8 hrss, REAL8 eccentricity, REAL8 phase, REAL8 delta_t)
int XLALGenerateStringKinkKink(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, REAL8 amplitude, REAL8 delta_t)
int XLALGenerateBandAndTimeLimitedWhiteNoiseBurst(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, REAL8 duration, REAL8 frequency, REAL8 bandwidth, REAL8 eccentricity, REAL8 phase, REAL8 int_hdot_squared, REAL8 delta_t, gsl_rng *rng)
int XLALSimBurstGaussian(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, REAL8 duration, REAL8 hrss, REAL8 delta_t)
int XLALGenerateImpulseBurst(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, REAL8 hpeak, REAL8 delta_t)
int XLALGenerateStringKink(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, REAL8 amplitude, REAL8 f_high, REAL8 delta_t)
int XLALGenerateStringCusp(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, REAL8 amplitude, REAL8 f_high, REAL8 delta_t)
int XLALSimBurstCherenkovRadiation(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, double source_length, double dE_over_dA, double deltaT)
const LALDetector * XLALDetectorPrefixToLALDetector(const char *string)
REAL8TimeSeries * XLALSimDetectorStrainREAL8TimeSeries(const REAL8TimeSeries *hplus, const REAL8TimeSeries *hcross, REAL8 right_ascension, REAL8 declination, REAL8 psi, const LALDetector *detector)
int XLALSimAddInjectionREAL8TimeSeries(REAL8TimeSeries *target, REAL8TimeSeries *h, const COMPLEX16FrequencySeries *response)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
int int int XLALPrintInfo(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_ERROR(...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_ENOMEM
XLAL_EFUNC
XLAL_EINVAL
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
LIGOTimeGPS * XLALGPSAddGPS(LIGOTimeGPS *epoch, const LIGOTimeGPS *dt)
REAL8 XLALGPSDiff(const LIGOTimeGPS *t1, const LIGOTimeGPS *t0)
int XLALGenerateSimBurst(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, const SimBurst *sim_burst, double delta_t)
Generate the + and x time series for a single sim_burst table row.
Definition: GenerateBurst.c:67
int XLALBurstInjectSignals(REAL8TimeSeries *series, const SimBurst *sim_burst, const TimeSlide *time_slide_table_head, const COMPLEX16FrequencySeries *response)
Wrapper to iterate over the entries in a sim_burst linked list and inject them into a time series.
INT4 gpsNanoSeconds
REAL8Sequence * data
LIGOTimeGPS epoch
CHAR name[LALNameLength]
REAL8 * data
char waveform[LIGOMETA_WAVEFORM_MAX]
struct tagSimBurst * next
LIGOTimeGPS time_geocent_gps
REAL8 amplitude
REAL8 pol_ellipse_angle
unsigned long waveform_number
REAL8 frequency
long time_slide_id
long simulation_id
REAL8 psi
REAL8 duration
REAL8 egw_over_rsquared
REAL8 ra
REAL8 bandwidth
REAL8 pol_ellipse_e
REAL8 dec
REAL8 hrss
REAL8 offset