LALPulsar  6.1.0.1-c9a8ef6
hwinject.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2003-9 Bruce Allen, Peter Shawhan
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  * \file
22  * \ingroup lalpulsar_bin_Tools
23  * \author Bruce Allen, Peter Shawhan
24  * \brief Multipulsar injection routine
25  *
26  * How it works
27  * ============
28  *
29  * (adapted from \c README.s3inject by Bruce Allen)
30  *
31  * There are two executables: \c lalpulsar_Makefakedata_v4 and \c lalpulsar_hwinject.
32  *
33  * \c lalpulsar_Makefakedata_v4 generates a continuous stream of data for a single
34  * pulsar, using a file called \c Pulsar.N to get the pulsar's parameters,
35  * and command line arguments to get the starting GPS time and detector
36  * name. It can write either to files or to stdout.
37  *
38  * \c lalpulsar_hwinject starts up M copies of \c lalpulsar_Makefakedata_v4, each with a
39  * different set of parameters, gathers their output, and adds it
40  * together, writing it to stdout.
41  *
42  * Both of these executables support a \c -h command-line argument that
43  * will give you a command-line argument summary description. Try it
44  * before reading further:
45  * \code
46  * lalpulsar_Makefakedata_v4 -h
47  * lalpulsar_hwinject -h
48  * \endcode
49  *
50  * In this document we assume you will inject 5 pulsar signals total.
51  *
52  * Create pulsar parameter files
53  * -----------------------------
54  *
55  * Create a files called \c Pulsar.0 to \c Pulsar.4 containing the parameters
56  * of the pulsars that you wish the inject. These files should be
57  * "almost" identical at the different sites. They only differ because
58  * the Actuation function differs between the sites.
59  *
60  * I have included five files - but note that the parameters to be used
61  * "for real" still need to be determined. People who should help
62  * creating these parameter files include: Riles, S. Anderson,
63  * G. Mendell, X. Siemens, G. Woan and M. Landry. These files, once
64  * created, should be made read-only, and should only be modified if the
65  * instrument Actuation function changes. Be sure to save a copy of them
66  * someplace safe.
67  *
68  * Note: Each pulsar's parameters are defined at a particular fiducial
69  * Solar System Barycenter (SSB) time. In this document, I call this
70  * time \f$ t_S \f$ . The actual choice of this time is not important,
71  * but it should be fixed and invariant. The team defining pulsar
72  * parameters may wish to change the value to something that they find
73  * convenient.
74  *
75  * At the end of this document is a more detailed description of the
76  * \c Pulsar.N parameter files.
77  *
78  * Create command-line argument files
79  * ----------------------------------
80  *
81  * Create files called \c in.0 to \c in.4. Each file should contain one line.
82  * This is used to construct the command-line arguments for
83  * \c lalpulsar_Makefakedata_v4.
84  *
85  * The file \c in.0 should look like this:
86  * \code
87  * lalpulsar_Makefakedata_v4 @Pulsar.0 -I LHO -S 751680013 -b
88  * \endcode
89  *
90  * and the other \c in.N files should be identical except that they should
91  * contain \c Pulsar.N. The \c in.N files at LLO should contain \c LLO rather
92  * than \c LHO.
93  *
94  * Verify setup
95  * ------------
96  *
97  * To test your setup, do the following:
98  * \code
99  * lalpulsar_hwinject -n 5 -G 751680013 -s
100  * \endcode
101  *
102  * The \c -s option is a show option. It makes \c lalpulsar_hwinject read
103  * the command line files \c in.N and show you the \b exact commands it would
104  * actually run (preceeded by an integer count of the form <tt>[XX]</tt>). The
105  * \c -G command line argument is the GPS time at which to start producing
106  * data.
107  *
108  * Now let's make some output (but just from one pulsar):
109  * \code
110  * lalpulsar_hwinject -n 1 -G 751680013 -T -X 2> infolog | head -20
111  * \endcode
112  *
113  * The <tt>2> infolog</tt> redirects stderr into an information log. Have a look.
114  *
115  * The \c -T option makes \c lalpulsar_hwinject output in human readable text
116  * rather than binary
117  *
118  * The \c -X option makes \c lalpulsar_hwinject output an X axis as well.
119  *
120  * Notice that the first number output by \c lalpulsar_hwinject is \c always
121  * 1234.5, which is a key to use in checking endian ordering and general
122  * sanity.
123  *
124  * Now let's go "whole hog":
125  * \code
126  * lalpulsar_hwinject -n 5 -G 751680013 2> infolog | od -w4 -f | more
127  * \endcode
128  *
129  * This shows you the raw binary output in single column format
130  *
131  * CPU and resource use
132  * --------------------
133  *
134  * On my 1 GHz PIII laptop, this job:
135  * \code
136  * lalpulsar_hwinject -n 5 -G 751680013 2> infolog > /dev/null
137  * \endcode
138  *
139  * runs at five time real time speed, has a starup latency of around 1
140  * second, and uses 11 MB of memory per pulsar (55 MB total).
141  *
142  * Defining Pulsar.* files
143  * -----------------------
144  *
145  * Here is a typical file:
146  * \code
147  * refTime = 751680013 ## pulsar reference time in SSB frame
148  * aPlus = 4.996981857609109e-26 ## plus-polarization signal amplitude
149  * aCross = 4.868177666869495e-26 ## cross-polarization signal amplitude
150  * psi = 0.770087086 ## polarization angle psi (radians)
151  * phi0 = 2.66 ## phase at reference time
152  * Freq = 265.5771052 ## GW frequency at reference time
153  * Delta = -0.981180225 ## declination (radians)
154  * Alpha = 1.248816734 ## right ascension (radians)
155  * f1dot = -4.15E-12 ## 1st frequency derivative
156  * f2dot = 0.0 ## 2nd frequency derivative
157  * f3dot = 0.0 ## 3rd frequency derivative
158  * \endcode
159  *
160  * This structure contains gravitational wave source position (in
161  * Equatorial coordinates), and orientation angle.
162  * Equatorial coordinates are the standard sky-fixed coordinate
163  * system. The z-axis is defined as for geographic coordinates, above;
164  * the plane orthogonal to this passing through the Earth's centre is
165  * called the equator. The x-axis is defined to be the direction, as
166  * viewed from the centre of the Earth, where the Sun appears to cross
167  * the equator moving north in spring. This is called the vernal equinox,
168  * and is shown in Fig. 16.6. In this coordinate system, the latitude
169  * coordinate is called the declination \f$ \delta \f$ and the longitude
170  * coordinate is called the right ascension \f$ \alpha \f$ .
171  * (See also \ref SkyCoordinates_h.)
172  *
173  * \c aPlus and \c aCross set the amplitude of the two polarizations. This is
174  * where you can insert an amplitude calibration factor.
175  *
176  * The only other value to note is \c phi0. This is where you can insert a
177  * phase calibration offset, if needed. Note: \c phi0 is \b not scaled by a
178  * factor of two. In other words, if you set <tt>phi=PI</tt>, you'll find the
179  * output inverted. If you set <tt>phi=PI/2</tt>, you'll see the output phase
180  * retarted. In other words, the peak of a particular cycle occurs one
181  * quarter of a cycle \b earlier.
182  *
183  * To see this clearly, just do something like:
184  * \code
185  * lalpulsar_hwinject -n 1 -G 751680013 -T | head -100 > junk1
186  * \endcode
187  * Then change the value of \c phi0 in \c Pulsar.0, and do it again:
188  * \code
189  * lalpulsar_hwinject -n 1 -G 751680013 -T | head -100 > junk2
190  * \endcode
191  * Comparing \c junk1 and \c junk2 should make the sign convention of \c phi0 very
192  * clear.
193  *
194  * Calibration lines
195  * -----------------
196  *
197  * The \c lalpulsar_hwinject executable can inject up to three calibration
198  * lines. Here they are denoted by <tt>L==low</tt>, <tt>M==medium</tt> and
199  * <tt>H==high</tt> to indicate the frequency. They are defined by:
200  * \code
201  * DARM = A_L sin(2 pi f_L (GPS-GPS_0)) +
202  * A_M sin(2 pi f_M (GPS-GPS_0)) +
203  * A_H sin(2 pi f_H (GPS-GPS_0))
204  * \endcode
205  * where <tt>GPS_0 = 751680013</tt>. In the code, the frequencies are hardwired to:
206  * \code
207  * f_L = 52.296875 = 52+1/4+1/32+1/64 Hz
208  * f_M = 166.6875 = 166+1/2+1/8+1/16 Hz
209  * f_H = 927.6875 = 927+1/2+1/8+1/16 Hz
210  * \endcode
211  * These can be changed, but (1) MUST be exactly represented as IEEE754
212  * floats (not doubles) and (2) MUST be positive.
213  *
214  * The amplitudes of the injected lines are defined by three arguments (\c -L, \c -M and \c -H) to
215  * \c lalpulsar_hwinject which set the amplitudes of the three lines. The arguments are, for example:
216  * \code
217  * lalpulsar_hwinject -n 0 -T -G 12345678 -L 17.76 | more
218  * \endcode
219  * will inject a calibration line at low frequency with an amplitude of
220  * 17.76. You can include any combination of \c -L, \c -M and \c -H. If one of
221  * these arguments is not present, then its assumed amplitude is zero.
222  *
223  * You can inject five pulsars plus three calibration lines with:
224  * \code
225  * lalpulsar_hwinject -n 5 -L 0.003 -M 0.0006 -H 0.8 -G 751680013 -T | more
226  * \endcode
227  *
228  * Note: a good check that the calibration line injection code works
229  * correctly is to compare the output with GPS times offset by integer
230  * multiples of 64 seconds. Since the smallest fractional part of the
231  * frequencies above is 1/64 Hz, the calibration signal should repeat
232  * exactly every 64 seconds.
233  *
234  * The \c -p option to \c lalpulsar_hwinject prints out the built-in
235  * calibration line frequencies.
236  *
237  * Comments
238  * --------
239  *
240  * I've tried to make \c lalpulsar_hwinject fairly robust. In particular,
241  * it catches \c SIGCHLD and if a child has been terminated (rather than
242  * just being stopped) it tries to say why. System related errors print
243  * errno and it's interpretation. Most error messages should come with a
244  * PID to help figure out which process is going bad.
245  *
246  * Note that under Solaris, the pid returned with these error messages
247  * appears to be the PID of the shell (started by popen) under which the
248  * child was started. This is usually one less than the PID of the
249  * associated \c lalpulsar_Makefakedata_v4 process.
250  *
251  * If you send SIGUSR1 to \c lalpulsar_hwinject:
252  * \code
253  * kill -SIGUSR1 PID
254  * \endcode
255  * then it will report to stderr the amount of simulated data that it has
256  * made (days/hours/minutes/seconds). Be careful \b not to send the signal
257  * to the entire process group, since the children don't catch this
258  * signal and will respond to it by terminating!
259  *
260  * The \c lalpulsar_hwinject program can be used to inject signals from sources \b other
261  * than pulsars. To use it in this way, your code must do the following:
262  *
263  * 1. write data to stdout, errors to stderr
264  *
265  * 2. take a command line argument which is GPS seconds and start its
266  * output at that time: <tt>-G secs</tt>
267  *
268  * 3. be able to run faster than real time under Solaris. It should
269  * produce data at a sample rate of 16384 Hz in blocks of an integer
270  * number of seconds (called S below).
271  *
272  * 4. have the following internal structure. Here \c S is the number of
273  * seconds, for example, 30, that your code uses internally to compute
274  * the next block of output.
275  * \code
276  * main() {
277  *
278  * int length=S*16384;
279  *
280  * float magic=1234.5;
281  * fwrite(&magic, sizeof(float), 1, stdout);
282  *
283  * while (1) {
284  *
285  * // compute next output data, may be time-consuming ...
286  *
287  * fwrite(&data, sizeof(float), length, stdout);
288  *
289  * fflush(stdout);
290  * }
291  * }
292  * \endcode
293  * The <tt>fflush(stdout)</tt> is \b very important. It ensures that your program
294  * will have time to compute its next block of data \b before it is needed
295  * by \c lalpulsar_hwinject.
296  * 5. create an \c in.N file for your executable. See description above.
297  *
298  * Changelog
299  * =========
300  *
301  * - Multipulsar injection routine, written for E10/S3 by Bruce Allen, 10/2003.
302  * - Calls to Signal Injection Library added by Peter Shawhan.
303  * - 2005/02: Duncan Brown renamed variable to avoid Condor conflict.
304  * - 2005/02: Reinhard Prix removed the actuation scaling options.
305  * - 28 May 2009: renamed this code from 's3inject' to 'psinject' in lalsuite-GIT
306  * - 19 March - 10 August: Bruce Allen, added ability to output FRAME format
307  * files for VIRGO real-time hardware injections.
308  * - 2022/07: Karl Wette added test script, ported FRAME writing to LALFrame,
309  * add '--fmin' and '--Band' options to command line, moved code to LALPulsar,
310  * renamed lalpulsar_hwinject, RPM packaging
311  */
312 
313 #define _GNU_SOURCE /* for SA_RESTART */
314 
315 #include "config.h"
316 
317 #include <stdio.h>
318 #ifdef HAVE_UNISTD_H
319 #include <unistd.h>
320 #endif
321 #include <stdlib.h>
322 #include <string.h>
323 #include <strings.h>
324 #include <errno.h>
325 #include <stdarg.h>
326 #include <signal.h>
327 #include <sys/types.h>
328 #include <sys/wait.h>
329 #include <time.h>
330 #include <math.h>
331 #include <sys/stat.h>
332 
333 #ifdef ONLINE
334 #ifdef HAVE_GDS_DTT_SISTR_H
335 #include <gds/dtt/SIStr.h>
336 #else
337 #error SIStr header is not available
338 #endif
339 #endif
340 
341 #include <lal/LALMalloc.h>
342 #include <lal/XLALError.h>
343 #include <lal/LALConstants.h>
344 #include <lal/LALgetopt.h>
345 #include <lal/LALPulsarVCSInfo.h>
346 
347 #ifdef HAVE_LIBLALFRAME
348 #include <lal/Units.h>
349 #include <lal/TimeSeries.h>
350 #include <lal/LALFrameIO.h>
351 #endif
352 
353 #define MAXPULSARS 64
354 /* blocksize for gathering results from children */
355 #define BLOCKSIZE 16384
356 
357 /* Flag to initiate graceful shutdown, set by sighandler */
358 volatile int shutdown_pulsar_injection = 0;
359 int npulsars = 0;
362 float testval = 1234.5;
363 char *directory;
364 char *channel = NULL;
365 int gpstime = 0;
367 int show = 0;
368 int do_axis = 0;
369 int do_text = 0;
370 int write_frames = 0;
371 long long count = 0;
372 long blocks = 0;
373 const char *ifo_name = NULL;
374 const char *actuation = NULL;
375 int sampling_rate = 16384; /* sample rate of output requested by user (default = 16kHz) */
376 double starttime_offset_eff = 0; /* effective starttime offset (in multiple of samples) requested by user*/
377 
378 /* capacity, occupancy, and pointers to input buffers. Cleared to zero
379  on starup because they are initialized data. Units of buffer size
380  and offsets are counted in floats!
381 */
385 
386 double calamp[3] = {0.0, 0.0, 0.0};
387 
388 /*
389  Calibration line frequencies. THE CODE ASSUMES THAT THESE ARE
390  POSITIVE. Order is Low, Medium, High frequency. If you change
391  these, you MUST choose a frequency that can be exactly represented
392  as an IEEE754 floating point floats. For example
393  52+1/4+1/32+1/64=52.296875
394 */
395 double calfreq[3] = {
396  52.296875, /* 52+1/4+1/32+1/64 Hz */
397  166.6875, /* 166+1/2+1/8+1/16 Hz */
398  927.6875 /* 927+1/2+1/8+1/16 Hz */
399 };
400 
401 /*
402  Calibration line fiducial time.
403 */
404 int tfiducial = 751680013;
405 
406 FILE *fp[MAXPULSARS];
407 
408 /* forward declaration */
409 void syserror( int showerrno, const char *fmt, ... );
410 void sighandler( int sig );
411 void usage( FILE *filep );
412 int parseinput( int argc, char **argv );
413 
414 /* signal handler to monitor the status of children catch SIGCHLD */
415 void sighandler( int sig )
416 {
417  pid_t pid;
418  int status;
419  long long seconds = ( ( long long )blocks ) * ( ( long long )BLOCKSIZE ) / ( ( long long )sampling_rate );
420  int minutes = seconds / 60;
421  int hours = minutes / 60;
422  int days = hours / 24;
423  int secs = seconds % 60;
424 
425  syserror( 0, "made %d days %d hours %d minutes %d seconds of data\n",
426  days, hours % 24, minutes % 60, secs );
427 
428  syserror( 0, "Received signal %d\n", sig );
429 
430  if ( sig == SIGTERM ) {
431  syserror( 0, "received SIGTERM, initiating graceful shutdown...\n" );
433  }
434 
435  if ( sig != SIGCHLD ) {
436  return;
437  }
438 
439  if ( ( pid = waitpid( -1, &status, WNOHANG | WUNTRACED ) ) > 0 ) {
440  /* if child stopped, make log entry then return */
441  if ( WIFSTOPPED( status ) ) {
442  syserror( 0, "Subprocess [PID=%d] stopped because it caught signal %d [%s]\n",
443  ( int )pid, WSTOPSIG( status ), strsignal( WSTOPSIG( status ) ) );
444  return;
445  }
446 
447  /* otherwise something more serious is wrong... */
448  syserror( 0, "Subprocess [PID=%d] is misbehaving.\n", ( int )pid );
449  if ( WIFEXITED( status ) ) {
450  syserror( 0, "Subprocess [PID=%d] or shell did exit(%d)\n", ( int )pid, WEXITSTATUS( status ) );
451  }
452 
453  if ( WIFSIGNALED( status ) )
454  syserror( 0, "Subprocess [PID=%d] terminated because it caught signal %d [%s]\n",
455  ( int )pid, WTERMSIG( status ), strsignal( WTERMSIG( status ) ) );
457  } else {
458  syserror( 1, "waitpid() returned -1. Call Bruce...\n" );
459  }
460  return;
461 }
462 
463 /* Like perror() but takes variable numbers of arguments and includes program name */
464 void syserror( int showerrno, const char *fmt, ... )
465 {
466  char *thiserror = NULL;
467  pid_t pid = getpid();
468  time_t t = time( NULL );
469  va_list ap;
470  /* initialize variable argument list */
471  va_start( ap, fmt );
472  /* print a standardized header with time and PID info */
473  if ( showerrno && errno && ( thiserror = strerror( errno ) ) ) {
474  fprintf( stderr, "%s [PID=%d] %.24s: %s: ", programname, ( int )pid, ctime( &t ), thiserror );
475  } else {
476  fprintf( stderr, "%s [PID=%d] %.24s: ", programname, ( int )pid, ctime( &t ) );
477  }
478  vfprintf( stderr, fmt, ap );
479  va_end( ap );
480  fflush( stderr );
481  return;
482 }
483 
484 /* usage message */
485 void usage( FILE *filep )
486 {
487  fprintf( filep,
488  "--------------------------------------------------------------------------------\n"
489  "%s: \n"
490  "--------------------------------------------------------------------------------\n"
491  "Options are:\n"
492  "-h THIS help message\n"
493  "-v VCS ID information\n"
494  "-n INT Number of pulsars to simulate: 0, 1, 2, ..., %d\n"
495  "-d DIRECTORY Directory containing command line files in.0, in.1, ...\n"
496  " Default is: . (current working directory)\n"
497  "-e CHANNEL Inject excitation into CHANNEL\n"
498  "-D Turn on Debug output for routines in signal injection library\n"
499  "-G INTGPS GPS time (integer seconds) that will be passed on command line\n"
500  "-T Print human readable text rather than binary to stdout\n"
501  "-X Include X-axis in human-readable text output\n"
502  "-s Print commands that would be fork(2)ed, then exit(0)\n"
503  " ---------- --------------------------------------------------\n"
504  "-L DOUBLE | Inject calibration lines. Here L,M,H denote Low/Mid/High |\n"
505  "-M DOUBLE | frequency. The DOUBLE values specifies the corresponding |\n"
506  "-H DOUBLE | amplitude. If NOT given, the amplitude defaults to 0.0 |\n"
507  " ------------- -----------------------------------------------\n"
508  "-p Print the calibration line frequencies in Hz then exit(0)\n"
509  "-I STRING Detector: LHO, LLO, GEO, VIRGO, TAMA, CIT, ROME [REQUIRED]\n"
510  "-A STRING File containing detector actuation-function [OPTIONAL]\n"
511 #ifdef HAVE_LIBLALFRAME
512  "-F INT Keep N frame files on disk. If N==0 write all frames immediately.\n"
513  "-S INT Number of 1-second frames per frame file (default 60).\n"
514 #endif
515  "-r INT Sampling rate (NOTE: strain-generators must use the same!) (Default:16384)\n"
516  "-z DOUBLE Delay: shift CHANNEL signals by round[offset*samplingRate] samples forward (Default:0)\n"
517  "--------------------------------------------------------------------------------\n"
519  );
520  return;
521 }
522 
523 
524 int parseinput( int argc, char **argv )
525 {
526 
527  int c;
528  const char *optionlist = "hL:M:H:n:d:e:DG:TXspI:A:F:vS:r:z:";
529  opterr = 0;
530 
531  double starttime_offset_req = 0; /* requested offset correction to shift start-time of signals into the future */
532  double starttime_offset_samples = 0; /* offset rounded to nearest sample */
533 
534  /* set some defaults */
535  directory = strdup( "." );
536 
537  programname = argv[0];
538 
539  while ( -1 != ( c = LALgetopt( argc, argv, optionlist ) ) ) {
540  char *end;
541  double tempamp;
542  switch ( c ) {
543  case 'v':
544  if ( XLALOutputVCSInfo( stdout, lalPulsarVCSInfoList, 0, "%% " ) != XLAL_SUCCESS ) {
545  XLALPrintError( "XLALOutputVCSInfo() failed!\n" );
546  exit( 1 );
547  }
548  exit( 0 );
549  break;
550 
551  case 'p':
552  printf( "The calibration line frequencies are:\n"
553  " L: %18.14f Hz\n"
554  " M: %18.14f Hz\n"
555  " H: %18.14f Hz\n",
556  calfreq[0], calfreq[1], calfreq[2] );
557  exit( 0 );
558  break;
559  case 'h':
560  /* usage message */
561  usage( stdout );
562  exit( 0 );
563  break;
564 
565  case 'n':
566  /* number of pulsars to simulate */
567  npulsars = atoi( LALoptarg );
568  if ( npulsars < 0 || npulsars > MAXPULSARS ) {
569  syserror( 0, "%s: Number of pulsars (-n argument = %d) must be non-negative and less than %d\n",
570  argv[0], npulsars, MAXPULSARS + 1 );
571  exit( 1 );
572  }
573  break;
574  case 'L':
575  case 'M':
576  case 'H':
577  /* calibration-line amplitude */
578  tempamp = strtod( LALoptarg, &end );
579  if ( *end ) {
580  syserror( 1, "-%c %s is invalid. -%c takes a double-precision amplitude.\n", c, LALoptarg, c );
581  exit( 1 );
582  }
583  /* assign amplitude to the correct line */
584  if ( c == 'L' ) {
585  calamp[0] = tempamp;
586  } else if ( c == 'M' ) {
587  calamp[1] = tempamp;
588  } else {
589  calamp[2] = tempamp;
590  }
591  break;
592  case 'd':
593  /* directory path */
594  if ( directory ) {
595  free( directory );
596  }
597  if ( !( directory = strdup( LALoptarg ) ) ) {
598  syserror( 1, "Out of memory to duplicate -d directory path %s\n", LALoptarg );
599  exit( 1 );
600  }
601  break;
602  case 'e':
603 #ifdef ONLINE
604  /* Excitation channel into which to inject */
605  if ( !( channel = strdup( LALoptarg ) ) ) {
606  syserror( 1, "Out of memory to duplicate -e channel name %s\n", LALoptarg );
607  exit( 1 );
608  }
609 #else
610  syserror( 0, "The -e option to enable online signal injection requires compilation with -DONLINE\n" );
611  exit( 1 );
612 #endif
613  break;
614  case 'D':
615 #ifdef ONLINE
616  /* Turn on debugging for SIStr library routines */
617  SIStr_debug++;
618 #else
619  syserror( 0, "The -D option to enable SIStr debugging requires compilation with -DONLINE\n" );
620  exit( 1 );
621 #endif
622  break;
623  case 'G':
624  /* GPS time to pass as argument */
625  gpstime = atoi( LALoptarg );
626  break;
627  case 'T':
628  /* enable text output */
629  do_text = 1;
630  break;
631  case 'X':
632  /* include x axis in text output */
633  do_axis = 1;
634  break;
635  case 's':
636  /* show commands rather than executing them */
637  show = 1;
638  break;
639  case 'I':
641  break;
642  case 'A':
644  break;
645  case 'F':
646 #ifdef HAVE_LIBLALFRAME
647  {
648  int how_many = atoi( LALoptarg );
649  if ( how_many < 0 ) {
650  syserror( 0, "%s: fatal error, argument -F %d must be non-negative.\n", argv[0], how_many );
651  exit( 1 );
652  }
653  write_frames = 1 + how_many;
654  }
655 #else
656  syserror( 0, "%s: -F specified, but this binary was built without frame support.\n", argv[0] );
657  exit( 1 );
658 #endif
659  break;
660  case 'r':
661  sampling_rate = atoi( LALoptarg );
662  if ( sampling_rate <= 0 ) {
663  syserror( 0, "%s: need positive sampling rate! %d\n", argv[0], sampling_rate );
664  exit( 1 );
665  }
666  if ( sampling_rate % 2 != 0 ) {
667  syserror( 0, "%s: need sampling rate divisible by 2! %d\n", argv[0], sampling_rate );
668  exit( 1 );
669  }
670 #ifdef HAVE_LIBLALFRAME
671  if ( BLOCKSIZE % sampling_rate != 0 ) {
672  syserror( 0, "%s: sampling rate %d must divide evenly into block size %d for frame output\n", argv[0], sampling_rate, BLOCKSIZE );
673  exit( 1 );
674  }
675 #endif
676  break;
677 
678  case 'z':
679  starttime_offset_req = strtod( LALoptarg, &end );
680  if ( end == LALoptarg ) {
681  syserror( 1, "-%c %s is invalid. -%c takes a double-precision amplitude.\n", c, LALoptarg, c );
682  exit( 1 );
683  }
684  break;
685 
686  default:
687  /* error case -- option not recognized */
688  syserror( 0, "%s: Option argument: -%c unrecognized or missing argument.\n"
689  "\t\tPlease use the '-h' option to print usage message\n"
690  , argv[0], optopt );
691  exit( 1 );
692  break;
693 
694  } /* switch(c) */
695 
696  } /* while (LALgetopt) */
697 
698  /* sanity checks on command line arguments */
699  if ( do_axis && !do_text ) {
700  syserror( 0, "The -X (axis) option only works with the -T (human readable) option\n" );
701  exit( 1 );
702  }
703  if ( do_text && channel ) {
704  syserror( 0, "Can't use both '-T' and '-e' together\n" );
705  exit( 1 );
706  }
707  if ( channel && ( strlen( channel ) < 3 || channel[2] != ':' ) ) {
708  syserror( 0, "Excitation channel %s not of form CC:CCC...\n", channel );
709  exit( 1 );
710  }
711  if ( ifo_name == NULL ) {
712  syserror( 0, "You must specify the IFO name (-I)\n" );
713  exit( 1 );
714  }
715 
716 
717  /* "discretize" starttime offset to sampling rate, and
718  * provide some debug-info about starttime shifting */
719  starttime_offset_samples = floor( starttime_offset_req * sampling_rate + 0.5 ); /* correctly *round*, allowing for negative offsets */
720  starttime_offset_eff = starttime_offset_samples / sampling_rate;
721  if ( starttime_offset_req ) {
722  syserror( 0, "starttime OFFSET requested = %+.16g s (offset > 0 means a *delay*)\n", starttime_offset_req );
723  syserror( 0, "effective OFFSET will be = %+.16g s (that is: %+.0f samples)\n", starttime_offset_eff, starttime_offset_samples );
724  }
725 
726 #ifndef ONLINE
727  if ( channel ) {
728  syserror( 0, "Can't do exicitations. Code not compiled with ONLINE defined\n" );
729  exit( 1 );
730  }
731 #endif
732 
733  return 0;
734 }
735 
736 #define MAXLINE 1024
737 int main( int argc, char *argv[] )
738 {
739  int i, j;
740 #ifdef ONLINE
741  char *cwd;
742  int status;
743  SIStream sis;
744  char info[MAXLINE];
745  memset( &sis, '\0', sizeof( SIStream ) );
746 #endif
747 
748 #ifdef HAVE_LIBLALFRAME
749  int framecounter = 0;
750  REAL4TimeSeries *framesim = NULL;
751 #endif
752 
753  parseinput( argc, argv );
754 
755  syserror( 0, "Starting up\n" );
756 
757  /* install signal handler to catch SIGCHLD. Note that solaris uses
758  SysV rather than BSD semantics and doesn't automaticall restart system
759  calls like fread and fwrite. So we use sigaction() rather than
760  signal() so that we can set SA_RESTART. */
761  {
762  struct sigaction sig;
763  memset( &sig, '\0', sizeof( sig ) );
764  sig.sa_flags = SA_RESTART;
765  sig.sa_handler = sighandler;
766  if ( sigaction( SIGCHLD, &sig, NULL ) ) {
767  syserror( 1, "Unable to install signal handler for messages about troubled children\n" );
768  }
769  if ( sigaction( SIGTERM, &sig, NULL ) ) {
770  syserror( 1, "Unable to install signal handler for logging output rate data and terminating\n" );
771  }
772  if ( sigaction( SIGUSR1, &sig, NULL ) ) {
773  syserror( 1, "Unable to install signal handler for logging output rate data\n" );
774  }
775  }
776 
777  for ( i = 0; i < npulsars; i++ ) {
778  char command[MAXLINE];
779  char filename[MAXLINE];
780  FILE *fpc = NULL;
781  int length = 0;
782  char *newlineloc = NULL;
783 
784  /* construct file name */
785  if ( snprintf( filename, MAXLINE, "%s/in.%d", directory, i ) > MAXLINE - 1 ) {
786  syserror( 0, "%s: file name %s/in.%d has more than MAXLINE=%d characters\n",
788  exit( 1 );
789  }
790 
791  /* open file */
792  if ( !( fpc = fopen( filename, "r" ) ) ) {
793  syserror( 1, "Can't open file %s for reading\n", filename );
794  exit( 1 );
795  }
796 
797  /* read command line from file */
798  if ( !( fgets( command, MAXLINE, fpc ) ) ) {
799  syserror( 1, "Command line file %s was empty!\n", filename );
800  exit( 1 );
801  }
802  fclose( fpc );
803 
804  /* check that contents are not too large */
805  length = strlen( command );
806  if ( length >= MAXLINE - 1 ) {
807  syserror( 0, "Command line file %s has line >= to MAXLINE=%d characters!\n",
808  filename, MAXLINE );
809  exit( 1 );
810  }
811 
812  /* replace first NEWLINE to null terminate string */
813  if ( ( newlineloc = strchr( command, '\n' ) ) ) {
814  *newlineloc = '\0';
815  }
816 
817  /* append additional arguments to command line */
818  /* GPS starttime */
819  length = strlen( command );
820  if ( snprintf( command + length, MAXLINE - length, " -G %d", gpstime ) > MAXLINE - length - 1 ) {
821  command[length] = '\0';
822  syserror( 0, "%s: command line has >= MAXLINE=%d characters\n", programname, MAXLINE );
823  exit( 1 );
824  }
825  /* IFO */
826  length = strlen( command );
827  if ( snprintf( command + length, MAXLINE - length, " -I %s", ifo_name ) > MAXLINE - length - 1 ) {
828  command[length] = '\0';
829  syserror( 0, "%s: command line has >= MAXLINE=%d characters\n", programname, MAXLINE );
830  exit( 1 );
831  }
832  /* frequency band; zero to half the sampling rate */
833  length = strlen( command );
834  if ( snprintf( command + length, MAXLINE - length, " --fmin=0 --Band=%d", sampling_rate / 2 ) > MAXLINE - length - 1 ) {
835  command[length] = '\0';
836  syserror( 0, "%s: command line has >= MAXLINE=%d characters\n", programname, MAXLINE );
837  exit( 1 );
838  }
839  /* Actuation-function if given */
840  if ( actuation ) {
841  length = strlen( command );
842  if ( snprintf( command + length, MAXLINE - length, " --actuation=%s", actuation ) > MAXLINE - length - 1 ) {
843  command[length] = '\0';
844  syserror( 0, "%s: command line has >= MAXLINE=%d characters\n", programname, MAXLINE );
845  exit( 1 );
846  }
847  }
848 
849  /* now either show the command or execute it */
850  if ( show ) {
851  printf( "[%02d] %s\n", i, command );
852  } else {
853  errno = 0;
854  if ( !( fp[i] = popen( command, "r" ) ) || errno ) {
855  syserror( 1, "Unable to popen(3) %s\n", command );
856  exit( 1 );
857  }
858  }
859  }
860 
861  /* a useful option for debugging -- show the output */
862  if ( show ) {
863  if ( !npulsars ) {
864  printf( "%s: Warning: n=0 so an infinite-length zero strength signal will be made!\n", argv[0] );
865  }
866  exit( 0 );
867  }
868 
869 #if 0
870  {
871  pid_t pid;
872  int status;
873  /* wait a couple of seconds, then check that all processes are running happily! */
874  sleep( 2 );
875  pid = waitpid( -1, &status, WNOHANG | WUNTRACED );
876  if ( pid ) {
877  syserror( 0, "Subprocess with PID=%d is misbehaving.\n", ( int )pid );
878  if ( WIFEXITED( status ) ) {
879  syserror( 0, "Subprocess or shell did exit(%d)\n", WEXITSTATUS( status ) );
880  }
881 
882  if ( WIFSIGNALED( status ) )
883  syserror( 0, "Subprocess terminated because it caught signal %d [%s]\n",
884  WTERMSIG( status ), strsignal( WTERMSIG( status ) ) );
885  exit( 1 );
886  }
887  }
888 #endif
889 
890  /* processes opened, read data*/
891  for ( i = 0; i < npulsars; i++ ) {
892  if ( fread( &testval, sizeof( float ), 1, fp[i] ) != 1 ) {
893  syserror( 1, "Could not read first float 1234.5 from %d'th signal source\n", i );
894  exit( 1 );
895  } else if ( testval != 1234.5 ) {
896  syserror( 0, "First value (%f) from %d'th signal source was not 1234.5\n", testval, i );
897  exit( 1 );
898  } else if ( fread( bufflen + i, sizeof( int ), 1, fp[i] ) != 1 ) {
899  syserror( 1, "Could not read buffer size from %d'th signal source\n", i );
900  exit( 1 );
901  } else if ( bufflen[i] < sampling_rate || bufflen[i] > sampling_rate * 60 ) {
902  syserror( 0, "Bad buffer size %d floats from %d'th signal source (expect %d <= size <= %d)\n", bufflen[i], i, sampling_rate, 60 * sampling_rate );
903  exit( 1 );
904  } else if ( bufflen[i] % BLOCKSIZE ) {
905  syserror( 0, "Bad buffer size %d floats from %d'th signal source NOT a multiple of BLOCKSIZE=%d\n", bufflen[i], i, BLOCKSIZE );
906  exit( 1 );
907  } else if ( !( buffs[i] = ( float * )calloc( bufflen[i], sizeof( float ) ) ) ) {
908  syserror( 1, "Can't allocate buffer of %d floats for %d'th signal source\n", bufflen[i], i );
909  exit( 1 );
910  }
911  /* ensure that we read buffers on first pass */
912  readfrombuff[i] = bufflen[i];
913  }
914 
915  /* are we calling the excitation engine directly? */
916  if ( channel ) {
917 
918 #ifdef ONLINE
919  /* Report some information about this injection client */
920  cwd = getcwd( NULL, 256 );
921  if ( cwd ) {
922  sprintf( info, "%s %s", argv[0], cwd );
923  } else {
924  sprintf( info, "%s unknown_directory", argv[0] );
925  }
926  free( cwd );
927  SIStrAppInfo( info );
928 
929  /* Open the Signal Injection Stream */
930  status = SIStrOpen( &sis, channel, sampling_rate, ( double ) gpstime + starttime_offset_eff );
931  if ( SIStr_debug ) {
932  syserror( 0, "SIStrOpen() returned %d\n", status );
933  }
934  if ( status != SIStr_OK ) {
935  syserror( 0, "SIStrOpen() error opening SIStream: %s\n", SIStrErrorMsg( status ) );
936  exit( 2 );
937  }
938 #endif
939  } else if ( do_text ) {
940  printf( "1234.5\n" );
941  } else {
942  /* write out 1234.5 */
943  if ( 1 != fwrite( &testval, sizeof( float ), 1, stdout ) ) {
944  syserror( 1, "Unable to output key value 1234.5\n" );
945  exit( 1 );
946  }
947  }
948 
949  /* now read data blocks unless a SIGTERM has set shutdown */
950  while ( !shutdown_pulsar_injection ) {
951  int num = 0;
952  int line;
953  int tdelt = gpstime - tfiducial;
954 
955  /* clear block that will contain totals */
956  for ( j = 0; j < BLOCKSIZE; j++ ) {
957  total[j] = 0.0;
958  }
959 
960  /* if needed, insert calibration line(s) */
961  for ( line = 0; line < 3; line++ ) {
962  if ( calamp[line] != 0.0 ) {
963  /* normal int and double variables for integer/fractional
964  time. In this and in the code that follows, _fra refers to
965  the fractional part [0,1) and _int refers to the integer
966  part. */
967 
968  double dt_fra;
969 
970  /* Avoid long longs in inner loop as they are slow. */
971  long long t_rem = blocks, t_int = BLOCKSIZE;
972 
973  /* line amplitude and frequency (integer + fractional parts) */
974  double f_fra = calfreq[line];
975  int f_int = ( int )f_fra;
976  f_fra -= f_int;
977 
978  /* integer and fractional time offsets of first sample */
979  t_rem *= t_int;
980  t_int = t_rem;
981  t_int /= sampling_rate;
982  t_rem -= t_int * sampling_rate;
983  t_int += tdelt;
984 
985  // unused: int dt_int = t_int;
986  dt_fra = t_rem;
987  dt_fra /= sampling_rate;
988 
989  for ( j = 0; j < BLOCKSIZE; j++ ) {
990  double cycles1, cycles2, cycles3;
991  double tlocal_fra = dt_fra + ( double )j / ( ( double )sampling_rate );
992  int tlocal_int = ( int )tlocal_fra;
993  tlocal_fra -= tlocal_int;
994  tlocal_int += t_int;
995  cycles1 = f_fra * tlocal_int;
996  cycles1 -= ( int )cycles1;
997  cycles2 = tlocal_fra * f_int;
998  cycles2 -= ( int )cycles2;
999  cycles3 = tlocal_fra * f_fra;
1000  cycles3 -= ( int )cycles3;
1001 
1002  total[j] = calamp[line] * sin( 2 * LAL_PI * ( cycles1 + cycles2 + cycles3 ) );
1003  }
1004  }
1005  }
1006 
1007  /* loop over the different pulsars */
1008  for ( i = 0; i < npulsars; i++ ) {
1009  float *where;
1010 
1011  if ( readfrombuff[i] == bufflen[i] ) {
1012  /* read data from the i'th signal */
1013  if ( bufflen[i] != ( num = fread( buffs[i], sizeof( float ), bufflen[i], fp[i] ) ) ) {
1014  syserror( 1, "Only read %d floats (not %d) from %d'th signal source\n", num, bufflen[i], i );
1015  exit( 1 );
1016  }
1017 #ifdef DEBUGTIMING
1018  syserror( 0, "just read %d seconds of data from %d'th signal\n", num / sampling_rate, i );
1019 #endif
1020  readfrombuff[i] = 0;
1021  }
1022 
1023  /* location of signal in buffer */
1024  where = buffs[i] + readfrombuff[i];
1025 
1026  /* add i'th pulsar to the total signal */
1027  for ( j = 0; j < BLOCKSIZE; j++ ) {
1028  total[j] += where[j];
1029  }
1030 
1031  readfrombuff[i] += BLOCKSIZE;
1032  }
1033 
1034  /* now output the total signal to frames */
1035 
1036  if ( write_frames ) {
1037 #ifdef HAVE_LIBLALFRAME
1038 
1039  const int secs_per_framefile = BLOCKSIZE / sampling_rate;
1040 
1041  /* allocate time series */
1042  if ( !framesim ) {
1043  const char frName[] = "CW_simulated";
1044  framesim = XLALCreateREAL4TimeSeries( frName, 0, 0, 1.0 / sampling_rate, &lalDimensionlessUnit, BLOCKSIZE );
1045  if ( !framesim ) {
1046  syserror( 1, "XLALCreateREAL4TimeSeries() failed" );
1047  exit( 1 );
1048  }
1049  }
1050 
1051  /* set up GPS time, copy data */
1052  framesim->epoch.gpsSeconds = gpstime + framecounter * secs_per_framefile;
1053  for ( size_t m = 0; m < BLOCKSIZE; m++ ) {
1054  framesim->data->data[m] = total[m];
1055  }
1056 
1057  /* create frame */
1058  const char framename[] = "CW_Injection";
1059  LALFrameH *frame = XLALFrameNew( &framesim->epoch, secs_per_framefile, framename, 1, framecounter, 0 );
1060  if ( !frame ) {
1061  syserror( 1, "XLALFrameNew() failed" );
1062  exit( 1 );
1063  }
1064 
1065  /* add data to frame */
1066  if ( XLALFrameAddREAL4TimeSeriesSimData( frame, framesim ) != XLAL_SUCCESS ) {
1067  syserror( 1, "!XLALFrameAddREAL4TimeSeriesSimData() failed" );
1068  exit( 1 );
1069  }
1070 
1071  /* write data to framefile */
1072  char framefilename[256];
1073  snprintf( framefilename, sizeof( framefilename ), "%s-%d-%d.gwf", framename, framesim->epoch.gpsSeconds, secs_per_framefile );
1074  if ( XLALFrameWrite( frame, framefilename ) ) {
1075  syserror( 1, "Error during frame write" );
1076  exit( 1 );
1077  }
1078 
1079  /* free memory for frames and for simdata structures */
1080  XLALFrameFree( frame );
1081 
1082  /* Do we keep a limited set of frames on disk? */
1083  if ( write_frames > 1 ) {
1084  char listname[256];
1085  int watchtime = gpstime + secs_per_framefile * ( framecounter / secs_per_framefile - write_frames + 1 );
1086  sprintf( listname, "%s-%d-%d.gwf", framename, watchtime, secs_per_framefile );
1087  /* syserror(0, "Watching for file %s to disappear....\n", listname); */
1088  struct stat statbuf;
1089  while ( !stat( listname, &statbuf ) ) {
1090  /* if enough files already in place, then sleep 0.1 seconds */
1091  struct timespec rqtp;
1092  rqtp.tv_sec = 0;
1093  rqtp.tv_nsec = 100000000;
1094  nanosleep( &rqtp, NULL );
1095  }
1096  }
1097 
1098  /* increment counter for the next second */
1099  framecounter++;
1100 #else
1101  syserror( 0, "ERROR: write_frames!=0, but binary was built without Frame support\n" );
1102  exit( 1 );
1103 #endif
1104  } /* if (write_frames) */
1105 
1106  /* now output the total signal... */
1107  else if ( channel ) {
1108 #ifdef ONLINE
1109  /* ... to the excitation engine ... */
1110  status = SIStrAppend( &sis, total, BLOCKSIZE, 1.0 );
1111  if ( SIStr_debug >= 2 ) {
1112  syserror( 0, "SIStrAppend() returned %d\n", status );
1113  }
1114  if ( status != SIStr_OK ) {
1115  syserror( 0, "SIStrAppend() error adding data to stream: %s\n",
1116  SIStrErrorMsg( status ) );
1117  break;
1118  }
1119 #endif
1120  }
1121  /* ... or as text ... */
1122  else if ( do_text ) {
1123  if ( do_axis ) {
1124  /* ... either as text with both x and y axes ... */
1125  long long x1 = gpstime;
1126  long long E9 = 1000000000;
1127  x1 *= E9;
1128  x1 += ( long long )( starttime_offset_eff * E9 ); /* account for startime-shift, consistent with CHANNEL injection */
1129 
1130  for ( j = 0; j < BLOCKSIZE; j++ ) {
1131  long long x2 = count, x3;
1132  x2 *= E9;
1133  x2 /= ( sampling_rate );
1134  x2 += x1;
1135  x3 = x2;
1136  x3 /= E9;
1137  x2 -= x3 * E9;
1138  printf( "%lld.%09lld %g\n", x3, x2, total[j] );
1139  count++;
1140  }
1141  } else {
1142  /* ... or as y-axis text only ... */
1143  for ( j = 0; j < BLOCKSIZE; j++ ) {
1144  printf( "%g\n", total[j] );
1145  }
1146  }
1147  } else {
1148  /* ... or in raw binary form. */
1149  if ( BLOCKSIZE != ( num = fwrite( total, sizeof( float ), BLOCKSIZE, stdout ) ) ) {
1150  syserror( 1, "Only wrote %d values (not %d)\n", num, BLOCKSIZE );
1151  exit( 1 );
1152  }
1153 #ifdef DEBUGTIMING
1154  syserror( 0, "Just sent %d seconds of data to system\n", BLOCKSIZE / sampling_rate );
1155  sleep( BLOCKSIZE / sampling_rate );
1156 #endif
1157  }
1158 
1159  /* increment counter of blocks sent out */
1160  blocks++;
1161  }
1162 
1163  /* We'll be exiting, so clean up */
1164  if ( channel ) {
1165 #ifdef ONLINE
1166  /* Close the signal injection stream */
1167  status = SIStrClose( &sis );
1168  if ( SIStr_debug ) {
1169  syserror( 0, "SIStrClose returned %d\n", status );
1170  }
1171  if ( status != SIStr_OK ) {
1172  syserror( 0, "Error while closing SIStream: %s\n", SIStrErrorMsg( status ) );
1173  exit( 2 );
1174  }
1175 #endif
1176  }
1177 
1178 #ifdef _LINUX
1179  /* shut down signal handler for SIGCHLD */
1180  {
1181  struct sigaction sig;
1182  memset( &sig, '\0', sizeof( sig ) );
1183  sig.sa_flags = SA_RESTART | SA_NOCLDSTOP;
1184  sig.sa_handler = SIG_IGN;
1185  if ( sigaction( SIGCHLD, &sig, NULL ) ) {
1186  syserror( 1, "Unable to install signal handler for exiting\n" );
1187  }
1188  if ( sigaction( SIGPIPE, &sig, NULL ) ) {
1189  syserror( 1, "Unable to install signal handler for exiting\n" );
1190  }
1191  }
1192 
1193  for ( i = 0; i < npulsars; i++ ) {
1194  int status;
1195 
1196  __fpurge( fp[i] );
1197  status = pclose( fp[i] );
1198  if ( status != -1 ) {
1199  syserror( 0, "The %d'th signal generator did exit(%d)\n", i, ( int )WEXITSTATUS( status ) );
1200  } else {
1201  syserror( 1, "Trouble shutting down the %d'th signal generator\n", i );
1202  exit( 1 );
1203  }
1204  }
1205 #endif
1206 
1207 #ifdef HAVE_LIBLALFRAME
1208  XLALDestroyREAL4TimeSeries( framesim );
1209 #endif
1210 
1212 
1213  /* and exit cleanly */
1214  syserror( 0, "Shutdown complete, exiting cleanly\n" );
1215  exit( 0 );
1216 }
int j
void LALCheckMemoryLeaks(void)
const LALVCSInfoList lalPulsarVCSInfoList
NULL-terminated list of VCS and build information for LALPulsar and its dependencies
#define c
int LALgetopt(int argc, char *const *argv, const char *optstring)
char * LALoptarg
#define fprintf
#define LAL_PI
LALFrameUFrameH LALFrameH
int XLALFrameWrite(LALFrameH *frame, const char *fname)
int XLALFrameAddREAL4TimeSeriesSimData(LALFrameH *frame, const REAL4TimeSeries *series)
LALFrameH * XLALFrameNew(const LIGOTimeGPS *epoch, double duration, const char *project, int run, int frnum, INT8 detectorFlags)
void XLALFrameFree(LALFrameH *frame)
int XLALOutputVCSInfo(FILE *fp, const LALVCSInfoList vcs_list, const int verbose, const char *prefix)
static const INT4 m
void XLALDestroyREAL4TimeSeries(REAL4TimeSeries *series)
REAL4TimeSeries * XLALCreateREAL4TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalDimensionlessUnit
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_SUCCESS
int tfiducial
Definition: hwinject.c:404
const char * actuation
Definition: hwinject.c:374
int main(int argc, char *argv[])
Definition: hwinject.c:737
int do_axis
Definition: hwinject.c:368
long blocks
Definition: hwinject.c:372
int sampling_rate
Definition: hwinject.c:375
long long count
Definition: hwinject.c:371
#define MAXLINE
Definition: hwinject.c:736
char * programname
Definition: hwinject.c:366
float data[BLOCKSIZE]
Definition: hwinject.c:360
int readfrombuff[MAXPULSARS]
Definition: hwinject.c:383
double calamp[3]
Definition: hwinject.c:386
char * channel
Definition: hwinject.c:364
volatile int shutdown_pulsar_injection
Definition: hwinject.c:358
int npulsars
Definition: hwinject.c:359
char * directory
Definition: hwinject.c:363
int show
Definition: hwinject.c:367
int do_text
Definition: hwinject.c:369
float total[BLOCKSIZE]
Definition: hwinject.c:361
float testval
Definition: hwinject.c:362
double calfreq[3]
Definition: hwinject.c:395
int gpstime
Definition: hwinject.c:365
void sighandler(int sig)
Definition: hwinject.c:415
#define MAXPULSARS
Definition: hwinject.c:353
FILE * fp[MAXPULSARS]
Definition: hwinject.c:406
void usage(FILE *filep)
Definition: hwinject.c:485
void syserror(int showerrno, const char *fmt,...)
Definition: hwinject.c:464
int write_frames
Definition: hwinject.c:370
int bufflen[MAXPULSARS]
Definition: hwinject.c:382
int parseinput(int argc, char **argv)
Definition: hwinject.c:524
double starttime_offset_eff
Definition: hwinject.c:376
const char * ifo_name
Definition: hwinject.c:373
float * buffs[MAXPULSARS]
Definition: hwinject.c:384
#define BLOCKSIZE
Definition: hwinject.c:355
end
REAL4Sequence * data
LIGOTimeGPS epoch
REAL4 * data