Loading [MathJax]/extensions/TeX/AMSmath.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 */
359int npulsars = 0;
362float testval = 1234.5;
364char *channel = NULL;
365int gpstime = 0;
367int show = 0;
368int do_axis = 0;
369int do_text = 0;
371long long count = 0;
372long blocks = 0;
373const char *ifo_name = NULL;
374const char *actuation = NULL;
375int sampling_rate = 16384; /* sample rate of output requested by user (default = 16kHz) */
376double 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
386double 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*/
395double 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*/
404int tfiducial = 751680013;
405
407
408/* forward declaration */
409void syserror( int showerrno, const char *fmt, ... );
410void sighandler( int sig );
411void usage( FILE *filep );
412int parseinput( int argc, char **argv );
413
414/* signal handler to monitor the status of children catch SIGCHLD */
415void 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 */
464void 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 */
485void 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
524int 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
737int 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 */
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
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
REAL4TimeSeries * XLALCreateREAL4TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
void XLALDestroyREAL4TimeSeries(REAL4TimeSeries *series)
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