Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALSimulation 6.2.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
detector_strain.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2015 Jolien Creighton
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 * The following command injects waveform.dat directly overhead in Hanford:
22 *
23 * lalsim-detector-strain --detector-prefix H1 --gps-time 1079467252.35 --ra 0 --dec 46.45515 --psi 324 --verbose waveform.dat
24 * and this injects it directly below:
25 *
26 * lalsim-detector-strain --detector-prefix H1 --gps-time 1079467252.35 --ra 180 --dec -46.45515 --psi -324 --verbose waveform.dat
27 */
28
29/**
30 * @defgroup lalsim_detector_strain lalsim-detector-strain
31 * @ingroup lalsimulation_programs
32 *
33 * @brief Computes the strain on a detector given a gravitational waveform
34 *
35 * ### Synopsis
36 *
37 * lalsim-detector-strain [options] [file]
38 *
39 * ### Description
40 *
41 * The `lalsim-detector-strain` utility converts a gravitational waveform
42 * in `file` or standard input if `file` is absent into an induced detector
43 * strain on a specified detector. The input data should be in a
44 * three-column ascii format with the first column being the time of each
45 * sample, the second column being the plus-polarization of the gravitational
46 * waveform, and the third column being the cross-polarization of the
47 * gravitational waveform. The timestamps on the input file should be
48 * centered time 0 (conventions vary: some waveforms will end near time 0;
49 * others will be centered on time 0). The output is written to standard
50 * output in two column ascii format where the first column is the GPS
51 * timestamp of each sample and the second column is the strain induced on
52 * the detector.
53 *
54 * ### Options
55 *
56 * <DL>
57 * <DT>`-h`, `--help`</DT>
58 * <DD>print a help message and exit</DD>
59 * <DT>`-v`, `--verbose`</DT>
60 * <DD>verbose output</DD>
61 * <DT>`-r`, `--radians`</DT>
62 * <DD>use radians rather than decimal degrees</DD>
63 * <DT>`-O`, `--overhead`</DT>
64 * <DD>signal from directly overhead</DD>
65 * <DT>`-D` PREFIX, `--detector-prefix=`PREFIX</DT>
66 * <DD>(required unless overhead) detector prefix (e.g., 'H1', 'L1', 'V1')</DD>
67 * <DT>`-t` EPOCH, `--gps-time=`EPOCH</DT>
68 * <DD>(required) time of arrival at earth geocenter (or at detector if
69 * overhead): this is added to the timestamp of the input data, which should be
70 * an waveform about time = 0</DD>
71 * <DT>`-a` RA, `--right-ascension=`RA</DT>
72 * <DD>(required unless overhead) right ascension in H:M:S format or decimal
73 * degrees</DD>
74 * <DT>`-d` DEC, `--declination=`DEC</DT>
75 * <DD>(required unless overhead) declination in D:M:S format or decimal
76 * degrees</DD>
77 * <DT>`-p` PSI,` --polarization-angle=`PSI</DT>
78 * <DD>(required) polarization angle in degrees</DD>
79 * </DL>
80 *
81 * ### Environment
82 *
83 * The `LAL_DEBUG_LEVEL` can used to control the error and warning reporting of
84 * `lalsim-detector-strain`. Common values are: `LAL_DEBUG_LEVEL=0` which
85 * suppresses error messages, `LAL_DEBUG_LEVEL=1` which prints error messages
86 * alone, `LAL_DEBUG_LEVEL=3` which prints both error messages and warning
87 * messages, and `LAL_DEBUG_LEVEL=7` which additionally prints informational
88 * messages.
89 *
90 * ### Exit Status
91 *
92 * The `lalsim-detector-strain` utility exits 0 on success, and >0 if an error
93 * occurs.
94 *
95 * ### Example
96 *
97 * The command:
98 *
99 * lalsim-inspiral | lalsim-detector-strain -D H1 -a 1:23:45 -d 45.0 -p 30.0 -t 1000000000
100 *
101 * outputs to standard output in two-column ascii format the strain induced
102 * on the LHO observatory detector from a 1.4 solar mass + 1.4 solar mass
103 * binary inspiral at 1 Mpc distance originating from source at
104 * right-ascension 1h 23m 45s, declination 45 degrees, and polarization angle
105 * 30 degrees that arrives at the geocenter at GPS time 1000000000. The
106 * first column contains the GPS time of each sample and the second column
107 * contains the induced detector strain at that time.
108 *
109 * The command:
110 *
111 * lalsim-inspiral | lalsim-detector-strain -O -p 0.0 -t 1000000000
112 *
113 * produces a similar output, but now for a signal coming from directly
114 * overhead of a arbitrary detector with polarization angle 0 (optimally
115 * oriented); the GPS arrival time is now at the detector location.
116 */
117
118
119#include <limits.h>
120#include <math.h>
121#include <stdio.h>
122#include <stdlib.h>
123#include <string.h>
124#include <time.h>
125
126#include <lal/LALConstants.h>
127#include <lal/LALgetopt.h>
128#include <lal/LALDatatypes.h>
129#include <lal/LALDetectors.h>
130#include <lal/TimeSeries.h>
131#include <lal/Units.h>
132#include <lal/Date.h>
133#include <lal/DetResponse.h>
134#include <lal/TimeDelay.h>
135#include <lal/LALSimulation.h>
136
137#define INVALID_EPOCH { .gpsSeconds = LAL_INT4_MAX, .gpsNanoSeconds = LAL_INT4_MAX }
138
139/*
140 * Timezones for certain detectors.
141 *
142 * PSTPDT: Pacific Time
143 * PST (standard): UTC-8
144 * PDT (daylight): UTC-7
145 * Daylight begin: Second Sunday of March at 02:00 PST
146 * Daylight end: Last Sunday of October at 02:00 PDT
147 *
148 * CSTCDT: Pacific Time
149 * PST (standard): UTC-6
150 * PDT (daylight): UTC-5
151 * Daylight begin: Second Sunday of March at 02:00 PST
152 * Daylight end: Last Sunday of October at 02:00 PDT
153 *
154 * CETCEST: Central Europe Time
155 * CET (standard): UTC+1
156 * CEST (daylight): UTC+2
157 * Daylight begin: Last Sunday of March at 02:00 CET = 01:00 UTC
158 * Daylight end: Last Sunday of October at 03:00 CEST = 01:00 UTC
159 *
160 * JST: Japanese Standard Time
161 * JST: UTC+9
162 * No daylight savings time
163 */
164#define TZ_PSTPDT "PST08:00:00PDT07:00:00,M3.2.0/02:00:00,M11.1.0/02:00:00"
165#define TZ_CSTCDT "CST06:00:00CDT05:00:00,M3.2.0/02:00:00,M11.1.0/02:00:00"
166#define TZ_CETCEST "CET-01:00:00CEST-02:00:00,M3.5.0/02:00:00,M10.5.0/03:00:00"
167#define TZ_JST "JST-09:00:00"
168
169#define TZ_LHO TZ_PSTPDT
170#define TZ_LLO TZ_CSTCDT
171#define TZ_GEO TZ_CETCEST
172#define TZ_VIRGO TZ_CETCEST
173#define TZ_KAGRA TZ_JST
174#define TZ_TAMA TZ_JST
175
176struct params {
178 FILE *fp;
182 double ra;
183 double dec;
184 double psi;
185};
186int printparams(struct params p);
187char *sitetime(char *s, size_t size, time_t * timer, int site);
188double strtora(const char *s, int degrees);
189double strtodec(const char *s, int degrees);
190int fputra(double ra, FILE * fp);
191int fputdec(double ra, FILE * fp);
192struct params parseargs(int argc, char **argv);
193int usage(const char *program);
194int readdata(REAL8TimeSeries ** hplus, REAL8TimeSeries ** hcross, FILE * fp);
195
196int main(int argc, char *argv[])
197{
198 char tstr[32]; // string to hold GPS time -- 31 characters is enough
199 REAL8TimeSeries *hplus = NULL;
200 REAL8TimeSeries *hcross = NULL;
202 struct params p;
203 size_t j;
204
206
207 p = parseargs(argc, argv);
208 printparams(p);
209
210 readdata(&hplus, &hcross, p.fp);
211
212 /* shift injection to required epoch */
213 XLALGPSAddGPS(&hplus->epoch, &p.epoch);
214 XLALGPSAddGPS(&hcross->epoch, &p.epoch);
215
216 /* compute detector strain */
217 if (p.overhead) {
218 double cos2psi = cos(2.0 * p.psi);
219 double sin2psi = sin(2.0 * p.psi);
220 /* ra and dec are ignored parameters; psi is used to mix plus and
221 * cross polarizations; note sign convention has F+ = -1 and Fx = 0
222 * for psi = 0, and F+ = 0, Fx = 1 for psi = 45 degrees:
223 * see Sec. "The Gravitational Wave Tensor in the Earth Fixed Frame",
224 * LIGO-T010110 https://dcc.ligo.org/LIGO-T010110/public */
225 h = XLALCreateREAL8TimeSeries("STRAIN", &hplus->epoch, hplus->f0, hplus->deltaT, &hplus->sampleUnits, hplus->data->length);
226 for (j = 0; j < h->data->length; ++j)
227 h->data->data[j] = -hplus->data->data[j] * cos2psi + hcross->data->data[j] * sin2psi;
228 fprintf(stdout, "# time (s)\tSTRAIN (strain)\n");
229 } else {
230 h = XLALSimDetectorStrainREAL8TimeSeries(hplus, hcross, p.ra, p.dec, p.psi, p.detector);
231 fprintf(stdout, "# time (s)\t%s:STRAIN (strain)\n", p.detector->frDetector.prefix);
232 }
233
234 for (j = 0; j < h->data->length; ++j) {
235 LIGOTimeGPS t = h->epoch;
236 fprintf(stdout, "%s\t%.18e\n", XLALGPSToStr(tstr, XLALGPSAdd(&t, j * h->deltaT)), h->data->data[j]);
237 }
238
243 return 0;
244}
245
246int printparams(struct params p)
247{
248 if (p.verbose) {
249 char tstr[32]; // string to hold GPS time -- 31 characters is enough
250 struct tm utc = {.tm_sec = 0 };
251 time_t timer;
252 char date[64];
253 double gmst_rad = XLALGreenwichMeanSiderealTime(&p.epoch);
254 if (p.overhead) {
255 XLALGPSToUTC(&utc, round(XLALGPSGetREAL8(&p.epoch)));
256 timer = round(XLALGPSGetREAL8(&p.epoch)) + XLAL_EPOCH_UNIX_GPS;
257 strftime(date, sizeof(date), "%c %Z", &utc);
258 fputs("detector arrival time: GPS = ", stderr);
259 fputs(XLALGPSToStr(tstr, &p.epoch), stderr);
260 fputs("\n", stderr);
261 fputs("coordinated universal time: ", stderr);
262 fprintf(stderr, "%s", date);
263 fputs("\n", stderr);
264 fputs("Greenwich mean sidereal time: HH:MM:SS = ", stderr);
265 fputra(gmst_rad, stderr);
266 fprintf(stderr, " (%g deg, %g rad)", fmod(gmst_rad, 2.0 * LAL_PI) / LAL_PI_180, fmod(gmst_rad, 2.0 * LAL_PI));
267 fputs("\n", stderr);
268 fputs("polarization angle: ", stderr);
269 fprintf(stderr, "%g deg, %g rad", p.psi / LAL_PI_180, p.psi);
270 fputs("\n", stderr);
271 } else {
272 LIGOTimeGPS epoch = p.epoch;
273 double longitude = p.detector->frDetector.vertexLongitudeRadians;
274 double latitude = p.detector->frDetector.vertexLatitudeRadians;
275 double lmst_rad = gmst_rad + longitude;
276 double ha = lmst_rad - p.ra;
277 double altitude = asin(sin(p.dec) * sin(latitude) + cos(p.dec) * cos(latitude) * cos(ha));
278 double azimuth = -atan2(cos(p.dec) * sin(ha), sin(p.dec) * cos(latitude) - cos(p.dec) * sin(latitude) * cos(ha));
279 double fplus, fcross;
280 double dt = XLALTimeDelayFromEarthCenter(p.detector->location, p.ra, p.dec, &p.epoch);
282 XLALGPSToUTC(&utc, round(XLALGPSGetREAL8(&p.epoch)));
283 timer = round(XLALGPSGetREAL8(&p.epoch)) + XLAL_EPOCH_UNIX_GPS;
284 XLALComputeDetAMResponse(&fplus, &fcross, p.detector->response, p.ra, p.dec, p.psi, gmst_rad);
285 strftime(date, sizeof(date), "%c %Z", &utc);
286 fputs("geocentric arrival time: GPS = ", stderr);
287 fputs(XLALGPSToStr(tstr, &p.epoch), stderr);
288 fputs("\n", stderr);
289 fputs("coordinated universal time: ", stderr);
290 fprintf(stderr, "%s", date);
291 fputs("\n", stderr);
292 fputs("Greenwich mean sidereal time: HH:MM:SS = ", stderr);
293 fputra(gmst_rad, stderr);
294 fprintf(stderr, " (%g deg, %g rad)", fmod(gmst_rad, 2.0 * LAL_PI) / LAL_PI_180, fmod(gmst_rad, 2.0 * LAL_PI));
295 fputs("\n", stderr);
296 fputs("right ascension: HH:MM:SS = ", stderr);
297 fputra(p.ra, stderr);
298 fprintf(stderr, " (%g deg, %g rad)", p.ra / LAL_PI_180, p.ra);
299 fputs("\n", stderr);
300 fputs("declination: DD:MM:SS = ", stderr);
301 fputdec(p.dec, stderr);
302 fprintf(stderr, " (%g deg, %g rad)", p.dec / LAL_PI_180, p.dec);
303 fputs("\n", stderr);
304 fputs("polarization angle: ", stderr);
305 fprintf(stderr, "%g deg, %g rad", p.psi / LAL_PI_180, p.psi);
306 fputs("\n", stderr);
307 fputs("detector: ", stderr);
308 fprintf(stderr, "%s", p.detector->frDetector.name);
309 fputs("\n", stderr);
310 fputs("time delay from Earth center: ", stderr);
311 fprintf(stderr, "%+f s", dt);
312 fputs("\n", stderr);
313 fputs("arrival time at detector: GPS = ", stderr);
314 fputs(XLALGPSToStr(tstr, &epoch), stderr);
315 fputs("\n", stderr);
316 fputs("local time: ", stderr);
317 fprintf(stderr, "%s", sitetime(tstr, sizeof(tstr), &timer, *p.detector->frDetector.prefix));
318 fputs("\n", stderr);
319 fputs("latitude North: DD:MM:SS = ", stderr);
320 fputdec(latitude, stderr);
321 fprintf(stderr, " (%g deg, %g rad)", latitude / LAL_PI_180, latitude);
322 fputs("\n", stderr);
323 fputs("longitude East: HH:MM:SS = ", stderr);
324 fputra(longitude, stderr);
325 fprintf(stderr, " (%g deg, %g rad)", longitude / LAL_PI_180, longitude);
326 fputs("\n", stderr);
327 fputs("local mean sidereal time: HH:MM:SS = ", stderr);
328 fputra(lmst_rad, stderr);
329 fprintf(stderr, " (%g deg, %g rad)", fmod(lmst_rad, 2.0 * LAL_PI) / LAL_PI_180, fmod(lmst_rad, 2.0 * LAL_PI));
330 fputs("\n", stderr);
331 fputs("hour angle: HH:MM:SS = ", stderr);
332 fputra(ha, stderr);
333 fprintf(stderr, " (%g deg, %g rad)", fmod(ha, 2.0 * LAL_PI) / LAL_PI_180, fmod(ha, 2.0 * LAL_PI));
334 fputs("\n", stderr);
335 fputs("altitude: ", stderr);
336 fprintf(stderr, "%g deg, %g rad", altitude / LAL_PI_180, altitude);
337 fputs("\n", stderr);
338 fputs("azimuth West of North: ", stderr);
339 fprintf(stderr, "%g deg, %g rad", azimuth / LAL_PI_180, azimuth);
340 fputs("\n", stderr);
341 fputs("detector antenna response: ", stderr);
342 fprintf(stderr, "F+ = %g, Fx = %g", fplus, fcross);
343 fputs("\n", stderr);
344 }
345 }
346 return 0;
347}
348
349char *sitetime(char *s, size_t size, time_t * timer, int site)
350{
351 static char tz_lho[] = TZ_LHO;
352 static char tz_llo[] = TZ_LLO;
353 static char tz_geo[] = TZ_GEO;
354 static char tz_virgo[] = TZ_VIRGO;
355 static char tz_kagra[] = TZ_KAGRA;
356 static char tz_tama[] = TZ_TAMA;
357 char *tz_orig = getenv("TZ");
358 char *tz_site = tz_orig;
359 switch (site) {
360 case 'H':
361 tz_site = tz_lho;
362 break;
363 case 'L':
364 tz_site = tz_llo;
365 break;
366 case 'G':
367 tz_site = tz_geo;
368 break;
369 case 'V':
370 tz_site = tz_virgo;
371 break;
372 case 'K':
373 tz_site = tz_kagra;
374 break;
375 case 'T':
376 tz_site = tz_tama;
377 break;
378 default:
379 fprintf(stderr, "warning: unknown time zone - using localtime\n");
380 tz_site = tz_orig;
381 break;
382 }
383 setenv("TZ", tz_site, 1);
384 strftime(s, size, "%c %Z", localtime(timer));
385 if (tz_orig)
386 setenv("TZ", tz_orig, 1);
387 else
388 unsetenv("TZ");
389 return s;
390}
391
392int readdata(REAL8TimeSeries ** hplus, REAL8TimeSeries ** hcross, FILE * fp)
393{
394 const size_t block = 1024;
395 LIGOTimeGPS start;
397 double dt;
398 double *hp = NULL;
399 double *hc = NULL;
400 size_t bufsz = 0;
401 size_t n, l;
402 char line[LINE_MAX];
403 char t0[LINE_MAX];
404 char t1[LINE_MAX];
405
406 for (l = 0, n = 0; fgets(line, sizeof(line), fp); ++l) {
407 int c;
408 if (*line == '#')
409 continue;
410 if (n == bufsz) { /* allocate more memory */
411 bufsz += block;
412 hp = realloc(hp, bufsz * sizeof(*hp));
413 hc = realloc(hc, bufsz * sizeof(*hc));
414 }
415 c = sscanf(line, "%s %le %le", n ? t1 : t0, hp + n, hc + n);
416 if (c != 3) {
417 fprintf(stderr, "error: format error on line %zd: %s\n", l, line);
418 exit(1);
419 }
420 ++n;
421 }
422 hp = realloc(hp, n * sizeof(*hp));
423 hc = realloc(hc, n * sizeof(*hp));
424
425 XLALStrToGPS(&start, t0, NULL);
426 XLALStrToGPS(&end, t1, NULL);
427 dt = XLALGPSDiff(&end, &start) / (n - 1);
428 *hplus = XLALCreateREAL8TimeSeries("h_plus", &start, 0.0, dt, &lalStrainUnit, n);
429 *hcross = XLALCreateREAL8TimeSeries("h_cross", &start, 0.0, dt, &lalStrainUnit, n);
430 memcpy((*hplus)->data->data, hp, n * sizeof(*hp));
431 memcpy((*hcross)->data->data, hc, n * sizeof(*hc));
432
433 free(hp);
434 free(hc);
435 return 0;
436}
437
438double strtora(const char *string, int degrees)
439{
440 double h = 0, m = 0, s = 0;
441 double ra;
442 int c;
443
444 /* try H:M:S format first */
445 if (strchr(string, ':'))
446 c = sscanf(string, "%lf:%lf:%lf", &h, &m, &s);
447 else {
448 ra = atof(string);
449 if (degrees)
450 ra *= LAL_PI_180;
451 goto done;
452 }
453
454 if (c == 0) {
455 fprintf(stderr, "error parsing option --right-ascension with argument %s\n", string);
456 exit(1);
457 }
458 m = copysign(m, h) / 60.0;
459 s = copysign(s, h) / 3600.0;
460 ra = (h + m + s) * 15.0 * LAL_PI_180;
461
462 done:
463 ra = fmod(ra, 2.0 * LAL_PI);
464 if (ra < 0.0)
465 ra += 2.0 * LAL_PI;
466 return ra;
467}
468
469double strtodec(const char *string, int degrees)
470{
471 double d = 0, m = 0, s = 0;
472 double dec;
473 int c;
474
475 /* try D:M:S format first */
476 if (strchr(string, ':'))
477 c = sscanf(string, "%lf:%lf:%lf", &d, &m, &s);
478 else {
479 dec = atof(string);
480 if (degrees)
481 dec *= LAL_PI_180;
482 goto done;
483 }
484
485 if (c == 0) {
486 fprintf(stderr, "error parsing option --declination with argument %s\n", string);
487 exit(1);
488 }
489 m = copysign(m, d) / 60.0;
490 s = copysign(s, d) / 3600.0;
491 dec = (d + m + s) * LAL_PI_180;
492 done:
493 dec = fmod(dec + LAL_PI, 2.0 * LAL_PI) - LAL_PI;
494 return dec;
495}
496
497/* output right ascension in hms format */
498int fputra(double ra, FILE * fp)
499{
500 double h, m, s;
501 ra = fmod(ra, 2.0 * LAL_PI);
502 if (ra < 0.0)
503 ra += 2.0 * LAL_PI;
504 ra /= 15.0 * LAL_PI_180; /* convert to hours */
505 m = 60.0 * modf(ra, &h);
506 s = 60.0 * modf(m, &s);
507 return fprintf(fp, "%02d:%02d:%04.1f", (int)h, (int)fabs(m), fabs(s));
508}
509
510/* output right ascension in hms format */
511int fputdec(double dec, FILE * fp)
512{
513 double d, m, s;
514 dec = fmod(dec + LAL_PI, 2.0 * LAL_PI) - LAL_PI;
515 dec /= LAL_PI_180; /* convert to degrees */
516 m = 60.0 * modf(dec, &d);
517 s = 60.0 * modf(m, &s);
518 return fprintf(fp, "%c%02d:%02d:%04.1fs", dec < 0 ? '-' : '+', (int)fabs(d), (int)fabs(m), fabs(s));
519}
520
521struct params parseargs(int argc, char **argv)
522{
523 LIGOTimeGPS invalid_epoch = INVALID_EPOCH;
524 char *ra_string = NULL;
525 char *dec_string = NULL;
526 char *psi_string = NULL;
527 int degrees = 1;
528 struct params p = {
529 .verbose = 0,
530 .fp = stdin,
531 .overhead = 0,
532 .detector = NULL,
533 .epoch = invalid_epoch,
534 .ra = HUGE_VAL,
535 .dec = HUGE_VAL,
536 .psi = HUGE_VAL,
537 };
538 struct LALoption long_options[] = {
539 {"help", no_argument, 0, 'h'},
540 {"verbose", no_argument, 0, 'v'},
541 {"radians", no_argument, 0, 'r'},
542 {"overhead", no_argument, 0, 'O'},
543 {"detector-prefix", required_argument, 0, 'D'},
544 {"gps-time", required_argument, 0, 't'},
545 {"right-ascension", required_argument, 0, 'a'},
546 {"ra", required_argument, 0, 'a'},
547 {"alpha", required_argument, 0, 'a'},
548 {"declination", required_argument, 0, 'd'},
549 {"dec", required_argument, 0, 'd'},
550 {"delta", required_argument, 0, 'd'},
551 {"polarization-angle", required_argument, 0, 'p'},
552 {"psi", required_argument, 0, 'p'},
553 {0, 0, 0, 0}
554 };
555 char args[] = "hvrOD:t:a:d:p:";
556 int fail = 0;
557 int d;
558 while (1) {
559 int option_index = 0;
560 int c;
561 c = LALgetopt_long_only(argc, argv, args, long_options, &option_index);
562 if (c == -1) /* end of options */
563 break;
564 switch (c) {
565 case 0: /* if option set a flag, nothing else to do */
566 if (long_options[option_index].flag)
567 break;
568 else {
569 fprintf(stderr, "error parsing option %s with argument %s\n", long_options[option_index].name, LALoptarg);
570 exit(1);
571 }
572 case 'h': /* help */
573 usage(argv[0]);
574 exit(0);
575 case 'v': /* verbose */
576 p.verbose = 1;
577 break;
578 case 'r': /* radians */
579 degrees = 0;
580 break;
581 case 'O': /* overhead */
582 p.overhead = 1;
583 break;
584 case 'D': /* detector-prefix */
585 for (d = 0; d < LAL_NUM_DETECTORS; ++d) {
586 if (strcmp(LALoptarg, lalCachedDetectors[d].frDetector.prefix) == 0) {
587 p.detector = lalCachedDetectors + d;
588 break;
589 }
590 }
591 break;
592 case 't': /* gps-time */
593 XLALStrToGPS(&p.epoch, LALoptarg, NULL);
594 break;
595 case 'a': /* right-ascension */
596 ra_string = LALoptarg;
597 break;
598 case 'd': /* right-ascension */
599 dec_string = LALoptarg;
600 break;
601 case 'p': /* polarization-angle */
602 psi_string = LALoptarg;
603 break;
604 case '?':
605 default:
606 fprintf(stderr, "unknown error while parsing options\n");
607 exit(1);
608 }
609 }
610 switch (argc - LALoptind) {
611 case 0:
612 break;
613 case 1: /* the input file name */
614 p.fp = fopen(argv[LALoptind], "r");
615 if (!p.fp) {
616 fprintf(stderr, "error: could not open file %s\n", argv[LALoptind]);
617 exit(1);
618 }
619
620 break;
621 default:
622 fprintf(stderr, "extraneous command line arguments:\n");
623 while (++LALoptind < argc)
624 fprintf(stderr, "%s\n", argv[LALoptind]);
625 exit(1);
626 }
627
628 /* make sure all required arguments have been specified */
629 if (XLALGPSCmp(&p.epoch, &invalid_epoch) == 0) {
630 fprintf(stderr, "error: unspecified arrival time\n");
631 fail = 1;
632 }
633
634 if (psi_string) {
635 p.psi = atof(psi_string);
636 if (degrees)
637 p.psi *= LAL_PI_180;
638 } else {
639 fprintf(stderr, "error: unspecified polarization angle\n");
640 fail = 1;
641 }
642
643 if (p.overhead) {
644 /* remaining parameters are ignored */
645 if (p.detector)
646 fprintf(stderr, "warning: ignoring detector for overhead injection\n");
647 if (ra_string)
648 fprintf(stderr, "warning: ignoring right ascension for overhead injection\n");
649 if (dec_string)
650 fprintf(stderr, "warning: ignoring declination for overhead injection\n");
651 goto done;
652 }
653
654 if (p.detector == NULL) {
655 fprintf(stderr, "error: unspecified detector prefix\n");
656 fprintf(stderr, "recognized detector prefixes are:\n");
657 for (d = 0; d < LAL_NUM_DETECTORS; ++d)
658 fprintf(stderr, "\t%s: %s\n", lalCachedDetectors[d].frDetector.prefix, lalCachedDetectors[d].frDetector.name);
659 fail = 1;
660 }
661
662 if (ra_string)
663 p.ra = strtora(ra_string, degrees);
664 else {
665 fprintf(stderr, "error: unspecified right ascension\n");
666 fail = 1;
667 }
668
669 if (dec_string)
670 p.dec = strtodec(dec_string, degrees);
671 else {
672 fprintf(stderr, "error: unspecified declination\n");
673 fail = 1;
674 }
675
676done:
677 if (fail)
678 exit(1);
679
680 return p;
681}
682
683int usage(const char *program)
684{
685 /* *INDENT-OFF* */
686 fprintf(stderr, "\
687usage: %s [options] [file]\n\
688options:\n\
689 -h, --help print this message and exit\n\
690 -v, --verbose verbose output\n\
691 -r, --radians use radians rather than decimal degrees\n\
692 -O, --overhead signal from directly overhead\n\
693 -D PREFIX, --detector-prefix=PREFIX (required unless overhead)\n\
694 detector prefix (e.g., 'H1', 'L1', 'V1')\n\
695 -t EPOCH, --gps-time=EPOCH (required)\n\
696 time of arrival at earth geocenter (or at detector if overhead):\n\
697 this is added to the timestamp of the input data,\n\
698 which should be an waveform about time = 0\n\
699 -a RA, --right-ascension=RA (required unless overhead)\n\
700 right ascension in H:M:S format or decimal degrees\n\
701 -d DEC, --declination=DEC (required unless overhead)\n\
702 declination in D:M:S format or decimal degrees\n\
703 -p PSI, --polarization-angle=PSI (required)\n\
704 polarization angle in degrees\n\
705", program);
706 /* *INDENT-ON* */
707 return 0;
708}
int XLALStrToGPS(LIGOTimeGPS *t, const char *nptr, char **endptr)
void LALCheckMemoryLeaks(void)
static vector d(const double L_norm, const double J_norm, const vector roots)
Internal function that returns the coefficients "d_0", "d_2" and "d_4" from 1703.03967 corresponding ...
#define c
const char * name
#define LINE_MAX
#define char
Definition: LALSimUnicorn.c:14
int LALgetopt_long_only(int argc, char *const *argv, const char *options, const struct LALoption *long_options, int *opt_index)
int LALoptind
char * LALoptarg
#define no_argument
#define required_argument
#define fprintf
int s
Definition: bh_qnmode.c:137
int l
Definition: bh_qnmode.c:135
double dt
Definition: bh_ringdown.c:113
#define TZ_LHO
int main(int argc, char *argv[])
double strtora(const char *s, int degrees)
double strtodec(const char *s, int degrees)
#define TZ_KAGRA
int fputdec(double ra, FILE *fp)
int usage(const char *program)
#define TZ_GEO
#define TZ_TAMA
int fputra(double ra, FILE *fp)
char * sitetime(char *s, size_t size, time_t *timer, int site)
#define INVALID_EPOCH
int readdata(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, FILE *fp)
#define TZ_LLO
struct params parseargs(int argc, char **argv)
#define TZ_VIRGO
int printparams(struct params p)
const LALDetector lalCachedDetectors[LAL_NUM_DETECTORS]
#define XLAL_EPOCH_UNIX_GPS
char * XLALGPSToStr(char *s, const LIGOTimeGPS *t)
void XLALComputeDetAMResponse(double *fplus, double *fcross, const REAL4 D[3][3], const double ra, const double dec, const double psi, const double gmst)
#define LAL_PI_180
#define LAL_PI
LAL_NUM_DETECTORS
REAL8TimeSeries * XLALSimDetectorStrainREAL8TimeSeries(const REAL8TimeSeries *hplus, const REAL8TimeSeries *hcross, REAL8 right_ascension, REAL8 declination, REAL8 psi, const LALDetector *detector)
Transforms the waveform polarizations into a detector strain.
static const INT4 m
REAL8 XLALTimeDelayFromEarthCenter(const double detector_earthfixed_xyz_metres[3], double source_right_ascension_radians, double source_declination_radians, const LIGOTimeGPS *gpstime)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
REAL8TimeSeries * XLALCreateREAL8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalStrainUnit
struct tm * XLALGPSToUTC(struct tm *utc, INT4 gpssec)
void XLALBacktraceErrorHandler(const char *func, const char *file, int line, int errnum)
XLALErrorHandlerType * XLALSetErrorHandler(XLALErrorHandlerType *newHandler)
REAL8 XLALGreenwichMeanSiderealTime(const LIGOTimeGPS *gpstime)
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
int XLALGPSCmp(const LIGOTimeGPS *t0, const LIGOTimeGPS *t1)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
LIGOTimeGPS * XLALGPSAddGPS(LIGOTimeGPS *epoch, const LIGOTimeGPS *dt)
REAL8 XLALGPSDiff(const LIGOTimeGPS *t1, const LIGOTimeGPS *t0)
char * program
Definition: inject.c:87
string date
end
p
LALFrDetector frDetector
CHAR name[LALNameLength]
int * flag
REAL8Sequence * data
LALUnit sampleUnits
LIGOTimeGPS epoch
REAL8 * data
Definition: burst.c:245
double ra
const LALDetector * detector
double dec
LIGOTimeGPS epoch
double psi
FILE * fp
enum @4 site
FILE * fp
LIGOTimeGPS epoch
Definition: unicorn.c:20