Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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
72int verbose = 0;
73
74static void
75Usage( const char *program, int exitflag );
76
77static void
78ParseOptions( int argc, char *argv[] );
79
80static void
81TestStatus( LALStatus *status, const char *expectedCodes, int exitCode );
82
83int 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;
91
92 static REAL4TimeSeries y;
94
95 static COMPLEX8TimeSeries 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 */
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
282 TestStatus( &status, CODES( 0 ), 1 );
284 TestStatus( &status, CODES( 0 ), 1 );
285
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 */
304static void
305TestStatus( LALStatus *status, const char *ignored, int exitcode )
306{
307 char str[64];
308 char *tok;
309
310 if ( verbose )
311 {
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 */
348static void
349Usage( 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 */
367static void
368ParseOptions( 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)
RandomParams * XLALCreateRandomParams(INT4 seed)
Definition: Random.c:102
static const REAL4 eps
Definition: Random.c:84
void XLALDestroyRandomParams(RandomParams *params)
Definition: Random.c:140
int XLALNormalDeviates(REAL4Vector *deviates, RandomParams *params)
Definition: Random.c:171
#define RealFFTPlan
Definition: RealFFT.h:195
REAL4FFTPlan * XLALCreateReverseREAL4FFTPlan(UINT4 size, int measurelvl)
Returns a new REAL4FFTPlan for a reverse transform.
Definition: CudaRealFFT.c:130
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)
void XLALDestroyREAL4Window(REAL4Window *window)
Definition: Window.c:757
REAL4Window * XLALCreateHannREAL4Window(UINT4 length)
Definition: Window.c:691
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