LALFrame  3.0.4.1-89842e6
stream.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_stream lalfr-stream
22  * @ingroup lalframe_programs
23  *
24  * @brief Output a frame data stream
25  *
26  * ### Synopsis
27  *
28  * lalfr-stream --channel=channel --frame-cache=cachefile [--start-time=tstart] [--duration=deltat]
29  *
30  * lalfr-stream --channel=channel --frame-glob=globstring [--start-time=tstart] [--duration=deltat]
31  *
32  * ### Description
33  *
34  * The `lalfr-stream` utility reads a requested interval
35  * [`tstart`,`tstart+deltat`) of `channel` data from frame files that are
36  * either indexed in the `cachefile` or matching the pattern `globstring` as
37  * described by `glob(3)`. If `tstart` is not specified, streaming begins at
38  * the beginning of the available data. If `deltat` is not specified,
39  * streaming continues until the end of the available data. The output is
40  * written to the standard output in two-column ascii format data in which the
41  * first column contains the GPS times of each sample and the second column
42  * contains the corresponding sample values.
43  *
44  * ### Options
45  *
46  * <DL>
47  * <DT>`-h`, `--help`</DT>
48  * <DD>Prints the help message.</DD>
49  * <DT>`-c channel`, `--channel=channel`</DT>
50  * <DD>The channel name that is to be read.</DD>
51  * <DT>`-f cachefile`, `--frame-cache=cachefile`</DT>
52  * <DD>The cachefile indexing the frame files to be used.</DD>
53  * <DT>`-g globstring `, `--frame-glob=globstring`</DT>
54  * <DD>The globstring identifying the frame files to be used.</DD>
55  * <DT>`-s tstart`, `--start-time=tstart`</DT>
56  * <DD>The time `tstart` GPS seconds of the data to read.</DD>
57  * <DT>`-t deltat`, `--duration=deltat`</DT>
58  * <DD>The duration `deltat` in seconds of data to read.</DD>
59  * </DL>
60  *
61  * ### Environment
62  *
63  * The `LAL_DEBUG_LEVEL` can used to control the error and warning reporting of
64  * `lalfr-stream`. Common values are: `LAL_DEBUG_LEVEL=0` which suppresses
65  * error messages, `LAL_DEBUG_LEVEL=1` which prints error messages alone,
66  * `LAL_DEBUG_LEVEL=3` which prints both error messages and warning messages,
67  * and `LAL_DEBUG_LEVEL=7` which additionally prints informational messages.
68  *
69  *
70  * ### Exit Status
71  *
72  * The `lalfr-stream` utility exits 0 on success, and >0 if an error occurs.
73  *
74  * ### Examples
75  *
76  * The command:
77  *
78  * lalfr-stream -c H1:LSC-STRAIN -g "H-*.gwf" -s 1000000000 -t 1000
79  *
80  * will stream 1000 seconds of `H1:LSC-STRAIN` data beginning at GPS time
81  * 1000000000 from frame files matching `H-*.gwf` in the current directory.
82  *
83  * @sa @ref lalfr_vis
84  */
85 
86 
87 #include <math.h>
88 #include <stdio.h>
89 #include <stdlib.h>
90 #include <string.h>
91 
92 
93 #include <lal/Date.h>
94 #include <lal/LALgetopt.h>
95 #include <lal/LALStdlib.h>
96 #include <lal/LALString.h>
97 #include <lal/TimeSeries.h>
98 #include <lal/LALFrStream.h>
99 #include <lal/Units.h>
100 
101 #define FS "\t" /* field separator */
102 #define RS "\n" /* record separator */
103 #define MAXDUR 16.0 /* max segment duration (s) */
104 #define MAXLEN 16384 /* max number of points in buffer */
105 
106 /* globals */
108 char *channel;
109 double t0;
110 double dt;
111 
112 int usage(const char *program);
113 int parseargs(int argc, char **argv);
114 void output_INT2(LALFrStream * stream, const char *channame,
115  LIGOTimeGPS * start, LIGOTimeGPS * end);
116 void output_INT4(LALFrStream * stream, const char *channame,
117  LIGOTimeGPS * start, LIGOTimeGPS * end);
118 void output_INT8(LALFrStream * stream, const char *channame,
119  LIGOTimeGPS * start, LIGOTimeGPS * end);
120 void output_UINT2(LALFrStream * stream, const char *channame,
121  LIGOTimeGPS * start, LIGOTimeGPS * end);
122 void output_UINT4(LALFrStream * stream, const char *channame,
123  LIGOTimeGPS * start, LIGOTimeGPS * end);
124 void output_UINT8(LALFrStream * stream, const char *channame,
125  LIGOTimeGPS * start, LIGOTimeGPS * end);
126 void output_REAL4(LALFrStream * stream, const char *channame,
127  LIGOTimeGPS * start, LIGOTimeGPS * end);
128 void output_REAL8(LALFrStream * stream, const char *channame,
129  LIGOTimeGPS * start, LIGOTimeGPS * end);
130 void output_COMPLEX8(LALFrStream * stream, const char *channame,
131  LIGOTimeGPS * start, LIGOTimeGPS * end);
132 void output_COMPLEX16(LALFrStream * stream, const char *channame,
133  LIGOTimeGPS * start, LIGOTimeGPS * end);
134 
135 int main(int argc, char *argv[])
136 {
137  LALFrStream *stream;
138  LALTYPECODE type;
139  LIGOTimeGPS start;
141 
143 
144  parseargs(argc, argv);
145 
146  stream = XLALFrStreamCacheOpen(cache);
147 
148  /* determine the start of the output stream */
149  if (t0 > 0.0) /* use value provide by user */
150  XLALGPSSetREAL8(&start, t0);
151  else { /* use start of input stream */
152  XLALFrStreamTell(&start, stream);
153  t0 = XLALGPSGetREAL8(&start);
154  }
155 
156  /* determine the end of the output stream */
157  if (dt > 0.0) /* use value provide by user */
158  XLALGPSSetREAL8(&end, t0 + dt);
159  else { /* use end of input stream */
160  int mode = XLALFrStreamGetMode(stream);
161  /* we're seeking to the end, so don't complain! */
162  XLALFrStreamSetMode(stream,
165  XLALFrStreamSeekO(stream, 0, SEEK_END);
166  XLALFrStreamTell(&end, stream);
167  XLALFrStreamSetMode(stream, mode);
168  }
169 
170  XLALFrStreamSeek(stream, &start);
171 
172  type = XLALFrStreamGetTimeSeriesType(channel, stream);
173  switch (type) {
174  case LAL_I2_TYPE_CODE:
175  output_INT2(stream, channel, &start, &end);
176  break;
177  case LAL_I4_TYPE_CODE:
178  output_INT4(stream, channel, &start, &end);
179  break;
180  case LAL_I8_TYPE_CODE:
181  output_INT8(stream, channel, &start, &end);
182  break;
183  case LAL_U2_TYPE_CODE:
184  output_UINT2(stream, channel, &start, &end);
185  break;
186  case LAL_U4_TYPE_CODE:
187  output_UINT4(stream, channel, &start, &end);
188  break;
189  case LAL_U8_TYPE_CODE:
190  output_UINT8(stream, channel, &start, &end);
191  break;
192  case LAL_S_TYPE_CODE:
193  output_REAL4(stream, channel, &start, &end);
194  break;
195  case LAL_D_TYPE_CODE:
196  output_REAL8(stream, channel, &start, &end);
197  break;
198  case LAL_C_TYPE_CODE:
199  output_COMPLEX8(stream, channel, &start, &end);
200  break;
201  case LAL_Z_TYPE_CODE:
202  output_COMPLEX16(stream, channel, &start, &end);
203  break;
204  default:
205  fprintf(stderr, "unsupported channel type\n");
206  return 1;
207  }
208 
209  XLALFrStreamClose(stream);
210  return 0;
211 }
212 
213 int parseargs(int argc, char **argv)
214 {
215  struct LALoption long_options[] = {
216  {"help", no_argument, 0, 'h'},
217  {"channel", required_argument, 0, 'c'},
218  {"frame-cache", required_argument, 0, 'f'},
219  {"frame-glob", required_argument, 0, 'g'},
220  {"start-time", required_argument, 0, 's'},
221  {"duration", required_argument, 0, 't'},
222  {0, 0, 0, 0}
223  };
224  char args[] = "hc:f:g:s:t:";
225  while (1) {
226  int option_index = 0;
227  int c;
228 
229  c = LALgetopt_long_only(argc, argv, args, long_options, &option_index);
230  if (c == -1) /* end of options */
231  break;
232 
233  switch (c) {
234  case 0: /* if option set a flag, nothing else to do */
235  if (long_options[option_index].flag)
236  break;
237  else {
238  fprintf(stderr, "error parsing option %s with argument %s\n",
239  long_options[option_index].name, LALoptarg);
240  exit(1);
241  }
242  case 'h': /* help */
243  usage(argv[0]);
244  exit(0);
245  case 'c': /* channel */
247  break;
248  case 'f': /* frame-cache */
250  break;
251  case 'g': /* frame-cache */
252  cache = XLALCacheGlob(NULL, LALoptarg);
253  break;
254  case 's': /* start-time */
255  t0 = atof(LALoptarg);
256  break;
257  case 't': /* duration */
258  dt = atof(LALoptarg);
259  break;
260  case '?':
261  default:
262  fprintf(stderr, "unknown error while parsing options\n");
263  exit(1);
264  }
265  }
266 
267  if (LALoptind < argc) {
268  fprintf(stderr, "extraneous command line arguments:\n");
269  while (LALoptind < argc)
270  fprintf(stderr, "%s\n", argv[LALoptind++]);
271  exit(1);
272  }
273 
274  /* sanity check parameters */
275 
276  if (!channel) {
277  fprintf(stderr, "must specify a channel\n");
278  usage(argv[0]);
279  exit(1);
280  }
281  if (!cache) {
282  fprintf(stderr, "must specify a frame cache or frame files\n");
283  usage(argv[0]);
284  exit(1);
285  }
286 
287  return 0;
288 }
289 
290 int usage(const char *program)
291 {
292  fprintf(stderr, "usage: %s [options]\n", program);
293  fprintf(stderr, "options:\n");
294  fprintf(stderr, "\t-h, --help \tprint this message and exit\n");
295  fprintf(stderr, "\t-c, CHAN --channel=CHAN \tchannel name CHAN\n");
296  fprintf(stderr, "\t-f CACHE, --frame-cache=CACHE\tframe cache file CACHE\n");
297  fprintf(stderr, "\t-g GLOB, --frame-glob=GLOB \tframe file glob string GLOB\n");
298  fprintf(stderr, "\t-s T0, --start-time=T0 \tGPS start time T0 (s)\n");
299  fprintf(stderr, "\t-t DT, --duration=DT \tduration DT (s)\n");
300  return 0;
301 }
302 
303 #define DEFINE_OUTPUT_FUNCTION(laltype, format, ...) \
304 void output_ ## laltype (LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end) \
305 { \
306  double remaining; \
307  laltype ## TimeSeries *series; \
308  /* create zero-length time series */ \
309  series = XLALCreate ## laltype ## TimeSeries(channame, start, 0.0, 0.0, &lalDimensionlessUnit, 0); \
310  XLALFrStreamGet ## laltype ## TimeSeriesMetadata(series, stream); \
311  while ((remaining = XLALGPSDiff(end, start)) > series->deltaT) { \
312  size_t length; \
313  size_t i; \
314  remaining = (remaining > MAXDUR ? MAXDUR : remaining); \
315  length = (size_t)floor(remaining / series->deltaT); \
316  length = (length > MAXLEN ? MAXLEN : length); \
317  if (series->data->length != length) \
318  XLALResize ## laltype ## TimeSeries(series, 0, length); \
319  XLALFrStreamGet ## laltype ## TimeSeries(series, stream); \
320  for (i = 0; i < series->data->length; ++i) { \
321  char tstr[32]; \
322  laltype value = series->data->data[i]; \
323  LIGOTimeGPS t = series->epoch; \
324  XLALGPSAdd(&t, i * series->deltaT); \
325  fprintf(stdout, "%s", XLALGPSToStr(tstr, &t)); \
326  fputs(FS, stdout); \
327  fprintf(stdout, format, __VA_ARGS__); \
328  fputs(RS, stdout); \
329  } \
330  XLALGPSAdd(start, series->data->length * series->deltaT); \
331  } \
332  XLALDestroy ## laltype ## TimeSeries(series); \
333 }
334 
335 /* *INDENT-OFF* */
336 DEFINE_OUTPUT_FUNCTION(INT2, "%" LAL_INT2_PRId, value)
337 DEFINE_OUTPUT_FUNCTION(INT4, "%" LAL_INT4_PRId, value)
338 DEFINE_OUTPUT_FUNCTION(INT8, "%" LAL_INT8_PRId, value)
339 DEFINE_OUTPUT_FUNCTION(UINT2, "%" LAL_INT2_PRIu, value)
340 DEFINE_OUTPUT_FUNCTION(UINT4, "%" LAL_INT4_PRIu, value)
341 DEFINE_OUTPUT_FUNCTION(UINT8, "%" LAL_INT8_PRIu, value)
342 DEFINE_OUTPUT_FUNCTION(REAL4, "%.7g", value)
343 DEFINE_OUTPUT_FUNCTION(REAL8, "%.15g", value)
344 DEFINE_OUTPUT_FUNCTION(COMPLEX8, "(%.7g,%.7g)", crealf(value), cimagf(value))
345 DEFINE_OUTPUT_FUNCTION(COMPLEX16, "(%.15g,%.15g)", creal(value), cimag(value))
346 /* *INDENT-ON* */
const char * program
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
LALCache * XLALCacheImport(const char *fname)
LALCache * XLALCacheGlob(const char *dirstr, const char *fnptrn)
LALTYPECODE
uint64_t UINT8
double complex COMPLEX16
double REAL8
int16_t INT2
int64_t INT8
uint16_t UINT2
uint32_t UINT4
float complex COMPLEX8
int32_t INT4
float REAL4
LAL_C_TYPE_CODE
LAL_U2_TYPE_CODE
LAL_Z_TYPE_CODE
LAL_S_TYPE_CODE
LAL_I2_TYPE_CODE
LAL_I8_TYPE_CODE
LAL_D_TYPE_CODE
LAL_I4_TYPE_CODE
LAL_U8_TYPE_CODE
LAL_U4_TYPE_CODE
int XLALFrStreamSeek(LALFrStream *stream, const LIGOTimeGPS *epoch)
Seeks a LALFrStream stream to data at a given time.
Definition: LALFrStream.c:542
int XLALFrStreamSeekO(LALFrStream *stream, double dt, int whence)
Seeks a LALFrStream stream by a time offset.
Definition: LALFrStream.c:676
int XLALFrStreamTell(LIGOTimeGPS *epoch, LALFrStream *stream)
Tells the current time of the current position of a LALFrStream stream.
Definition: LALFrStream.c:717
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
int XLALFrStreamGetMode(LALFrStream *stream)
Returns the current operating mode of a LALFrStream.
Definition: LALFrStream.c:284
int XLALFrStreamSetMode(LALFrStream *stream, int mode)
Change the operating mode of a LALFrStream.
Definition: LALFrStream.c:327
@ LAL_FR_STREAM_TIMEWARN_MODE
display warning for invalid time requests
Definition: LALFrStream.h:82
@ LAL_FR_STREAM_IGNORETIME_MODE
ignore invalid times requested
Definition: LALFrStream.h:86
LALTYPECODE XLALFrStreamGetTimeSeriesType(const char *chname, LALFrStream *stream)
Returns the type code for the data type of channel chname in the current frame in frame stream stream...
char char * XLALStringDuplicate(const char *s)
void XLALAbortErrorHandler(const char *func, const char *file, int line, int errnum)
XLALErrorHandlerType * XLALSetErrorHandler(XLALErrorHandlerType *newHandler)
LIGOTimeGPS * XLALGPSSetREAL8(LIGOTimeGPS *epoch, REAL8 t)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
end
void output_INT2(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
double dt
Definition: stream.c:110
int main(int argc, char *argv[])
Definition: stream.c:135
LALCache * cache
Definition: stream.c:107
double t0
Definition: stream.c:109
int usage(const char *program)
Definition: stream.c:290
#define DEFINE_OUTPUT_FUNCTION(laltype, format,...)
Definition: stream.c:303
int parseargs(int argc, char **argv)
Definition: stream.c:213
void output_UINT2(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
void output_UINT8(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
void output_REAL8(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
void output_COMPLEX16(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
void output_COMPLEX8(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
char * channel
Definition: stream.c:108
void output_REAL4(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
void output_UINT4(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
void output_INT4(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
void output_INT8(LALFrStream *stream, const char *channame, LIGOTimeGPS *start, LIGOTimeGPS *end)
This structure details the state of the frame stream.
Definition: LALFrStream.h:95
const char * name
int * flag