LALFrame  3.0.4.1-fe68b98
vis.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2013 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  * @defgroup lalfr_vis lalfr-vis
22  * @ingroup lalframe_programs
23  *
24  * @brief Visualize frame data
25  *
26  * ### Synopsis
27  *
28  * lalfr-vis --channel=channel --frame-cache=cachefile --start-time=tstart --duration=deltat [--output=outfile] [--highpass=minfreq] [--lowpass=maxfreq] [--pad=padding] [--resample=srate] [--spectrum=resolution]
29  *
30  * lalfr-vis --channel=channel --frame-glob=globstring --start-time=tstart --duration=deltat [--output=outfile] [--highpass=minfreq] [--lowpass=maxfreq] [--pad=padding] [--resample=srate] [--spectrum=resolution]
31  *
32  *
33  * ### Description
34  *
35  * The `lalfr-vis` utility reads a requested interval
36  * [`tstart`,`tstart+deltat`) of `channel` data from frame files that are
37  * either indexed in the `cachefile` or matching the pattern `globstring` as
38  * described by `glob(3)`. The output is written to `outfile` and the format
39  * of the output is deter- mined by extension of `outfile` as described below.
40  * If `outfile` is not specified, the output is written to the standard output
41  * in two-column ascii format data.
42  *
43  * The `lalfr-vis` can optionally perform certain manipulations of the data
44  * that is read, including:
45  *
46  * * High-pass filtering of the data.
47  * * Low-pass filtering of the data.
48  * * Resampling of the data.
49  * * Computing the power spectrum of the data.
50  *
51  * If any of the filtering or resampling operations are performed, it is
52  * recommended additional `padding` is used. This additional data, before and
53  * after the requested interval, will be discarded before output (or before
54  * computing the power spectrum) which will remove filter transients. Note
55  * that data will be read for the entire interval
56  * [`tstart-padding`,`tstart+deltat+padding`) and must be available.
57  *
58  *
59  * ### Options
60  *
61  * <DL>
62  * <DT>`-h`, `--help`</DT>
63  * <DD>Prints the help message.</DD>
64  * <DT>`-c channel`, `--channel=channel`</DT>
65  * <DD>The channel name that is to be read.</DD>
66  * <DT>`-f cachefile`, `--frame-cache=cachefile`</DT>
67  * <DD>The cachefile indexing the frame files to be used.</DD>
68  * <DT>`-g globstring `, `--frame-glob=globstring`</DT>
69  * <DD>The globstring identifying the frame files to be used.</DD>
70  * <DT>`-o outfile`, `--output=outfile`</DT>
71  * <DD>The `outfile` to use. The extension of `outfile` is used to determine
72  * the format of the output. The output formats are described below. </DD>
73  * <DT>`-s tstart`, `--start-time=tstart`</DT>
74  * <DD>The time `tstart` GPS seconds of the data to read. If padding is
75  * specified with the `-P` option or the `--pad` option, an additional amount
76  * of data preceding `tstart` is also read, and discarded after any requested
77  * filtering of the data is complete.</DD>
78  * <DT>`-t deltat`, `--duration=deltat`</DT>
79  * <DD>The duration `deltat` in seconds of data to read. If padding is
80  * specified with the `-P` option or the `--pad` option, an additional amount
81  * of data is also read, and discarded after any requested filtering of the
82  * data is complete.</DD>
83  * <DT>`-H minfreq`, `--highpass=minfreq`</DT>
84  * <DD>High-pass filter the data at `minfreq` Hertz. An additional amount of
85  * data, which will be discarded after the filtering, should be specified with
86  * the `-P` option or the `--pad` option to remove filter transients.</DD>
87  * <DT>`-L maxfreq`, `--lowpass=maxfreq`</DT>
88  * <DD>Low-pass filter the data at `maxfreq` Hertz. An additional amount of
89  * data, which will be discarded after the filtering, should be specified with
90  * the `-P` option or the `--pad` option to remove filter transients.</DD>
91  * <DT>`-P padding`, `--pad=padding`</DT>
92  * <DD>Read padding additional seconds of data before and after the requested
93  * interval. This data is then dropped after all requested filtering has been
94  * performed in order to remove filter transients.</DD>
95  * <DT>`-R srate`, `--resample=srate`</DT>
96  * <DD>Resample the data to sampling rate `srate` Hertz. An additional amount
97  * of data, which will be discarded after the filtering, should be specified
98  * with the `-P` option or the `--pad` option to remove filter transients.</DD>
99  * <DT>`-S resolution`, `--spectrum=resolution`</DT>
100  * <DD>Compute the power spectrum of the data at the requested `resolution` in
101  * Hertz. Depending on the output format, either the amplitude spectral
102  * density or the power spectral density is output.</DD>
103  * </DL>
104  *
105  * ### Output Formats
106  *
107  * If the -o or --output option is used to specify an output file, the
108  * extension of that file is used to determine the output format. Supported
109  * output formats include:
110  * <DL>
111  * <DT>`.au`</DT>
112  * <DD>Au audio file format. This format is for time-series data only and may
113  * not be used if the `-S` or the `--spectrum` option is used.</DD>
114  * <DT>`.eps`</DT>
115  * <DD>Encapsulated PostScript (EPS) graphical file format. A plot of the data
116  * values as a function of time is produced using the `gnuplot(1)` program, if
117  * available. If the `-S` or the `--spectrum` option is used, a log-log plot
118  * of the amplitude spectrum is produced instead.</DD>
119  * <DT>`.gif`</DT>
120  * <DD>Graphics Interchange Format (GIF) graphical file format. A plot of the
121  * data values as a function of time is produced using the `gnuplot(1)`
122  * program, if available. If the `-S` or the `--spectrum` option is used, a
123  * log-log plot of the amplitude spectrum is produced instead.</DD>
124  * <DT>`.jpg`</DT>
125  * <DD>JPEG graphical file format. A plot of the data values as a function of
126  * time is produced using the `gnuplot(1)` program, if available. If the `-S`
127  * or the `--spectrum` option is used, a log-log plot of the amplitude spectrum
128  * is produced instead.</DD>
129  * <DT>`.pdf`</DT>
130  * <DD>Portable Document Format (PDF) graphical file format. A plot of the
131  * data values as a function of time is produced using the `gnuplot(1)`
132  * program, if available. If the `-S` or the `--spectrum` option is used, a
133  * log-log plot of the amplitude spectrum is produced instead.</DD>
134  * <DT>`.png`</DT>
135  * <DD>Portable Network Graphics (PNG) graphical file format. A plot of the
136  * data values as a function of time is produced using the `gnuplot(1)`
137  * program, if available. If the `-S` or the `--spectrum` option is used, a
138  * log-log plot of the amplitude spectrum is produced instead.</DD>
139  * <DT>`.ps`</DT>
140  * <DD>PostScript (PS) graphical file format. A plot of the data values as a
141  * function of time is produced using the `gnuplot(1)` program, if available.
142  * If the `-S` or the `--spectrum` option is used, a log-log plot of the
143  * amplitude spectrum is produced instead.</DD>
144  * <DT>`.svg`</DT>
145  * <DD>Scalable Vector Graphics (SVG) graphical file format. A plot of the
146  * data values as a function of time is produced using the `gnuplot(1)`
147  * program, if available. If the `-S` or the `--spectrum` optione used, a
148  * log-log plot of the amplitude spectrum is produced instead.</DD>
149  * <DT>`.wav`</DT>
150  * <DD>Waveform Audio File Format (WAVE) audio file format. This format is for
151  * time-series data only and may not be used if the `-S` or the `--spectrum`
152  * option is used.</DD>
153  * <DT>`.xml`</DT>
154  * <DD>XML-based LIGO-lightweight (LIGOLw) file format. If the `-S` or the
155  * `--spectrum` option is used, the power spectral density data is written to
156  * the file.</DD>
157  * </DL>
158  *
159  * If none of these extensions are used then the output will be in two-column
160  * ascii format. The first column will be the GPS time of each sample of data
161  * and the second column will be the sample values. However, if the `-S` or
162  * the `--spectrum` option is used, the first column will be the frequency of
163  * each sample of the spectrum and the second column will be the value of the
164  * power spectral density at that frequency.
165  *
166  *
167  * ### Environment
168  *
169  * The `LAL_DEBUG_LEVEL` can used to control the error and warning reporting of
170  * `lalfr-vis`. Common values are: `LAL_DEBUG_LEVEL=0` which suppresses error
171  * messages, `LAL_DEBUG_LEVEL=1` which prints error messages alone,
172  * `LAL_DEBUG_LEVEL=3` which prints both error messages and warning messages,
173  * and `LAL_DEBUG_LEVEL=7` which additionally prints informational messages.
174  *
175  *
176  * ### Exit Status
177  *
178  * The `lalfr-vis` utility exits 0 on success, and >0 if an error occurs.
179  *
180  * ### Examples
181  *
182  * The command:
183  *
184  * lalfr-vis -c H1:LSC-STRAIN -g "H-*.gwf" -s 1000000000 -t 16 -o out.wav
185  *
186  * will read 16 seconds beginning at GPS time 1000000000 of `H1:LSC-STRAIN`
187  * data from frame files matching `H-*.gwf` in the current directory and output
188  * the data as a WAVE audio file `out.wav`.
189  *
190  * The command:
191  *
192  * lalfr-vis -c L1:LSC-STRAIN -f LLO.cache -s 1000000001 -t 64 -R 2048 -H 10 -L 1000 -P 1 -S 0.25 -o out.png
193  *
194  * will read 66 seconds beginning at GPS time 1000000000 of `L1:LSC-STRAIN`
195  * data from frame files indexed in `LLO.cache`, and the following
196  * manipulations will be performed: the data will be resampled to a sampling
197  * rate of 2048 Hz, the data will be high-pass filtered at 10 Hz, the data will
198  * be low-pass filtered at 1000 Hz, the first and last 1 second of data will be
199  * dropped (to remove filter transients), a power spectrum will be computed
200  * with 0.25 Hz resolution, and a PNG file displaying a log-log plot of the
201  * amplitude spectral density will output in file `out.pnd`.
202  *
203  * @sa lalfr_stream
204  */
205 
206 #include <math.h>
207 #include <stdio.h>
208 #include <stdlib.h>
209 #include <string.h>
210 
211 
212 #include <lal/LALStdlib.h>
213 #include <lal/LALgetopt.h>
214 #include <lal/LALString.h>
215 #include <lal/Date.h>
216 #include <lal/FrequencySeries.h>
217 #include <lal/TimeSeries.h>
218 #include <lal/BandPassTimeSeries.h>
219 #include <lal/ResampleTimeSeries.h>
220 #include <lal/Window.h>
221 #include <lal/TimeFreqFFT.h>
222 #include <lal/Audio.h>
223 #include <lal/LALFrStream.h>
224 #include <lal/Units.h>
225 
226 #define FS "\t" /* field separator */
227 #define RS "\n" /* record separator */
228 #define MAXDUR 16.0 /* max segment duration (s) */
229 #define MAXLEN 16384 /* max number of points in buffer */
230 
231 /* globals */
233 char *channel;
234 char *outfile;
235 double minfreq;
236 double maxfreq;
237 double srate;
238 double pad;
239 double df;
240 double t0;
241 double dt;
242 
243 int usage(const char *program);
244 int parseargs(int argc, char **argv);
245 void output_ts(const char *fname, REAL8TimeSeries *series);
246 void gnuplot_output_ts(const char *fname, const char *fmt, REAL8TimeSeries *series);
247 void output_fs(const char *fname, REAL8FrequencySeries *series);
248 void gnuplot_output_fs(const char *fname, const char *fmt, REAL8FrequencySeries *series);
249 
250 void xml_output_ts(const char *fname, REAL8TimeSeries *series);
251 void xml_output_fs(const char *fname, REAL8FrequencySeries *series);
252 
253 int main(int argc, char *argv[])
254 {
255  LALFrStream *stream;
256  REAL8TimeSeries *series;
257  LIGOTimeGPS start;
258 
260 
261  parseargs(argc, argv);
262 
263  /* get the data */
264  stream = XLALFrStreamCacheOpen(cache);
265  XLALGPSSetREAL8(&start, t0 - pad);
266  series = XLALFrStreamInputREAL8TimeSeries(stream, channel, &start, dt + 2.0 * pad, 0);
267  XLALFrStreamClose(stream);
268 
269  /* manipulate the data */
270  if (srate > 0)
271  XLALResampleREAL8TimeSeries(series, 1.0 / srate);
272  if (minfreq > 0)
273  XLALHighPassREAL8TimeSeries(series, minfreq, 0.9, 8);
274  if (maxfreq > 0)
275  XLALLowPassREAL8TimeSeries(series, maxfreq, 0.9, 8);
276  if (pad > 0)
277  series = XLALResizeREAL8TimeSeries(series, pad / series->deltaT, dt / series->deltaT);
278 
279  if (df > 0) { /* we are computing a spectrum */
280  REAL8FrequencySeries *spectrum;
281  REAL8FFTPlan *plan;
282  REAL8Window *window;
283  size_t seglen = 1.0 / (df * series->deltaT);
284 
285  /* make sure that the time series length is commensurate with seglen */
286  if (((2 * series->data->length) % seglen) != 0) {
287  size_t newlen = ((2 * series->data->length) / seglen) * seglen;
288  series = XLALResizeREAL8TimeSeries(series, 0, newlen);
289  }
290 
291  spectrum = XLALCreateREAL8FrequencySeries(series->name, &series->epoch, 0.0, df, &lalDimensionlessUnit, seglen/2 + 1);
292  plan = XLALCreateForwardREAL8FFTPlan(seglen, 0);
293  window = XLALCreateHannREAL8Window(seglen);
294  XLALREAL8AverageSpectrumWelch(spectrum, series, seglen, seglen/2, window, plan);
295  if (minfreq > 0 || maxfreq > 0) {
296  size_t first = minfreq / spectrum->deltaF;
297  size_t last = maxfreq > 0 ? maxfreq / spectrum->deltaF : spectrum->data->length;
298  spectrum = XLALResizeREAL8FrequencySeries(spectrum, first, last - first);
299  }
300  output_fs(outfile, spectrum);
301  XLALDestroyREAL8Window(window);
304  } else { /* we are outputting a time series */
305  output_ts(outfile, series);
306  }
307 
309  return 0;
310 }
311 
312 int parseargs(int argc, char **argv)
313 {
314  struct LALoption long_options[] = {
315  {"help", no_argument, 0, 'h'},
316  {"channel", required_argument, 0, 'c'},
317  {"frame-cache", required_argument, 0, 'f'},
318  {"frame-glob", required_argument, 0, 'g'},
319  {"output", required_argument, 0, 'o'},
320  {"start-time", required_argument, 0, 's'},
321  {"duration", required_argument, 0, 't'},
322  {"highpass", required_argument, 0, 'H'},
323  {"lowpass", required_argument, 0, 'L'},
324  {"pad", required_argument, 0, 'P'},
325  {"resample", required_argument, 0, 'R'},
326  {"spectrum", required_argument, 0, 'S'},
327  {0, 0, 0, 0}
328  };
329  char args[] = "hc:f:g:o:s:t:H:L:P:R:S:";
330  while (1) {
331  int option_index = 0;
332  int c;
333 
334  c = LALgetopt_long_only(argc, argv, args, long_options, &option_index);
335  if (c == -1) /* end of options */
336  break;
337 
338  switch (c) {
339  case 0: /* if option set a flag, nothing else to do */
340  if (long_options[option_index].flag)
341  break;
342  else {
343  fprintf(stderr, "error parsing option %s with argument %s\n",
344  long_options[option_index].name, LALoptarg);
345  exit(1);
346  }
347  case 'h': /* help */
348  usage(argv[0]);
349  exit(0);
350  case 'c': /* channel */
352  break;
353  case 'f': /* frame-cache */
355  break;
356  case 'g': /* frame-glob */
357  cache = XLALCacheGlob(NULL, LALoptarg);
358  break;
359  case 'o': /* output */
361  break;
362  case 's': /* start-time */
363  t0 = atof(LALoptarg);
364  break;
365  case 't': /* duration */
366  dt = atof(LALoptarg);
367  break;
368  case 'H': /* highpass */
369  minfreq = atof(LALoptarg);
370  break;
371  case 'L': /* lowpass */
372  maxfreq = atof(LALoptarg);
373  break;
374  case 'P': /* pad */
375  pad = atof(LALoptarg);
376  break;
377  case 'R': /* start-time */
378  srate = atof(LALoptarg);
379  break;
380  case 'S': /* spectrum */
381  df = atof(LALoptarg);
382  break;
383  case '?':
384  default:
385  fprintf(stderr, "unknown error while parsing options\n");
386  exit(1);
387  }
388  }
389 
390  if (LALoptind < argc) {
391  fprintf(stderr, "extraneous command line arguments:\n");
392  while (LALoptind < argc)
393  fprintf(stderr, "%s\n", argv[LALoptind++]);
394  exit(1);
395  }
396 
397  /* sanity check parameters */
398 
399  if (!channel) {
400  fprintf(stderr, "must specify a channel\n");
401  usage(argv[0]);
402  exit(1);
403  }
404  if (!cache) {
405  fprintf(stderr, "must specify a frame cache or frame files\n");
406  usage(argv[0]);
407  exit(1);
408  }
409 
410  return 0;
411 }
412 
413 int usage(const char *program)
414 {
415  /* basename */
416  program = strrchr(program, '/') ? strrchr(program, '/') + 1 : program;
417  fprintf(stderr, "usage: %s [options]\n", program);
418  fprintf(stderr, "options:\n");
419  fprintf(stderr, "\t-h, --help \tprint this message and exit\n");
420  fprintf(stderr, "\t-c CHAN, --channel=CHAN \tchannel name CHAN\n");
421  fprintf(stderr, "\t-f CACHE, --frame-cache=CACHE\tframe cache file CACHE\n");
422  fprintf(stderr, "\t-g GLOB, --frame-glob=GLOB \tframe file glob string GLOB\n");
423  fprintf(stderr, "\t-o OUTFILE, --output=OUTFILE \toutput to file OUTFILE\n");
424  fprintf(stderr, "\t-s T0, --start-time=T0 \tGPS start time T0 (s)\n");
425  fprintf(stderr, "\t-t DT, --duration=DT \tduration DT (s)\n");
426  fprintf(stderr, "\t-H FMIN, --highpass=FMIN \thighpass filter at frequency FMIN (Hz)\n");
427  fprintf(stderr, "\t-L FMAX, --lowpass=FMAX \tlowpass filter at frequency FMAX (Hz)\n");
428  fprintf(stderr, "\t-P PAD, --pad=PAD \tadd PAD data at start and end (s)\n");
429  fprintf(stderr, "\t-R SRATE, --resample=SRATE \tresample to rate SRATE (Hz)\n");
430  fprintf(stderr, "\t-S DF, --spectrum=DF \tcompute spectrum with resolution DF (Hz)\n");
431  fprintf(stderr, "\nOUTPUT FORMATS:\n");
432  fprintf(stderr, "\t");
433  fprintf(stderr, ".au, ");
434  fprintf(stderr, ".eps, ");
435  fprintf(stderr, ".gif, ");
436  fprintf(stderr, ".jpg, ");
437  fprintf(stderr, ".pdf, ");
438  fprintf(stderr, ".png, ");
439  fprintf(stderr, ".ps, ");
440  fprintf(stderr, ".svg, ");
441  fprintf(stderr, ".wav, ");
442  fprintf(stderr, ".xml\n");
443  fprintf(stderr, "\nEXAMPLES:\n");
444  fprintf(stderr, "\n\tOutput 64s of strain data to a WAV file:\n");
445  fprintf(stderr, "\t\t%s -c \"H1:LSC-STRAIN\" -g H-H1_RDS_C03_L2-864903135-128.gwf -s 864903136 -t 64 -P 1 -H 10 -L 1000 -R 2048 -o data.wav\n", program);
446  fprintf(stderr, "\n\tOutput amplitude spectrum to a PDF file:\n");
447  fprintf(stderr, "\t\t%s -c \"H1:LSC-STRAIN\" -g H-H1_RDS_C03_L2-864903135-128.gwf -s 864903136 -t 64 -P 1 -H 10 -L 1000 -R 2048 -S 0.25 -o spec.pdf\n", program);
448  return 0;
449 }
450 
451 void output_ts(const char *fname, REAL8TimeSeries *series)
452 {
453  const char *ext;
454  FILE *fp;
455  /* determine output type from extension */
456  ext = strrchr(fname ? fname : "", '.');
457  ext = ext ? ext + 1 : "";
458  if (XLALStringCaseCompare(ext, "wav") == 0) {
459  fp = fopen(fname, "w");
461  fclose(fp);
462  }
463  else if (XLALStringCaseCompare(ext, "au") == 0) {
464  fp = fopen(fname, "w");
466  fclose(fp);
467  }
468  else if (
469  XLALStringCaseCompare(ext, "eps") == 0
470  || XLALStringCaseCompare(ext, "jpeg") == 0
471  || XLALStringCaseCompare(ext, "jpg") == 0
472  || XLALStringCaseCompare(ext, "gif") == 0
473  || XLALStringCaseCompare(ext, "png") == 0
474  || XLALStringCaseCompare(ext, "ps") == 0
475  || XLALStringCaseCompare(ext, "pdf") == 0
476  || XLALStringCaseCompare(ext, "svg") == 0
477  )
478  gnuplot_output_ts(fname, ext, series);
479  else if (XLALStringCaseCompare(ext, "xml") == 0)
480  xml_output_ts(fname, series);
481  else { /* default is an ascii file */
482  size_t i;
483  fp = fname ? fopen(fname, "w") : stdout;
484  for (i = 0; i < series->data->length; ++i) {
485  char tstr[32];
486  LIGOTimeGPS t = series->epoch;
487  XLALGPSToStr(tstr, XLALGPSAdd(&t, i * series->deltaT));
488  fprintf(fp, "%s\t%.15g\n", tstr, series->data->data[i]);
489  }
490  if (fname)
491  fclose(fp);
492  }
493  return;
494 }
495 
496 void output_fs(const char *fname, REAL8FrequencySeries *series)
497 {
498  const char *ext;
499  FILE *fp;
500  /* determine output type from extension */
501  ext = strrchr(fname ? fname : "", '.');
502  ext = ext ? ext + 1 : "";
503  if (XLALStringCaseCompare(ext, "wav") == 0) {
504  fprintf(stderr, "cannot output a spectrum to an audio file\n");
505  exit(1);
506  }
507  else if (XLALStringCaseCompare(ext, "au") == 0) {
508  fprintf(stderr, "cannot output a spectrum to an audio file\n");
509  exit(1);
510  }
511  else if (
512  XLALStringCaseCompare(ext, "eps") == 0
513  || XLALStringCaseCompare(ext, "jpeg") == 0
514  || XLALStringCaseCompare(ext, "jpg") == 0
515  || XLALStringCaseCompare(ext, "gif") == 0
516  || XLALStringCaseCompare(ext, "png") == 0
517  || XLALStringCaseCompare(ext, "ps") == 0
518  || XLALStringCaseCompare(ext, "pdf") == 0
519  || XLALStringCaseCompare(ext, "svg") == 0
520  )
521  gnuplot_output_fs(fname, ext, series);
522  else if (XLALStringCaseCompare(ext, "xml") == 0)
523  xml_output_fs(fname, series);
524  else { /* default is an ascii file */
525  size_t i;
526  fp = fname ? fopen(fname, "w") : stdout;
527  for (i = 0; i < series->data->length; ++i)
528  fprintf(fp, "%f\t%.15g\n", i * series->deltaF, series->data->data[i]);
529  if (fname)
530  fclose(fp);
531  }
532  return;
533 }
534 
535 void gnuplot_output_ts(const char *fname, const char *fmt, REAL8TimeSeries *series)
536 {
537  size_t i;
538  char *units;
539  FILE *gp = popen("gnuplot -persistent", "w");
540 
541  if (!gp) {
542  fprintf(stderr, "require program gnuplot to output .%s files", fmt);
543  exit(1);
544  }
545 
546  /* get the sample units as a string */
547  units = XLALUnitToString(&series->sampleUnits);
548  if (units == NULL || *units == '\0') {
549  LALFree(units);
550  units = XLALStringDuplicate("unknown units");
551  }
552 
553  /* modify fmt as required by gnuplot */
554  if (strcmp(fmt, "jpg") == 0)
555  fmt = "jpeg";
556  else if (strcmp(fmt, "ps") == 0)
557  fmt = "postscript landscape";
558  else if (strcmp(fmt, "eps") == 0)
559  fmt = "postscript eps";
560 
561  /* issue gnuplot commands */
562  fprintf(gp, "set terminal %s\n", fmt);
563  fprintf(gp, "set output '%s'\n", fname);
564  fprintf(gp, "set key off\n");
565  fprintf(gp, "set grid\n");
566  fprintf(gp, "set xlabel 'time (s)'\n");
567  fprintf(gp, "set ylabel 'value (%s)'\n", units);
568  fprintf(gp, "set title '%s @ %d.%09d\n", series->name, series->epoch.gpsSeconds, series->epoch.gpsNanoSeconds);
569  fprintf(gp, "plot '-' with lines\n");
570  for (i = 0; i < series->data->length; ++i)
571  fprintf(gp, "%.9f\t%e\n", i * series->deltaT, series->data->data[i]);
572  fprintf(gp, "e");
573 
574  pclose(gp);
575  LALFree(units);
576  return;
577 }
578 
579 void gnuplot_output_fs(const char *fname, const char *fmt, REAL8FrequencySeries *series)
580 {
581  LALUnit asdunit;
582  char *units;
583  size_t i;
584  FILE *gp = popen("gnuplot -persistent", "w");
585 
586  if (!gp) {
587  fprintf(stderr, "require program gnuplot to output .%s files", fmt);
588  exit(1);
589  }
590 
591  /* get the sample units as a string */
592  XLALUnitSqrt(&asdunit, &series->sampleUnits);
593  units = XLALUnitToString(&asdunit);
594  if (units == NULL || *units == '\0') {
595  LALFree(units);
596  units = XLALStringDuplicate("unknown units");
597  }
598 
599  /* modify fmt as required by gnuplot */
600  if (strcmp(fmt, "jpg") == 0)
601  fmt = "jpeg";
602  else if (strcmp(fmt, "ps") == 0)
603  fmt = "postscript landscape";
604  else if (strcmp(fmt, "eps") == 0)
605  fmt = "postscript eps";
606 
607  /* issue gnuplot commands */
608  fprintf(gp, "set terminal %s\n", fmt);
609  fprintf(gp, "set output '%s'\n", fname);
610  fprintf(gp, "set key off\n");
611  fprintf(gp, "set grid xtics mxtics ytics\n");
612  fprintf(gp, "set xlabel 'frequency (Hz)'\n");
613  fprintf(gp, "set ylabel 'amplitude spectral density (%s)'\n", units);
614  fprintf(gp, "set title '%s @ %d.%09d\n", series->name, series->epoch.gpsSeconds, series->epoch.gpsNanoSeconds);
615  fprintf(gp, "set logscale\n");
616  fprintf(gp, "plot '-' with lines\n");
617  for (i = 0; i < series->data->length; ++i)
618  fprintf(gp, "%.9f\t%e\n", series->f0 + i * series->deltaF, sqrt(series->data->data[i]));
619  fprintf(gp, "e");
620 
621  pclose(gp);
622  LALFree(units);
623  return;
624 }
625 
626 
627 
628 void xml_begin_xml(FILE *fp);
629 void xml_end_xml(FILE *fp);
630 
631 void xml_begin_freq_series(FILE *fp);
632 void xml_begin_time_series(FILE *fp);
633 void xml_end_series(FILE *fp);
634 
635 void xml_put_gps(LIGOTimeGPS *epoch, FILE *fp);
636 void xml_put_f0(double f0, FILE *fp);
637 void xml_put_det(const char *name, FILE *fp);
638 
639 void xml_begin_freq_array(REAL8FrequencySeries *series, FILE *fp);
640 void xml_begin_time_array(REAL8TimeSeries *series, FILE *fp);
641 void xml_end_array(FILE *fp);
642 
643 void xml_put_stream(REAL8Vector *vector, double dx, FILE *fp);
644 
645 void xml_begin_xml(FILE *fp)
646 {
647  fputs("<?xml version='1.0' encoding='utf-8'?>\n", fp);
648  fputs("<!DOCTYPE LIGO_LW SYSTEM \"http://ldas-sw.ligo.caltech.edu/doc/ligolwAPI/html/ligolw_dtd.txt\">\n", fp);
649  fputs("<LIGO_LW>\n", fp);
650  return;
651 }
652 void xml_end_xml(FILE *fp)
653 {
654  fputs("</LIGO_LW>\n", fp);
655  return;
656 }
657 
658 void xml_begin_freq_series(FILE *fp)
659 {
660  fputs("\t<LIGO_LW Name=\"REAL8FrequencySeries\">\n", fp);
661  return;
662 }
663 void xml_begin_time_series(FILE *fp)
664 {
665  fputs("\t<LIGO_LW Name=\"REAL8TimeSeries\">\n", fp);
666  return;
667 }
668 void xml_end_series(FILE *fp)
669 {
670  fputs("\t</LIGO_LW>\n", fp);
671  return;
672 }
673 
674 void xml_put_gps(LIGOTimeGPS *epoch, FILE *fp)
675 {
676  char tstr[32];
677  XLALGPSToStr(tstr, epoch);
678  fprintf(fp, "\t\t<Time Type=\"GPS\" Name=\"epoch\">%s</Time>\n", tstr);
679  return;
680 }
681 void xml_put_f0(double f0, FILE *fp)
682 {
683  fprintf(fp, "\t\t<Param Type=\"real_8\" Name=\"f0:param\" Unit=\"s^-1\">"
684  "%g</Param>\n", f0);
685  return;
686 }
687 void xml_put_det(const char *name, FILE *fp)
688 {
689  const char *dets[] = {"G1", "H1", "H2", "K1", "L1", "T1", "V1"};
690  size_t ndet = XLAL_NUM_ELEM(dets);
691  size_t d;
692  fputs("\t\t<Param Type=\"lstring\" Name=\"instrument:param\">", fp);
693  for (d = 0; d < ndet; ++d)
694  if (strncmp(name, dets[d], 2) == 0) {
695  fputs(dets[d], fp);
696  break;
697  }
698  if (d == ndet)
699  fputs("??", fp);
700  fputs("</Param>\n", fp);
701  return;
702 }
703 
705 {
706  fprintf(fp, "\t\t<Array Type=\"real_8\" Name=\"%s:array\" Unit=\"%s\">\n",
707  series->name, XLALUnitToString(&series->sampleUnits));
708  fprintf(fp, "\t\t\t<Dim Start=\"%g\" Scale=\"%.15g\" "
709  "Name=\"Frequency\" Unit=\"s^-1\">%u</Dim>\n", series->f0,
710  series->deltaF, series->data->length);
711  fputs("\t\t\t<Dim Name=\"Frequency,Real\">2</Dim>\n", fp);
712  return;
713 }
714 void xml_begin_time_array(REAL8TimeSeries *series, FILE *fp)
715 {
716  fprintf(fp, "\t\t<Array Type=\"real_8\" Name=\"%s:array\" Unit=\"%s\">\n",
717  series->name, XLALUnitToString(&series->sampleUnits));
718  fprintf(fp, "\t\t\t<Dim Start=\"0\" Scale=\"%.15g\" "
719  "Name=\"Time\" Unit=\"s\">%u</Dim>\n", series->deltaT,
720  series->data->length);
721  fputs("\t\t\t<Dim Name=\"Time,Real\">2</Dim>\n", fp);
722  return;
723 }
724 void xml_end_array(FILE *fp)
725 {
726  fputs("\t\t</Array>\n", fp);
727  return;
728 }
729 
730 void xml_put_stream(REAL8Vector *vector, double dx, FILE *fp)
731 {
732 #define DELIM ","
733  size_t i;
734  fputs("\t\t\t<Stream Delimiter=\"" DELIM "\" Type=\"Local\">\n", fp);
735  for (i = 0; i < vector->length; ++i)
736  fprintf(fp, "\t\t\t\t%.15g" DELIM "%.15g" DELIM "\n", i * dx,
737  vector->data[i]);
738  fputs("\t\t\t</Stream>\n", fp);
739  return;
740 #undef DELIM
741 }
742 
743 void xml_output_ts(const char *fname, REAL8TimeSeries *series)
744 {
745  FILE *fp = fopen(fname, "w");
746  xml_begin_xml(fp);
747 
749 
750  xml_put_gps(&series->epoch, fp);
751  xml_put_f0(series->f0, fp);
752 
753  xml_begin_time_array(series, fp);
754 
755  xml_put_stream(series->data, series->deltaT, fp);
756 
757  xml_end_array(fp);
758 
759  xml_put_det(series->name, fp);
760 
762 
763  xml_end_xml(fp);
764 
765  fclose(fp);
766  return;
767 }
768 
769 void xml_output_fs(const char *fname, REAL8FrequencySeries *series)
770 {
771  FILE *fp = fopen(fname, "w");
772  xml_begin_xml(fp);
773 
775 
776  xml_put_gps(&series->epoch, fp);
777  xml_put_f0(series->f0, fp);
778 
779  xml_begin_freq_array(series, fp);
780 
781  xml_put_stream(series->data, series->deltaF, fp);
782 
783  xml_end_array(fp);
784 
785  xml_put_det(series->name, fp);
786 
788 
789  xml_end_xml(fp);
790 
791  fclose(fp);
792  return;
793 }
int XLALLowPassREAL8TimeSeries(REAL8TimeSeries *series, REAL8 frequency, REAL8 amplitude, INT4 filtorder)
int XLALHighPassREAL8TimeSeries(REAL8TimeSeries *series, REAL8 frequency, REAL8 amplitude, INT4 filtorder)
const char * program
#define LALFree(p)
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 XLALAudioAURecordREAL8TimeSeries(FILE *fp, REAL8TimeSeries *series)
int XLALAudioWAVRecordREAL8TimeSeries(FILE *fp, REAL8TimeSeries *series)
char * XLALGPSToStr(char *s, const LIGOTimeGPS *t)
REAL8FrequencySeries * XLALCreateREAL8FrequencySeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaF, const LALUnit *sampleUnits, size_t length)
REAL8FrequencySeries * XLALResizeREAL8FrequencySeries(REAL8FrequencySeries *series, int first, size_t length)
void XLALDestroyREAL8FrequencySeries(REAL8FrequencySeries *series)
LALCache * XLALCacheImport(const char *fname)
LALCache * XLALCacheGlob(const char *dirstr, const char *fnptrn)
#define XLAL_NUM_ELEM(x)
int XLALFrStreamClose(LALFrStream *stream)
Closes a LALFrStream.
Definition: LALFrStream.c:170
LALFrStream * XLALFrStreamCacheOpen(LALCache *cache)
Opens a LALFrStream associated with a LALCache.
Definition: LALFrStream.c:189
REAL8TimeSeries * XLALFrStreamInputREAL8TimeSeries(LALFrStream *stream, const char *channel, const LIGOTimeGPS *start, REAL8 duration, size_t lengthlimit)
Reads a time series channel from a LALFrStream stream with a specified start time and duration,...
int XLALStringCaseCompare(const char *s1, const char *s2)
char char * XLALStringDuplicate(const char *s)
void XLALDestroyREAL8FFTPlan(REAL8FFTPlan *plan)
REAL8FFTPlan * XLALCreateForwardREAL8FFTPlan(UINT4 size, int measurelvl)
int XLALResampleREAL8TimeSeries(REAL8TimeSeries *series, REAL8 dt)
int XLALREAL8AverageSpectrumWelch(REAL8FrequencySeries *spectrum, const REAL8TimeSeries *tseries, UINT4 seglen, UINT4 stride, const REAL8Window *window, const REAL8FFTPlan *plan)
REAL8TimeSeries * XLALResizeREAL8TimeSeries(REAL8TimeSeries *series, int first, size_t length)
void XLALDestroyREAL8TimeSeries(REAL8TimeSeries *series)
char * XLALUnitToString(const LALUnit *input)
const LALUnit lalDimensionlessUnit
LALUnit * XLALUnitSqrt(LALUnit *output, const LALUnit *input)
void XLALDestroyREAL8Window(REAL8Window *window)
REAL8Window * XLALCreateHannREAL8Window(UINT4 length)
void XLALAbortErrorHandler(const char *func, const char *file, int line, int errnum)
XLALErrorHandlerType * XLALSetErrorHandler(XLALErrorHandlerType *newHandler)
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
LIGOTimeGPS * XLALGPSSetREAL8(LIGOTimeGPS *epoch, REAL8 t)
ext
This structure details the state of the frame stream.
Definition: LALFrStream.h:95
const char * name
int * flag
INT4 gpsNanoSeconds
REAL8Sequence * data
CHAR name[LALNameLength]
REAL8Sequence * data
LALUnit sampleUnits
LIGOTimeGPS epoch
CHAR name[LALNameLength]
REAL8 * data
FILE * fp
enum @1 epoch
double dt
Definition: vis.c:241
double df
Definition: vis.c:239
int main(int argc, char *argv[])
Definition: vis.c:253
#define DELIM
void xml_begin_time_series(FILE *fp)
Definition: vis.c:663
LALCache * cache
Definition: vis.c:232
void xml_begin_time_array(REAL8TimeSeries *series, FILE *fp)
Definition: vis.c:714
double t0
Definition: vis.c:240
void xml_begin_xml(FILE *fp)
Definition: vis.c:645
int usage(const char *program)
Definition: vis.c:413
int parseargs(int argc, char **argv)
Definition: vis.c:312
void xml_put_det(const char *name, FILE *fp)
Definition: vis.c:687
void xml_output_ts(const char *fname, REAL8TimeSeries *series)
Definition: vis.c:743
void xml_put_stream(REAL8Vector *vector, double dx, FILE *fp)
Definition: vis.c:730
void xml_begin_freq_series(FILE *fp)
Definition: vis.c:658
double maxfreq
Definition: vis.c:236
void xml_end_xml(FILE *fp)
Definition: vis.c:652
void xml_put_f0(double f0, FILE *fp)
Definition: vis.c:681
double srate
Definition: vis.c:237
void xml_end_array(FILE *fp)
Definition: vis.c:724
void gnuplot_output_ts(const char *fname, const char *fmt, REAL8TimeSeries *series)
Definition: vis.c:535
char * channel
Definition: vis.c:233
void output_ts(const char *fname, REAL8TimeSeries *series)
Definition: vis.c:451
void xml_end_series(FILE *fp)
Definition: vis.c:668
void xml_put_gps(LIGOTimeGPS *epoch, FILE *fp)
Definition: vis.c:674
void xml_output_fs(const char *fname, REAL8FrequencySeries *series)
Definition: vis.c:769
char * outfile
Definition: vis.c:234
double minfreq
Definition: vis.c:235
void gnuplot_output_fs(const char *fname, const char *fmt, REAL8FrequencySeries *series)
Definition: vis.c:579
double pad
Definition: vis.c:238
void output_fs(const char *fname, REAL8FrequencySeries *series)
Definition: vis.c:496
void xml_begin_freq_array(REAL8FrequencySeries *series, FILE *fp)
Definition: vis.c:704