0
# FFT Operations
1
2
GPU-accelerated Fast Fourier Transform operations for signal processing and frequency domain analysis using the cuFFT library. Provides comprehensive support for 1D, 2D, and N-dimensional transforms.
3
4
## Capabilities
5
6
### One-Dimensional FFT
7
8
Basic 1D FFT operations for signal processing.
9
10
```python { .api }
11
def fft.fft(a, n=None, axis=-1, norm=None):
12
"""
13
One-dimensional discrete Fourier Transform.
14
15
Parameters:
16
- a: array-like, input array
17
- n: int, length of transformed axis
18
- axis: int, axis over which to compute FFT
19
- norm: str, normalization mode (None, 'ortho', 'backward', 'forward')
20
21
Returns:
22
cupy.ndarray, complex-valued FFT result
23
"""
24
25
def fft.ifft(a, n=None, axis=-1, norm=None):
26
"""
27
One-dimensional inverse discrete Fourier Transform.
28
29
Parameters:
30
- a: array-like, input array
31
- n: int, length of transformed axis
32
- axis: int, axis over which to compute IFFT
33
- norm: str, normalization mode
34
35
Returns:
36
cupy.ndarray, complex-valued IFFT result
37
"""
38
39
def fft.rfft(a, n=None, axis=-1, norm=None):
40
"""
41
Real-input one-dimensional discrete Fourier Transform.
42
43
Parameters:
44
- a: array-like, real-valued input array
45
- n: int, length of transformed axis
46
- axis: int, axis over which to compute FFT
47
- norm: str, normalization mode
48
49
Returns:
50
cupy.ndarray, complex-valued FFT result (half spectrum)
51
"""
52
53
def fft.irfft(a, n=None, axis=-1, norm=None):
54
"""
55
Inverse of rfft.
56
57
Parameters:
58
- a: array-like, complex-valued input array
59
- n: int, length of output along transformed axis
60
- axis: int, axis over which to compute IFFT
61
- norm: str, normalization mode
62
63
Returns:
64
cupy.ndarray, real-valued IFFT result
65
"""
66
67
def fft.hfft(a, n=None, axis=-1, norm=None):
68
"""
69
FFT of Hermitian (conjugate-symmetric) input.
70
71
Parameters:
72
- a: array-like, Hermitian input array
73
- n: int, length of output along transformed axis
74
- axis: int, axis over which to compute FFT
75
- norm: str, normalization mode
76
77
Returns:
78
cupy.ndarray, real-valued FFT result
79
"""
80
81
def fft.ihfft(a, n=None, axis=-1, norm=None):
82
"""
83
Inverse of hfft.
84
85
Parameters:
86
- a: array-like, real-valued input array
87
- n: int, length of output along transformed axis
88
- axis: int, axis over which to compute IFFT
89
- norm: str, normalization mode
90
91
Returns:
92
cupy.ndarray, complex-valued Hermitian result
93
"""
94
```
95
96
### Two-Dimensional FFT
97
98
2D FFT operations for image processing and 2D signal analysis.
99
100
```python { .api }
101
def fft.fft2(a, s=None, axes=(-2, -1), norm=None):
102
"""
103
Two-dimensional discrete Fourier Transform.
104
105
Parameters:
106
- a: array-like, input array
107
- s: tuple of ints, shape along transformed axes
108
- axes: tuple of ints, axes over which to compute FFT
109
- norm: str, normalization mode
110
111
Returns:
112
cupy.ndarray, complex-valued 2D FFT result
113
"""
114
115
def fft.ifft2(a, s=None, axes=(-2, -1), norm=None):
116
"""
117
Two-dimensional inverse discrete Fourier Transform.
118
119
Parameters:
120
- a: array-like, input array
121
- s: tuple of ints, shape along transformed axes
122
- axes: tuple of ints, axes over which to compute IFFT
123
- norm: str, normalization mode
124
125
Returns:
126
cupy.ndarray, complex-valued 2D IFFT result
127
"""
128
129
def fft.rfft2(a, s=None, axes=(-2, -1), norm=None):
130
"""
131
Real-input two-dimensional discrete Fourier Transform.
132
133
Parameters:
134
- a: array-like, real-valued input array
135
- s: tuple of ints, shape along transformed axes
136
- axes: tuple of ints, axes over which to compute FFT
137
- norm: str, normalization mode
138
139
Returns:
140
cupy.ndarray, complex-valued 2D FFT result
141
"""
142
143
def fft.irfft2(a, s=None, axes=(-2, -1), norm=None):
144
"""
145
Inverse of rfft2.
146
147
Parameters:
148
- a: array-like, complex-valued input array
149
- s: tuple of ints, shape along transformed axes
150
- axes: tuple of ints, axes over which to compute IFFT
151
- norm: str, normalization mode
152
153
Returns:
154
cupy.ndarray, real-valued 2D IFFT result
155
"""
156
```
157
158
### N-Dimensional FFT
159
160
N-dimensional FFT operations for multi-dimensional signal processing.
161
162
```python { .api }
163
def fft.fftn(a, s=None, axes=None, norm=None):
164
"""
165
N-dimensional discrete Fourier Transform.
166
167
Parameters:
168
- a: array-like, input array
169
- s: tuple of ints, shape along transformed axes
170
- axes: tuple of ints, axes over which to compute FFT
171
- norm: str, normalization mode
172
173
Returns:
174
cupy.ndarray, complex-valued N-D FFT result
175
"""
176
177
def fft.ifftn(a, s=None, axes=None, norm=None):
178
"""
179
N-dimensional inverse discrete Fourier Transform.
180
181
Parameters:
182
- a: array-like, input array
183
- s: tuple of ints, shape along transformed axes
184
- axes: tuple of ints, axes over which to compute IFFT
185
- norm: str, normalization mode
186
187
Returns:
188
cupy.ndarray, complex-valued N-D IFFT result
189
"""
190
191
def fft.rfftn(a, s=None, axes=None, norm=None):
192
"""
193
Real-input N-dimensional discrete Fourier Transform.
194
195
Parameters:
196
- a: array-like, real-valued input array
197
- s: tuple of ints, shape along transformed axes
198
- axes: tuple of ints, axes over which to compute FFT
199
- norm: str, normalization mode
200
201
Returns:
202
cupy.ndarray, complex-valued N-D FFT result
203
"""
204
205
def fft.irfftn(a, s=None, axes=None, norm=None):
206
"""
207
Inverse of rfftn.
208
209
Parameters:
210
- a: array-like, complex-valued input array
211
- s: tuple of ints, shape along transformed axes
212
- axes: tuple of ints, axes over which to compute IFFT
213
- norm: str, normalization mode
214
215
Returns:
216
cupy.ndarray, real-valued N-D IFFT result
217
"""
218
```
219
220
### Helper Functions
221
222
Utilities for frequency domain analysis and FFT operations.
223
224
```python { .api }
225
def fft.fftfreq(n, d=1.0):
226
"""
227
Return discrete Fourier Transform sample frequencies.
228
229
Parameters:
230
- n: int, window length
231
- d: scalar, sample spacing
232
233
Returns:
234
cupy.ndarray, array of sample frequencies
235
"""
236
237
def fft.rfftfreq(n, d=1.0):
238
"""
239
Return sample frequencies for rfft.
240
241
Parameters:
242
- n: int, window length
243
- d: scalar, sample spacing
244
245
Returns:
246
cupy.ndarray, array of sample frequencies for real FFT
247
"""
248
249
def fft.fftshift(x, axes=None):
250
"""
251
Shift zero-frequency component to center of spectrum.
252
253
Parameters:
254
- x: array-like, input array
255
- axes: int or tuple of ints, axes over which to shift
256
257
Returns:
258
cupy.ndarray, shifted array
259
"""
260
261
def fft.ifftshift(x, axes=None):
262
"""
263
Inverse of fftshift.
264
265
Parameters:
266
- x: array-like, input array
267
- axes: int or tuple of ints, axes over which to shift
268
269
Returns:
270
cupy.ndarray, shifted array
271
"""
272
```
273
274
### FFT Configuration
275
276
Configuration options for FFT operations.
277
278
```python { .api }
279
import cupy.fft.config
280
281
# FFT planning and caching configuration
282
fft.config.enable_nd_planning = True # Enable N-D FFT planning
283
fft.config.use_multi_gpus = False # Multi-GPU FFT support
284
fft.config.set_cufft_gpus(gpus) # Set GPUs for cuFFT operations
285
```
286
287
## Usage Examples
288
289
### Basic 1D FFT Operations
290
291
```python
292
import cupy as cp
293
import numpy as np
294
295
# Create a test signal (sum of sinusoids)
296
t = cp.linspace(0, 1, 1000, endpoint=False)
297
freq1, freq2 = 50, 120 # Hz
298
signal = cp.sin(2 * cp.pi * freq1 * t) + 0.5 * cp.sin(2 * cp.pi * freq2 * t)
299
300
# Add some noise
301
signal += 0.2 * cp.random.normal(size=t.shape)
302
303
# Compute FFT
304
fft_result = cp.fft.fft(signal)
305
frequencies = cp.fft.fftfreq(len(signal), d=1/1000) # Sample rate = 1000 Hz
306
307
# Get magnitude spectrum
308
magnitude = cp.abs(fft_result)
309
phase = cp.angle(fft_result)
310
311
# Find dominant frequencies
312
dominant_freqs = frequencies[cp.argpartition(magnitude, -10)[-10:]]
313
print("Dominant frequencies:", cp.asnumpy(dominant_freqs[dominant_freqs >= 0]))
314
```
315
316
### 2D FFT for Image Processing
317
318
```python
319
import cupy as cp
320
321
# Create a 2D test pattern
322
x = cp.linspace(-5, 5, 256)
323
y = cp.linspace(-5, 5, 256)
324
X, Y = cp.meshgrid(x, y)
325
326
# Create image with some periodic pattern
327
image = cp.exp(-(X**2 + Y**2)/2) * cp.cos(2*cp.pi*X) * cp.sin(2*cp.pi*Y)
328
329
# Add noise
330
image += 0.1 * cp.random.normal(size=image.shape)
331
332
# Compute 2D FFT
333
fft_image = cp.fft.fft2(image)
334
fft_shifted = cp.fft.fftshift(fft_image)
335
336
# Compute power spectrum
337
power_spectrum = cp.abs(fft_shifted)**2
338
339
# Apply low-pass filter in frequency domain
340
center = cp.array(image.shape) // 2
341
Y_freq, X_freq = cp.ogrid[:image.shape[0], :image.shape[1]]
342
distance = cp.sqrt((X_freq - center[1])**2 + (Y_freq - center[0])**2)
343
344
# Create circular low-pass filter
345
cutoff_freq = 30
346
filter_mask = distance <= cutoff_freq
347
filtered_fft = fft_shifted * filter_mask
348
349
# Inverse FFT to get filtered image
350
filtered_image = cp.fft.ifft2(cp.fft.ifftshift(filtered_fft))
351
filtered_image = cp.real(filtered_image)
352
```
353
354
### Real-valued FFT Operations
355
356
```python
357
import cupy as cp
358
359
# For real-valued signals, use rfft for efficiency
360
real_signal = cp.cos(2 * cp.pi * 10 * cp.linspace(0, 1, 1000))
361
362
# Real FFT (more memory efficient for real inputs)
363
rfft_result = cp.fft.rfft(real_signal)
364
rfreq = cp.fft.rfftfreq(len(real_signal))
365
366
# The result contains only positive frequencies
367
print(f"Original signal length: {len(real_signal)}")
368
print(f"RFFT result length: {len(rfft_result)}")
369
370
# Reconstruct original signal
371
reconstructed = cp.fft.irfft(rfft_result)
372
print(f"Reconstruction error: {cp.mean(cp.abs(real_signal - reconstructed)):.2e}")
373
```
374
375
### Advanced FFT Applications
376
377
```python
378
import cupy as cp
379
380
# Cross-correlation using FFT convolution
381
def cross_correlate_fft(a, b):
382
"""Compute cross-correlation using FFT."""
383
# Pad to avoid circular correlation
384
n = len(a) + len(b) - 1
385
386
# FFT of both signals
387
fft_a = cp.fft.fft(a, n)
388
fft_b = cp.fft.fft(b, n)
389
390
# Cross-correlation in frequency domain
391
cross_corr_fft = fft_a * cp.conj(fft_b)
392
393
# Inverse FFT to get cross-correlation
394
cross_corr = cp.fft.ifft(cross_corr_fft)
395
return cp.real(cross_corr)
396
397
# Example signals
398
signal1 = cp.random.randn(1000)
399
signal2 = cp.roll(signal1, 100) + 0.1 * cp.random.randn(1000)
400
401
# Compute cross-correlation
402
correlation = cross_correlate_fft(signal1, signal2)
403
delay = cp.argmax(correlation) - len(signal1) + 1
404
print(f"Detected delay: {delay} samples")
405
406
# Spectral differentiation using FFT
407
def spectral_derivative(f, dx=1.0):
408
"""Compute derivative using spectral method."""
409
n = len(f)
410
k = cp.fft.fftfreq(n, dx) * 2j * cp.pi
411
412
fft_f = cp.fft.fft(f)
413
fft_df = k * fft_f
414
df = cp.fft.ifft(fft_df)
415
416
return cp.real(df)
417
418
# Test with a known function
419
x = cp.linspace(0, 2*cp.pi, 100, endpoint=False)
420
f = cp.sin(x)
421
df_analytical = cp.cos(x)
422
df_spectral = spectral_derivative(f, dx=x[1]-x[0])
423
424
error = cp.mean(cp.abs(df_analytical - df_spectral))
425
print(f"Spectral derivative error: {error:.2e}")
426
```
427
428
### Performance Optimization
429
430
```python
431
import cupy as cp
432
import time
433
434
# Batch processing multiple signals
435
n_signals = 100
436
signal_length = 4096
437
signals = cp.random.randn(n_signals, signal_length)
438
439
# Method 1: Process each signal individually
440
start = time.time()
441
individual_ffts = []
442
for i in range(n_signals):
443
individual_ffts.append(cp.fft.fft(signals[i]))
444
individual_time = time.time() - start
445
446
# Method 2: Batch processing along axis
447
start = time.time()
448
batch_ffts = cp.fft.fft(signals, axis=1)
449
batch_time = time.time() - start
450
451
print(f"Individual processing: {individual_time:.4f} seconds")
452
print(f"Batch processing: {batch_time:.4f} seconds")
453
print(f"Speedup: {individual_time/batch_time:.2f}x")
454
455
# Use appropriate data types
456
signal_float32 = cp.random.randn(10000).astype(cp.complex64)
457
signal_float64 = signal_float32.astype(cp.complex128)
458
459
# float32 FFT (faster, less precision)
460
start = time.time()
461
fft32 = cp.fft.fft(signal_float32)
462
time32 = time.time() - start
463
464
# float64 FFT (slower, higher precision)
465
start = time.time()
466
fft64 = cp.fft.fft(signal_float64)
467
time64 = time.time() - start
468
469
print(f"Complex64 FFT: {time32:.4f} seconds")
470
print(f"Complex128 FFT: {time64:.4f} seconds")
471
```