LAL  7.5.0.1-fe68b98
TimeFreqFFTTest.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2007 Bernd Machenschalk, Duncan Brown, 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  * \file
22  * \ingroup TimeFreqFFT_h
23  *
24  * \brief Tests the routines in \ref TimeFreqFFT.h.
25  *
26  * ### Usage ###
27  *
28  * \code
29  * TimeFreqFFTTest [options]
30  * Options:
31  * -h print this message
32  * -q quiet: run silently
33  * -v verbose: print extra information
34  * -d level set lalDebugLevel to level
35  * \endcode
36  *
37  * ### Exit codes ###
38  *
39  * <table><tr><th>Code</th><th>Explanation</th></tr>
40  * <tr><td>0</td><td>Success, normal exit.</td></tr>
41  * <tr><td>1</td><td>Subroutine failed.</td></tr>
42  * <tr><td>2</td><td>PSD estimation tolerance exceeded</td></tr>
43  * </table>
44  *
45  * ### Uses ###
46  *
47  *
48  * ### Notes ###
49  *
50  */
51 /** \cond DONT_DOXYGEN */
52 #include <config.h>
53 
54 #include <complex.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <math.h>
58 
59 #include <lal/LALStdlib.h>
60 #include <lal/LALgetopt.h>
61 #include <lal/LALConstants.h>
62 #include <lal/LALStdio.h>
63 #include <lal/AVFactories.h>
64 #include <lal/Units.h>
65 #include <lal/Random.h>
66 #include <lal/PrintFTSeries.h>
67 #include <lal/TimeFreqFFT.h>
68 
69 #define CODES_(x) #x
70 #define CODES(x) CODES_(x)
71 
72 int verbose = 0;
73 
74 static void
75 Usage( const char *program, int exitflag );
76 
77 static void
78 ParseOptions( int argc, char *argv[] );
79 
80 static void
81 TestStatus( LALStatus *status, const char *expectedCodes, int exitCode );
82 
83 int main( int argc, char *argv[] )
84 {
85  const UINT4 n = 65536;
86  const REAL4 dt = 1.0 / 16384.0;
87  static LALStatus status;
88 
89  static REAL4TimeSeries x;
90  static COMPLEX8FrequencySeries X;
91 
92  static REAL4TimeSeries y;
93  static REAL4FrequencySeries Y;
94 
95  static COMPLEX8TimeSeries z;
96  static COMPLEX8FrequencySeries Z;
97 
98  RealFFTPlan *fwdRealPlan = NULL;
99  RealFFTPlan *revRealPlan = NULL;
100  ComplexFFTPlan *fwdComplexPlan = NULL;
101  ComplexFFTPlan *revComplexPlan = NULL;
102  RandomParams *randpar = NULL;
103 
104  UINT4 srate[] = { 4096, 9000 };
105  UINT4 npts[] = { 262144, 1048576 };
106  REAL4 var[] = { 5, 16 };
107 
108  UINT4 j, sr, np, vr;
109 
110 
111  /*CHAR fname[2048];*/
112 
113  ParseOptions( argc, argv );
114 
115  LALSCreateVector( &status, &x.data, n );
116  TestStatus( &status, CODES( 0 ), 1 );
117  LALCCreateVector( &status, &X.data, n / 2 + 1 );
118  TestStatus( &status, CODES( 0 ), 1 );
119 
120  LALCCreateVector( &status, &z.data, n );
121  TestStatus( &status, CODES( 0 ), 1 );
122  LALCCreateVector( &status, &Z.data, n );
123  TestStatus( &status, CODES( 0 ), 1 );
124 
125  fwdRealPlan = XLALCreateForwardREAL4FFTPlan( n, 0 );
126  revRealPlan = XLALCreateReverseREAL4FFTPlan( n, 0 );
127  fwdComplexPlan = XLALCreateForwardCOMPLEX8FFTPlan( n, 0 );
128  revComplexPlan = XLALCreateReverseCOMPLEX8FFTPlan( n, 0 );
129  TestStatus( &status, CODES( 0 ), 1 );
130 
131  randpar = XLALCreateRandomParams( 100 );
132 
133 
134  /*
135  *
136  * Try the real transform.
137  *
138  */
139 
140 
141  x.f0 = 0;
142  x.deltaT = dt;
143  x.sampleUnits = lalMeterUnit;
144  snprintf( x.name, sizeof( x.name ), "x" );
145  XLALNormalDeviates( x.data, randpar );
146  for ( j = 0; j < n; ++j ) /* add a 60 Hz line */
147  {
148  REAL4 t = j * dt;
149  x.data->data[j] += 0.1 * cos( LAL_TWOPI * 60.0 * t );
150  }
151  LALSPrintTimeSeries( &x, "x.out" );
152 
153  snprintf( X.name, sizeof( X.name ), "X" );
154  XLALREAL4TimeFreqFFT( &X, &x, fwdRealPlan );
155  LALCPrintFrequencySeries( &X, "X.out" );
156 
157  XLALREAL4FreqTimeFFT( &x, &X, revRealPlan );
158  LALSPrintTimeSeries( &x, "xx.out" );
159 
160 
161  /*
162  *
163  * Try the average power spectum.
164  *
165  */
166 
167 
168  for ( np = 0; np < XLAL_NUM_ELEM(npts) ; ++np )
169  {
170  REAL4Window *window = XLALCreateHannREAL4Window(npts[np]);
171  RealFFTPlan *plan = XLALCreateForwardREAL4FFTPlan(npts[np], 0);
172  /* length of time series for 7 segments, overlapped by 1/2 segment */
173  UINT4 tsLength = npts[np] * 7 - 6 * npts[np] / 2;
174  LALCreateVector( &status, &y.data, tsLength );
175  TestStatus( &status, CODES( 0 ), 1 );
176  LALCreateVector( &status, &Y.data, npts[np] / 2 + 1 );
177  TestStatus( &status, CODES( 0 ), 1 );
178 
179  for ( sr = 0; sr < XLAL_NUM_ELEM(srate) ; ++sr )
180  {
181  /* set the sample rate of the time series */
182  y.deltaT = 1.0 / (REAL8) srate[sr];
183  for ( vr = 0; vr < XLAL_NUM_ELEM(var) ; ++vr )
184  {
185  REAL4 eps = 1e-6; /* very conservative fp precision */
186  REAL4 Sfk = 2.0 * var[vr] * var[vr] * y.deltaT;
187  REAL4 sfk;
188  REAL4 lbn;
189  REAL4 sig;
190  REAL4 ssq;
191  REAL4 tol;
192 
193  /* create the data */
194  XLALNormalDeviates( y.data, randpar );
195  ssq = 0;
196  for ( j = 0; j < y.data->length; ++j )
197  {
198  y.data->data[j] *= var[vr];
199  ssq += y.data->data[j] * y.data->data[j];
200  }
201 
202  /* compute tolerance for comparison */
203  lbn = log( y.data->length ) / log( 2 );
204  sig = sqrt( 2.5 * lbn * eps * eps * ssq / y.data->length );
205  tol = 5 * sig;
206 
207  /* compute the psd and find the average */
208  XLALREAL4AverageSpectrumWelch(&Y, &y, npts[np], npts[np] / 2, window, plan);
209  TestStatus( &status, CODES( 0 ), 1 );
210  {
211  unsigned k;
212  for(sfk = 0., k = 0; k < Y.data->length; sfk += Y.data->data[k++])
213  ;
214  sfk /= Y.data->length;
215  }
216 
217  /* check the result */
218  if ( fabs(Sfk-sfk) > tol )
219  {
220  fprintf( stderr, "FAIL: PSD estimate appears incorrect\n");
221  fprintf( stderr, "expected %e, got %e ", Sfk, sfk );
222  fprintf( stderr, "(difference = %e, tolerance = %e)\n",
223  fabs(Sfk-sfk), tol );
224  exit(2);
225  }
226 
227  }
228  }
229 
230  /* destroy structures that need to be resized */
231  XLALDestroyREAL4FFTPlan( plan );
232  XLALDestroyREAL4Window( window );
233  LALDestroyVector( &status, &y.data );
234  TestStatus( &status, CODES( 0 ), 1 );
235  LALDestroyVector( &status, &Y.data );
236  TestStatus( &status, CODES( 0 ), 1 );
237  }
238 
239 
240  /*
241  *
242  * Try the complex transform.
243  *
244  */
245 
246 
247  z.f0 = 0;
248  z.deltaT = dt;
250  snprintf( z.name, sizeof( z.name ), "z" );
251  { /* dirty hack */
252  REAL4Vector tmp;
253  tmp.length = 2 * z.data->length;
254  tmp.data = (REAL4 *)z.data->data;
255  XLALNormalDeviates( &tmp, randpar );
256  }
257  for ( j = 0; j < n; ++j ) /* add a 50 Hz line and a 500 Hz ringdown */
258  {
259  REAL4 t = j * dt;
260  z.data->data[j] += 0.2 * cos( LAL_TWOPI * 50.0 * t );
261  z.data->data[j] += I * exp( -t ) * sin( LAL_TWOPI * 500.0 * t );
262  }
263  LALCPrintTimeSeries( &z, "z.out" );
264  TestStatus( &status, CODES( 0 ), 1 );
265 
266  snprintf( Z.name, sizeof( Z.name ), "Z" );
267  XLALCOMPLEX8TimeFreqFFT( &Z, &z, fwdComplexPlan );
268  LALCPrintFrequencySeries( &Z, "Z.out" );
269 
270  XLALCOMPLEX8FreqTimeFFT( &z, &Z, revComplexPlan );
271  TestStatus( &status, CODES( 0 ), 1 );
272  LALCPrintTimeSeries( &z, "zz.out" );
273 
274  XLALDestroyRandomParams( randpar );
275 
276  XLALDestroyREAL4FFTPlan( fwdRealPlan );
277  XLALDestroyREAL4FFTPlan( revRealPlan );
278  XLALDestroyCOMPLEX8FFTPlan( fwdComplexPlan );
279  XLALDestroyCOMPLEX8FFTPlan( revComplexPlan );
280 
281  LALCDestroyVector( &status, &Z.data );
282  TestStatus( &status, CODES( 0 ), 1 );
283  LALCDestroyVector( &status, &z.data );
284  TestStatus( &status, CODES( 0 ), 1 );
285 
286  LALCDestroyVector( &status, &X.data );
287  TestStatus( &status, CODES( 0 ), 1 );
288  LALSDestroyVector( &status, &x.data );
289  TestStatus( &status, CODES( 0 ), 1 );
290 
292  return 0;
293 }
294 
295 
296 /*
297  * TestStatus()
298  *
299  * Routine to check that the status code status->statusCode agrees with one of
300  * the codes specified in the space-delimited string ignored; if not,
301  * exit to the system with code exitcode.
302  *
303  */
304 static void
305 TestStatus( LALStatus *status, const char *ignored, int exitcode )
306 {
307  char str[64];
308  char *tok;
309 
310  if ( verbose )
311  {
312  REPORTSTATUS( status );
313  }
314 
315  if ( strncpy( str, ignored, sizeof( str ) ) )
316  {
317  if ( (tok = strtok( str, " " ) ) )
318  {
319  do
320  {
321  if ( status->statusCode == atoi( tok ) )
322  {
323  return;
324  }
325  }
326  while ( ( tok = strtok( NULL, " " ) ) );
327  }
328  else
329  {
330  if ( status->statusCode == atoi( str ) )
331  {
332  return;
333  }
334  }
335  }
336 
337  fprintf( stderr, "\nExiting to system with code %d\n", exitcode );
338  exit( exitcode );
339 }
340 
341 /*
342  *
343  * Usage()
344  *
345  * Prints a usage message for program program and exits with code exitcode.
346  *
347  */
348 static void
349 Usage( const char *program, int exitcode )
350 {
351  fprintf( stderr, "Usage: %s [options]\n", program );
352  fprintf( stderr, "Options:\n" );
353  fprintf( stderr, " -h print this message\n" );
354  fprintf( stderr, " -q quiet: run silently\n" );
355  fprintf( stderr, " -v verbose: print extra information\n" );
356  fprintf( stderr, " -d level set lalDebugLevel to level\n" );
357  exit( exitcode );
358 }
359 
360 
361 /*
362  * ParseOptions()
363  *
364  * Parses the argc - 1 option strings in argv[].
365  *
366  */
367 static void
368 ParseOptions( int argc, char *argv[] )
369 {
370  FILE *fp;
371 
372  while ( 1 )
373  {
374  int c = -1;
375 
376  c = LALgetopt( argc, argv, "hqvd:" );
377  if ( c == -1 )
378  {
379  break;
380  }
381 
382  switch ( c )
383  {
384  case 'd': /* set debug level */
385  break;
386 
387  case 'v': /* verbose */
388  ++verbose;
389  break;
390 
391  case 'q': /* quiet: run silently (ignore error messages) */
392  fp = freopen( "/dev/null", "w", stderr );
393  if (fp == NULL)
394  {
395  fprintf(stderr, "Error: Unable to open /dev/null\n");
396  exit(1);
397  }
398  fp = freopen( "/dev/null", "w", stdout );
399  if (fp == NULL)
400  {
401  fprintf(stderr, "Error: Unable to open /dev/null\n");
402  exit(1);
403  }
404  break;
405 
406  case 'h':
407  Usage( argv[0], 0 );
408  break;
409 
410  default:
411  Usage( argv[0], 1 );
412  }
413 
414  }
415 
416  if ( LALoptind < argc )
417  {
418  Usage( argv[0], 1 );
419  }
420 
421  return;
422 }
423 
424 /** \endcond */
const char * program
void REPORTSTATUS(LALStatus *status)
Definition: LALError.c:322
void LALCheckMemoryLeaks(void)
Definition: LALMalloc.c:784
int LALgetopt(int argc, char *const *argv, const char *optstring)
Definition: LALgetopt.c:172
int LALoptind
Definition: LALgetopt.c:79
#define fprintf
static double Y(int length, int i)
Maps the length of a window and the offset within the window to the "y" co-ordinate of the LAL docume...
Definition: Window.c:109
static void Usage(const char *program, int exitcode)
Definition: XLALChisqTest.c:70
static void ParseOptions(int argc, char *argv[])
Definition: XLALChisqTest.c:88
int main(int argc, char *argv[])
Definition: cache.c:25
COMPLEX8FFTPlan * XLALCreateReverseCOMPLEX8FFTPlan(UINT4 size, int measurelvl)
Returns a new COMPLEX8FFTPlan for a reverse transform.
COMPLEX8FFTPlan * XLALCreateForwardCOMPLEX8FFTPlan(UINT4 size, int measurelvl)
Returns a new COMPLEX8FFTPlan for a forward transform.
#define ComplexFFTPlan
Definition: ComplexFFT.h:83
void XLALDestroyCOMPLEX8FFTPlan(COMPLEX8FFTPlan *plan)
Destroys a COMPLEX8FFTPlan.
#define LAL_TWOPI
2*pi is circumference of a circle divided by its radius
Definition: LALConstants.h:180
#define XLAL_NUM_ELEM(x)
MACRO which gives the number of elements in a fixed-size array.
double REAL8
Double precision real floating-point number (8 bytes).
uint32_t UINT4
Four-byte unsigned integer.
float REAL4
Single precision real floating-point number (4 bytes).
void LALCPrintFrequencySeries(COMPLEX8FrequencySeries *series, const CHAR *filename)
void LALCPrintTimeSeries(COMPLEX8TimeSeries *series, const CHAR *filename)
void LALSPrintTimeSeries(REAL4TimeSeries *series, const CHAR *filename)
static const REAL4 eps
Definition: Random.c:84
RandomParams * XLALCreateRandomParams(INT4 seed)
Definition: Random.c:102
void XLALDestroyRandomParams(RandomParams *params)
Definition: Random.c:140
int XLALNormalDeviates(REAL4Vector *deviates, RandomParams *params)
Definition: Random.c:171
REAL4FFTPlan * XLALCreateReverseREAL4FFTPlan(UINT4 size, int measurelvl)
Returns a new REAL4FFTPlan for a reverse transform.
Definition: CudaRealFFT.c:130
#define RealFFTPlan
Definition: RealFFT.h:195
REAL4FFTPlan * XLALCreateForwardREAL4FFTPlan(UINT4 size, int measurelvl)
Returns a new REAL4FFTPlan for a forward transform.
Definition: CudaRealFFT.c:120
void XLALDestroyREAL4FFTPlan(REAL4FFTPlan *plan)
Destroys a REAL4FFTPlan.
Definition: CudaRealFFT.c:140
int XLALCOMPLEX8FreqTimeFFT(COMPLEX8TimeSeries *time, const COMPLEX8FrequencySeries *freq, const COMPLEX8FFTPlan *plan)
Definition: TimeFreqFFT.c:261
int XLALREAL4AverageSpectrumWelch(REAL4FrequencySeries *spectrum, const REAL4TimeSeries *tseries, UINT4 seglen, UINT4 stride, const REAL4Window *window, const REAL4FFTPlan *plan)
Use Welch's method to compute the average power spectrum of a time series.
int XLALREAL4FreqTimeFFT(REAL4TimeSeries *time, const COMPLEX8FrequencySeries *freq, const REAL4FFTPlan *plan)
Definition: TimeFreqFFT.c:74
int XLALCOMPLEX8TimeFreqFFT(COMPLEX8FrequencySeries *freq, const COMPLEX8TimeSeries *time, const COMPLEX8FFTPlan *plan)
Definition: TimeFreqFFT.c:206
int XLALREAL4TimeFreqFFT(COMPLEX8FrequencySeries *freq, const REAL4TimeSeries *time, const REAL4FFTPlan *plan)
Definition: TimeFreqFFT.c:38
const LALUnit lalMeterUnit
meter [m]
Definition: UnitDefs.c:160
const LALUnit lalVoltUnit
Volt [V].
Definition: UnitDefs.c:181
void LALCCreateVector(LALStatus *, COMPLEX8Vector **, UINT4)
void LALDestroyVector(LALStatus *, REAL4Vector **)
void LALCDestroyVector(LALStatus *, COMPLEX8Vector **)
void LALSDestroyVector(LALStatus *, REAL4Vector **)
void LALCreateVector(LALStatus *, REAL4Vector **, UINT4)
void LALSCreateVector(LALStatus *, REAL4Vector **, UINT4)
REAL4Window * XLALCreateHannREAL4Window(UINT4 length)
Definition: Window.c:691
void XLALDestroyREAL4Window(REAL4Window *window)
Definition: Window.c:757
See DATATYPE-FrequencySeries types for documentation.
Definition: LALDatatypes.h:899
CHAR name[LALNameLength]
Definition: LALDatatypes.h:900
COMPLEX8Sequence * data
Definition: LALDatatypes.h:905
Time series of COMPLEX8 data, see DATATYPE-TimeSeries types for more details.
Definition: LALDatatypes.h:590
CHAR name[LALNameLength]
The name of the time series.
Definition: LALDatatypes.h:591
LALUnit sampleUnits
The physical units of the quantity being sampled.
Definition: LALDatatypes.h:595
REAL8 f0
The heterodyning frequency, in Hertz (zero if not heterodyned).
Definition: LALDatatypes.h:594
REAL8 deltaT
The time step between samples of the time series in seconds.
Definition: LALDatatypes.h:593
COMPLEX8Sequence * data
The sequence of sampled data.
Definition: LALDatatypes.h:596
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:167
COMPLEX8 * data
Pointer to the data array.
Definition: LALDatatypes.h:168
LAL status structure, see The LALStatus structure for more details.
Definition: LALDatatypes.h:947
See DATATYPE-FrequencySeries types for documentation.
Definition: LALDatatypes.h:879
Time series of REAL4 data, see DATATYPE-TimeSeries types for more details.
Definition: LALDatatypes.h:570
Vector of type REAL4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:145
REAL4 * data
Pointer to the data array.
Definition: LALDatatypes.h:150
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:149
Structure for storing REAL4 window function data, providing storage for a sequence of samples as well...
Definition: Window.h:243
This structure contains the parameters necessary for generating the current sequence of random number...
Definition: Random.h:86
int verbose
Definition: tconvert.c:103
FILE * fp
Definition: tconvert.c:105