LALSimulation  5.4.0.1-89842e6
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 
176 struct params {
177  int verbose;
178  FILE *fp;
180  int overhead;
182  double ra;
183  double dec;
184  double psi;
185 };
186 int printparams(struct params p);
187 char *sitetime(char *s, size_t size, time_t * timer, int site);
188 double strtora(const char *s, int degrees);
189 double strtodec(const char *s, int degrees);
190 int fputra(double ra, FILE * fp);
191 int fputdec(double ra, FILE * fp);
192 struct params parseargs(int argc, char **argv);
193 int usage(const char *program);
194 int readdata(REAL8TimeSeries ** hplus, REAL8TimeSeries ** hcross, FILE * fp);
195 
196 int 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;
201  REAL8TimeSeries *h;
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 
246 int 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);
281  XLALGPSAdd(&epoch, dt);
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 
349 char *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 
392 int 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 
438 double 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 
469 double 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 */
498 int 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 */
511 int 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 
521 struct 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 
676 done:
677  if (fail)
678  exit(1);
679 
680  return p;
681 }
682 
683 int usage(const char *program)
684 {
685  /* *INDENT-OFF* */
686  fprintf(stderr, "\
687 usage: %s [options] [file]\n\
688 options:\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)
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)
REAL8TimeSeries * XLALCreateREAL8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
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)
LIGOTimeGPS * XLALGPSAddGPS(LIGOTimeGPS *epoch, const LIGOTimeGPS *dt)
int XLALGPSCmp(const LIGOTimeGPS *t0, const LIGOTimeGPS *t1)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
REAL8 XLALGPSDiff(const LIGOTimeGPS *t1, const LIGOTimeGPS *t0)
char * program
Definition: inject.c:87
list p
string date
end
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