1FFT(3) User Contributed Perl Documentation FFT(3)
2
3
4
6 Math::FFT - Perl module to calculate Fast Fourier Transforms
7
9 use Math::FFT;
10 my $PI = 3.1415926539;
11 my $N = 64;
12 my ($series, $other_series);
13 for (my $k=0; $k<$N; $k++) {
14 $series->[$k] = sin(4*$k*$PI/$N) + cos(6*$k*$PI/$N);
15 }
16 my $fft = new Math::FFT($series);
17 my $coeff = $fft->rdft();
18 my $spectrum = $fft->spctrm;
19 my $original_data = $fft->invrdft($coeff);
20
21 for (my $k=0; $k<$N; $k++) {
22 $other_series->[$k] = sin(16*$k*$PI/$N) + cos(8*$k*$PI/$N);
23 }
24 my $other_fft = $fft->clone($other_series);
25 my $other_coeff = $other_fft->rdft();
26 my $correlation = $fft->correl($other_fft);
27
29 This module implements some algorithms for calculating Fast Fourier
30 Transforms for one-dimensional data sets of size 2^n. The data,
31 assumed to arise from a constant sampling rate, is represented by an
32 array reference $data (as described in the methods below), which is
33 then used to create a "Math::FFT" object as
34
35 my $fft = new Math::FFT($data);
36
37 The methods available include the following.
38
39 FFT METHODS
40 "$coeff = $fft->cdft();"
41 This calculates the complex discrete Fourier transform for a data
42 set "x[j]". Here, $data is a reference to an array
43 "data[0...2*n-1]" holding the data
44
45 data[2*j] = Re(x[j]),
46 data[2*j+1] = Im(x[j]), 0<=j<n
47
48 An array reference $coeff is returned consisting of
49
50 coeff[2*k] = Re(X[k]),
51 coeff[2*k+1] = Im(X[k]), 0<=k<n
52
53 where
54
55 X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k<n
56
57 "$orig_data = $fft->invcdft([$coeff]);"
58 Calculates the inverse complex discrete Fourier transform on a data
59 set "x[j]". If $coeff is not given, it will be set equal to an
60 earlier call to "$fft->cdft()". $coeff is a reference to an array
61 "coeff[0...2*n-1]" holding the data
62
63 coeff[2*j] = Re(x[j]),
64 coeff[2*j+1] = Im(x[j]), 0<=j<n
65
66 An array reference $orig_data is returned consisting of
67
68 orig_data[2*k] = Re(X[k]),
69 orig_data[2*k+1] = Im(X[k]), 0<=k<n
70
71 where, excluding the scale,
72
73 X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k<n
74
75 A scaling "$orig_data->[$i] *= 2.0/$n" is then done so that
76 $orig_data coincides with the original $data.
77
78 "$coeff = $fft->rdft();"
79 This calculates the real discrete Fourier transform for a data set
80 "x[j]". On input, $data is a reference to an array "data[0...n-1]"
81 holding the data. An array reference $coeff is returned consisting
82 of
83
84 coeff[2*k] = R[k], 0<=k<n/2
85 coeff[2*k+1] = I[k], 0<k<n/2
86 coeff[1] = R[n/2]
87
88 where
89
90 R[k] = sum_j=0^n-1 data[j]*cos(2*pi*j*k/n), 0<=k<=n/2
91 I[k] = sum_j=0^n-1 data[j]*sin(2*pi*j*k/n), 0<k<n/2
92
93 "$orig_data = $fft->invrdft([$coeff]);"
94 Calculates the inverse real discrete Fourier transform on a data
95 set "coeff[j]". If $coeff is not given, it will be set equal to an
96 earlier call to "$fft->rdft()". $coeff is a reference to an array
97 "coeff[0...n-1]" holding the data
98
99 coeff[2*j] = R[j], 0<=j<n/2
100 coeff[2*j+1] = I[j], 0<j<n/2
101 coeff[1] = R[n/2]
102
103 An array reference $orig_data is returned where, excluding the
104 scale,
105
106 orig_data[k] = (R[0] + R[n/2]*cos(pi*k))/2 +
107 sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) +
108 sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n
109
110 A scaling "$orig_data->[$i] *= 2.0/$n" is then done so that
111 $orig_data coincides with the original $data.
112
113 "$coeff = $fft->ddct();"
114 Computes the discrete cosine tranform on a data set "data[0...n-1]"
115 contained in an array reference $data. An array reference $coeff is
116 returned consisting of
117
118 coeff[k] = C[k], 0<=k<n
119
120 where
121
122 C[k] = sum_j=0^n-1 data[j]*cos(pi*(j+1/2)*k/n), 0<=k<n
123
124 "$orig_data = $fft->invddct([$coeff]);"
125 Computes the inverse discrete cosine tranform on a data set
126 "coeff[0...n-1]" contained in an array reference $coeff. If $coeff
127 is not given, it will be set equal to an earlier call to
128 "$fft->ddct()". An array reference $orig_data is returned
129 consisting of
130
131 orig_data[k] = C[k], 0<=k<n
132
133 where, excluding the scale,
134
135 C[k] = sum_j=0^n-1 coeff[j]*cos(pi*j*(k+1/2)/n), 0<=k<n
136
137 A scaling "$orig_data->[$i] *= 2.0/$n" is then done so that
138 $orig_data coincides with the original $data.
139
140 "$coeff = $fft->ddst();"
141 Computes the discrete sine transform of a data set "data[0...n-1]"
142 contained in an array reference $data. An array reference $coeff is
143 returned consisting of
144
145 coeff[k] = S[k], 0<k<n
146 coeff[0] = S[n]
147
148 where
149
150 S[k] = sum_j=0^n-1 data[j]*sin(pi*(j+1/2)*k/n), 0<k<=n
151
152 "$orig_data = $fft->invddst($coeff);"
153 Computes the inverse discrete sine transform of a data set
154 "coeff[0...n-1]" contained in an array reference $coeff, arranged
155 as
156
157 coeff[j] = A[j], 0<j<n
158 coeff[0] = A[n]
159
160 If $coeff is not given, it will be set equal to an earlier call to
161 "$fft->ddst()". An array reference $orig_data is returned
162 consisting of
163
164 orig_data[k] = S[k], 0<=k<n
165
166 where, excluding a scale,
167
168 S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n
169
170 The scaling "$a->[$i] *= 2.0/$n" is then done so that $orig_data
171 coincides with the original $data.
172
173 "$coeff = $fft->dfct();"
174 Computes the real symmetric discrete Fourier transform of a data
175 set "data[0...n]" contained in the array reference $data. An array
176 reference $coeff is returned consisting of
177
178 coeff[k] = C[k], 0<=k<=n
179
180 where
181
182 C[k] = sum_j=0^n data[j]*cos(pi*j*k/n), 0<=k<=n
183
184 "$orig_data = $fft->invdfct($coeff);"
185 Computes the inverse real symmetric discrete Fourier transform of a
186 data set "coeff[0...n]" contained in the array reference $coeff.
187 If $coeff is not given, it will be set equal to an earlier call to
188 "$fft->dfct()". An array reference $orig_data is returned
189 consisting of
190
191 orig_data[k] = C[k], 0<=k<=n
192
193 where, excluding the scale,
194
195 C[k] = sum_j=0^n coeff[j]*cos(pi*j*k/n), 0<=k<=n
196
197 A scaling "$coeff->[0] *= 0.5", "$coeff->[$n] *= 0.5", and
198 "$orig_data->[$i] *= 2.0/$n" is then done so that $orig_data
199 coincides with the original $data.
200
201 "$coeff = $fft->dfst();"
202 Computes the real anti-symmetric discrete Fourier transform of a
203 data set "data[0...n-1]" contained in the array reference $data. An
204 array reference $coeff is returned consisting of
205
206 coeff[k] = C[k], 0<k<n
207
208 where
209
210 C[k] = sum_j=0^n data[j]*sin(pi*j*k/n), 0<k<n
211
212 ("coeff[0]" is used for a work area)
213
214 "$orig_data = $fft->invdfst($coeff);"
215 Computes the inverse real anti-symmetric discrete Fourier transform
216 of a data set "coeff[0...n-1]" contained in the array reference
217 $coeff. If $coeff is not given, it will be set equal to an earlier
218 call to "$fft->dfst()". An array reference $orig_data is returned
219 consisting of
220
221 orig_data[k] = C[k], 0<k<n
222
223 where, excluding the scale,
224
225 C[k] = sum_j=0^n coeff[j]*sin(pi*j*k/n), 0<k<n
226
227 A scaling "$orig_data->[$i] *= 2.0/$n" is then done so that
228 $orig_data coincides with the original $data.
229
230 CLONING
231 The algorithm used in the transforms makes use of arrays for a work
232 area and for a cos/sin lookup table dependent only on the size of the
233 data set. These arrays are initialized when the "Math::FFT" object is
234 created and then are populated when a transform method is first
235 invoked. After this, they persist for the lifetime of the object.
236
237 This aspect is exploited in a "cloning" method; if a "Math::FFT" object
238 is created for a data set $data1 of size "N":
239
240 $fft1 = new Math::FFT($data1);
241
242 then a new "Math::FFT" object can be created for a second data set
243 $data2 of the same size "N" by
244
245 $fft2 = $fft1->clone($data2);
246
247 The $fft2 object will copy the reuseable work area and lookup table
248 calculated from $fft1.
249
250 APPLICATIONS
251 This module includes some common applications - correlation,
252 convolution and deconvolution, and power spectrum - that arise with
253 real data sets. The conventions used here follow that of Numerical
254 Recipes in C, by Press, Teukolsky, Vetterling, and Flannery, in which
255 further details of the algorithms are given. Note in particular the
256 treatment of end effects by zero padding, which is assumed to be done
257 by the user, if required.
258
259 Correlation
260 The correlation between two functions is defined as
261
262 /
263 Corr(t) = | ds g(s+t) h(s)
264 /
265
266 This may be calculated, for two array references $data1 and $data2
267 of the same size $n, as either
268
269 $fft1 = new Math::FFT($data1);
270 $fft2 = new Math::FFT($data2);
271 $corr = $fft1->correl($fft2);
272
273 or as
274
275 $fft1 = new Math::FFT($data1);
276 $corr = $fft1->correl($data2);
277
278 The array reference $corr is returned in wrap-around order -
279 correlations at increasingly positive lags are in "$corr->[0]"
280 (zero lag) on up to "$corr->[$n/2-1]", while correlations at
281 increasingly negative lags are in "$corr->[$n-1]" on down to
282 "$corr->[$n/2]". The sign convention used is such that if $data1
283 lags $data2 (that is, is shifted to the right), then $corr will
284 show a peak at positive lags.
285
286 Convolution
287 The convolution of two functions is defined as
288
289 /
290 Convlv(t) = | ds g(s) h(t-s)
291 /
292
293 This is similar to calculating the correlation between the two
294 functions, but typically the functions here have a quite different
295 physical interpretation - one is a signal which persists
296 indefinitely in time, and the other is a response function of
297 limited duration. The convolution may be calculated, for two array
298 references $data and $respn, as
299
300 $fft = new Math::FFT($data);
301 $convlv = $fft->convlv($respn);
302
303 with the returned $convlv being an array reference. The method
304 assumes that the response function $respn has an odd number of
305 elements $m less than or equal to the number of elements $n of
306 $data. $respn is assumed to be stored in wrap-around order - the
307 first half contains the response at positive times, while the
308 second half, counting down from "$respn->[$m-1]", contains the
309 response at negative times.
310
311 Deconvolution
312 Deconvolution undoes the effects of convoluting a signal with a
313 known response function. In other words, in the relation
314
315 /
316 Convlv(t) = | ds g(s) h(t-s)
317 /
318
319 deconvolution reconstructs the original signal, given the
320 convolution and the response function. The method is implemented,
321 for two array references $data and $respn, as
322
323 $fft = new Math::FFT($data);
324 $deconvlv = $fft->deconvlv($respn);
325
326 As a result, if the convolution of a data set $data with a response
327 function $respn is calculated as
328
329 $fft1 = new Math::FFT($data);
330 $convlv = $fft1->convlv($respn);
331
332 then the deconvolution
333
334 $fft2 = new Math::FFT($convlv);
335 $deconvlv = $fft2->deconvlv($respn);
336
337 will give an array reference $deconvlv containing the same elements
338 as the original data $data.
339
340 Power Spectrum
341 If the FFT of a real function of "N" elements is calculated, the
342 "N/2+1" elements of the power spectrum are defined, in terms of the
343 (complex) Fourier coefficients "C[k]", as
344
345 P[0] = |C[0]|^2 / N^2
346 P[k] = 2 |C[k]|^2 / N^2 (k = 1, 2 ,..., N/2-1)
347 P[N/2] = |C[N/2]|^2 / N^2
348
349 Often for these purposes the data is partitioned into "K" segments,
350 each containing "2M" elements. The power spectrum for each segment
351 is calculated, and the net power spectrum is the average of all of
352 these segmented spectra.
353
354 Partitioning may be done in one of two ways: non-overlapping and
355 overlapping. Non-overlapping is useful when the data set is
356 gathered in real time, where the number of data points can be
357 varied at will. Overlapping is useful where there is a fixed number
358 of data points. In non-overlapping, the first <2M> elements
359 constitute segment 1, the next "2M" elements are segment 2, and so
360 on up to segment "K", for a total of "2KM" sampled points. In
361 overlapping, the first and second "M" elements are segment 1, the
362 second and third "M" elements are segment 2, and so on, for a total
363 of "(K+1)M" sampled points.
364
365 A problem that may arise in this procedure is leakage: the power
366 spectrum calculated for one bin contains contributions from nearby
367 bins. To lessen this effect data windowing is often used: multiply
368 the original data "d[j]" by a window function "w[j]", where j = 0,
369 1, ..., N-1. Some popular choices of such functions are
370
371 | j - N/2 |
372 w[j] = 1 - | ------- | ... Bartlett
373 | N/2 |
374
375
376 / j - N/2 \ 2
377 w[j] = 1 - | ------- | ... Welch
378 \ N/2 /
379
380
381 1 / \
382 w[j] = --- |1 - cos(2 pi j / N) | ... Hann
383 2 \ /
384
385 The "spctrm" method, used as
386
387 $fft = Math::FFT->new($data);
388 $spectrum = $fft->spctrm(%options);
389
390 returns an array reference $spectrum representing the power
391 spectrum for a data set represented by an array reference $data.
392 The options available are
393
394 "window => window_name"
395 This specifies the window function; if not given, no such
396 function is used. Accepted values (see above) are "bartlett",
397 "welch", "hann", and "\&my_window", where "my_window" is a user
398 specified subroutine which must be of the form, for example,
399
400 sub my_window {
401 my ($j, $n) = @_;
402 return 1 - abs(2*($j-$n/2)/$n);
403 }
404
405 which implements the Bartlett window.
406
407 "overlap => 1"
408 This specifies whether overlapping should be done; if true (1),
409 overlapping will be used, whereas if false (0), or not
410 specified, no overlapping is used.
411
412 "segments => n"
413 This specifies that the data will be partitioned into "n"
414 segments. If not specified, no segmentation will be done.
415
416 "number => m"
417 This specifies that "2m" data points will be used for each
418 segment, and must be a power of 2. The power spectrum returned
419 will consist of "m+1" elements.
420
421 STATISTICAL FUNCTIONS
422 For convenience, a number of common statistical functions are included
423 for analyzing real data. After creating the object as
424
425 my $fft = new Math::FFT($data);
426
427 for a data set represented by the array reference $data of size "N",
428 these methods may be called as follows.
429
430 "$mean = $fft->mean([$data]);"
431 This returns the mean
432
433 1/N * sum_j=0^N-1 data[j]
434
435 If an array reference $data is not given, the data set used in
436 creating $fft will be used.
437
438 "$stdev = $fft->stdev([$data]);"
439 This returns the standard deviation
440
441 sqrt{ 1/(N-1) * sum_j=0^N-1 (data[j] - mean)**2 }
442
443 If an array reference $data is not given, the data set used in
444 creating $fft will be used.
445
446 "$rms = $fft->rms([$data]);"
447 This returns the root mean square
448
449 sqrt{ 1/N * sum_j=0^N-1 (data[j])**2 }
450
451 If an array reference $data is not given, the data set used in
452 creating $fft will be used.
453
454 "($min, $max) = $fft->range([$data]);"
455 This returns the minimum and maximum values of the data set. If an
456 array reference $data is not given, the data set used in creating
457 $fft will be used.
458
459 "$median = $fft->median([$data]);"
460 This returns the median of a data set. The median is defined, for
461 the sorted data set, as either the middle element, if the number of
462 elements is odd, or as the interpolated value of the the two values
463 on either side of the middle, if the number of elements is even. If
464 an array reference $data is not given, the data set used in
465 creating $fft will be used.
466
468 Please report any to Randy Kobes <randy@theoryx5.uwinnipeg.ca>
469
471 Math::Pari and PDL
472
474 The algorithm used in this module to calculate the Fourier transforms
475 is based on the C routine of fft4g.c available at
476 http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html, which is copyrighted
477 1996-99 by Takuya OOURA. The file arrays.c included here to handle
478 passing arrays to and from C comes from the PGPLOT module of Karl
479 Glazebrook <kgb@aaoepp.aao.gov.au>. The perl code of Math::FFT is
480 copyright 2000,2005 by Randy Kobes <r.kobes@uwinnipeg.ca>, and is
481 distributed under the same terms as Perl itself.
482
483
484
485perl v5.12.0 2005-09-03 FFT(3)