0
# FFT Operations
1
2
Fast Fourier Transform operations through cuFFT integration, providing GPU-accelerated 1D, 2D, and N-dimensional transforms for both real and complex data. These functions enable high-performance frequency domain analysis and signal processing on GPU.
3
4
## Capabilities
5
6
### One-Dimensional FFT
7
8
Standard FFT operations for 1D signals.
9
10
```python { .api }
11
def fft(a, n=None, axis=-1, norm=None):
12
"""Compute 1-D discrete Fourier Transform.
13
14
Parameters:
15
- a: array-like, input array
16
- n: int, length of transformed axis (zero-padded or truncated)
17
- axis: int, axis over which to compute FFT
18
- norm: str, normalization mode ('backward', 'ortho', 'forward')
19
20
Returns:
21
cupy.ndarray: complex-valued FFT result
22
"""
23
24
def ifft(a, n=None, axis=-1, norm=None):
25
"""Compute 1-D inverse discrete Fourier Transform.
26
27
Parameters:
28
- a: array-like, input array
29
- n: int, length of transformed axis
30
- axis: int, axis over which to compute inverse FFT
31
- norm: str, normalization mode
32
33
Returns:
34
cupy.ndarray: complex-valued inverse FFT result
35
"""
36
```
37
38
### Multi-Dimensional FFT
39
40
FFT operations for 2D and N-dimensional arrays.
41
42
```python { .api }
43
def fft2(a, s=None, axes=(-2, -1), norm=None):
44
"""Compute 2-D discrete Fourier Transform.
45
46
Parameters:
47
- a: array-like, input array
48
- s: sequence of ints, shape of result along transformed axes
49
- axes: sequence of ints, axes over which to compute FFT
50
- norm: str, normalization mode
51
52
Returns:
53
cupy.ndarray: complex-valued 2D FFT result
54
"""
55
56
def ifft2(a, s=None, axes=(-2, -1), norm=None):
57
"""Compute 2-D inverse discrete Fourier Transform."""
58
59
def fftn(a, s=None, axes=None, norm=None):
60
"""Compute N-D discrete Fourier Transform.
61
62
Parameters:
63
- a: array-like, input array
64
- s: sequence of ints, shape of result
65
- axes: sequence of ints, axes over which to compute FFT
66
- norm: str, normalization mode
67
68
Returns:
69
cupy.ndarray: N-dimensional FFT result
70
"""
71
72
def ifftn(a, s=None, axes=None, norm=None):
73
"""Compute N-D inverse discrete Fourier Transform."""
74
```
75
76
### Real FFT
77
78
Optimized FFT functions for real-valued input data.
79
80
```python { .api }
81
def rfft(a, n=None, axis=-1, norm=None):
82
"""Compute 1-D FFT of real input.
83
84
For real input, the negative frequency terms are redundant,
85
so only positive frequencies are returned.
86
87
Parameters:
88
- a: array-like, real-valued input array
89
- n: int, length of transformed axis
90
- axis: int, axis over which to compute FFT
91
- norm: str, normalization mode
92
93
Returns:
94
cupy.ndarray: complex result with shape[axis] = n//2 + 1
95
"""
96
97
def irfft(a, n=None, axis=-1, norm=None):
98
"""Compute inverse of rfft.
99
100
Parameters:
101
- a: array-like, complex input from rfft
102
- n: int, length of real output axis
103
- axis: int, axis over which to compute inverse FFT
104
- norm: str, normalization mode
105
106
Returns:
107
cupy.ndarray: real-valued result
108
"""
109
110
def rfft2(a, s=None, axes=(-2, -1), norm=None):
111
"""Compute 2-D FFT of real input."""
112
113
def irfft2(a, s=None, axes=(-2, -1), norm=None):
114
"""Compute 2-D inverse FFT to real output."""
115
116
def rfftn(a, s=None, axes=None, norm=None):
117
"""Compute N-D FFT of real input."""
118
119
def irfftn(a, s=None, axes=None, norm=None):
120
"""Compute N-D inverse FFT to real output."""
121
```
122
123
### Hermitian FFT
124
125
FFT functions for Hermitian (conjugate symmetric) input.
126
127
```python { .api }
128
def hfft(a, n=None, axis=-1, norm=None):
129
"""Compute FFT of signal with Hermitian symmetry.
130
131
Takes complex input with Hermitian symmetry and returns real output.
132
133
Parameters:
134
- a: array-like, Hermitian input array
135
- n: int, length of transformed axis
136
- axis: int, axis over which to compute FFT
137
- norm: str, normalization mode
138
139
Returns:
140
cupy.ndarray: real-valued result
141
"""
142
143
def ihfft(a, n=None, axis=-1, norm=None):
144
"""Compute inverse of hfft.
145
146
Takes real input and returns complex output with Hermitian symmetry.
147
"""
148
```
149
150
### Frequency Arrays
151
152
Helper functions for frequency bin calculations.
153
154
```python { .api }
155
def fftfreq(n, d=1.0):
156
"""Return discrete Fourier Transform sample frequencies.
157
158
Parameters:
159
- n: int, window length
160
- d: scalar, sample spacing (time between samples)
161
162
Returns:
163
cupy.ndarray: frequency values for each bin
164
"""
165
166
def rfftfreq(n, d=1.0):
167
"""Return sample frequencies for rfft.
168
169
Parameters:
170
- n: int, window length
171
- d: scalar, sample spacing
172
173
Returns:
174
cupy.ndarray: positive frequency values
175
"""
176
```
177
178
### FFT Shifting
179
180
Functions to rearrange FFT output for centered frequency display.
181
182
```python { .api }
183
def fftshift(x, axes=None):
184
"""Shift zero-frequency component to center of spectrum.
185
186
Parameters:
187
- x: array-like, input array
188
- axes: int or shape tuple, axes over which to shift
189
190
Returns:
191
cupy.ndarray: shifted array
192
"""
193
194
def ifftshift(x, axes=None):
195
"""Inverse of fftshift.
196
197
Parameters:
198
- x: array-like, input array
199
- axes: int or shape tuple, axes over which to shift
200
201
Returns:
202
cupy.ndarray: shifted array
203
"""
204
```
205
206
### FFT Configuration
207
208
Configuration module for FFT operations.
209
210
```python { .api }
211
# From cupy.fft.config module
212
class config:
213
"""FFT configuration utilities for plan caching and optimization."""
214
215
@staticmethod
216
def get_plan_cache():
217
"""Get current FFT plan cache."""
218
219
@staticmethod
220
def set_cufft_gpus(gpus):
221
"""Set GPUs to use for multi-GPU FFT."""
222
223
@staticmethod
224
def set_cufft_callbacks(callbacks):
225
"""Set cuFFT callbacks for custom processing."""
226
```
227
228
## Usage Examples
229
230
### Basic 1D FFT
231
232
```python
233
import cupy as cp
234
import numpy as np
235
236
# Create sample signal
237
n = 1024
238
t = cp.linspace(0, 1, n)
239
signal = cp.sin(2 * cp.pi * 50 * t) + 0.5 * cp.sin(2 * cp.pi * 120 * t)
240
241
# Compute FFT
242
fft_result = cp.fft.fft(signal)
243
frequencies = cp.fft.fftfreq(n, 1/n)
244
245
# Get magnitude spectrum
246
magnitude = cp.abs(fft_result)
247
print(f"Peak frequencies at bins: {cp.argmax(magnitude[:n//2])}")
248
```
249
250
### 2D FFT for Image Processing
251
252
```python
253
import cupy as cp
254
255
# Create 2D image (or load real image data)
256
image = cp.random.random((512, 512))
257
258
# Compute 2D FFT
259
fft_image = cp.fft.fft2(image)
260
261
# Shift zero frequency to center for visualization
262
fft_shifted = cp.fft.fftshift(fft_image)
263
264
# Apply frequency domain filter (low-pass filter)
265
h, w = fft_shifted.shape
266
center_h, center_w = h // 2, w // 2
267
mask = cp.zeros((h, w))
268
mask[center_h-50:center_h+50, center_w-50:center_w+50] = 1
269
270
# Apply filter and inverse transform
271
filtered_fft = fft_shifted * mask
272
filtered_fft_shifted = cp.fft.ifftshift(filtered_fft)
273
filtered_image = cp.fft.ifft2(filtered_fft_shifted)
274
275
# Take real part (remove small imaginary components from numerical errors)
276
filtered_image = cp.real(filtered_image)
277
```
278
279
### Real FFT for Efficiency
280
281
```python
282
import cupy as cp
283
284
# Real-valued signal
285
real_signal = cp.random.random(10000)
286
287
# Use rfft for real input (more efficient)
288
rfft_result = cp.fft.rfft(real_signal)
289
print(f"Original length: {len(real_signal)}")
290
print(f"RFFT result length: {len(rfft_result)}") # n//2 + 1
291
292
# Compute power spectral density
293
psd = cp.abs(rfft_result) ** 2
294
295
# Inverse transform back to real signal
296
reconstructed = cp.fft.irfft(rfft_result, n=len(real_signal))
297
print(f"Reconstruction error: {cp.mean(cp.abs(real_signal - reconstructed))}")
298
```
299
300
### Batch FFT Processing
301
302
```python
303
import cupy as cp
304
305
# Process multiple signals simultaneously
306
batch_size = 100
307
signal_length = 1024
308
signals = cp.random.random((batch_size, signal_length))
309
310
# FFT along last axis (each row is a signal)
311
batch_fft = cp.fft.fft(signals, axis=1)
312
313
# Process along first axis (each column is a signal)
314
column_fft = cp.fft.fft(signals, axis=0)
315
316
# 2D FFT treating each signal as 2D
317
signals_2d = signals.reshape(10, 10, signal_length)
318
fft_2d = cp.fft.fft2(signals_2d, axes=(0, 1))
319
```
320
321
### Advanced FFT Applications
322
323
```python
324
import cupy as cp
325
326
# Convolution using FFT (faster for large kernels)
327
def fft_convolve(signal, kernel):
328
"""Convolution using FFT for efficiency."""
329
n = len(signal) + len(kernel) - 1
330
331
# Pad both to same length
332
signal_padded = cp.pad(signal, (0, n - len(signal)))
333
kernel_padded = cp.pad(kernel, (0, n - len(kernel)))
334
335
# FFT, multiply, inverse FFT
336
signal_fft = cp.fft.fft(signal_padded)
337
kernel_fft = cp.fft.fft(kernel_padded)
338
result_fft = signal_fft * kernel_fft
339
result = cp.fft.ifft(result_fft)
340
341
return cp.real(result)
342
343
# Example usage
344
signal = cp.random.random(10000)
345
gaussian_kernel = cp.exp(-cp.linspace(-3, 3, 101)**2)
346
convolved = fft_convolve(signal, gaussian_kernel)
347
348
# Cross-correlation using FFT
349
def fft_xcorr(x, y):
350
"""Cross-correlation using FFT."""
351
n = len(x) + len(y) - 1
352
x_padded = cp.pad(x, (0, n - len(x)))
353
y_padded = cp.pad(y, (0, n - len(y)))
354
355
X = cp.fft.fft(x_padded)
356
Y = cp.fft.fft(y_padded)
357
xcorr = cp.fft.ifft(X * cp.conj(Y))
358
359
return cp.real(xcorr)
360
361
# Find time delay between two signals
362
signal1 = cp.random.random(1000)
363
signal2 = cp.roll(signal1, 50) + 0.1 * cp.random.random(1000) # Delayed + noise
364
xcorr = fft_xcorr(signal1, signal2)
365
delay = cp.argmax(cp.abs(xcorr)) - len(signal1) + 1
366
print(f"Detected delay: {delay} samples")
367
```
368
369
### Spectral Analysis
370
371
```python
372
import cupy as cp
373
374
def power_spectral_density(signal, fs=1.0, nperseg=256):
375
"""Compute power spectral density using Welch's method."""
376
# Simple implementation - overlap segments and average
377
n_overlap = nperseg // 2
378
segments = []
379
380
for i in range(0, len(signal) - nperseg, nperseg - n_overlap):
381
segment = signal[i:i+nperseg]
382
# Apply Hanning window
383
window = 0.5 * (1 - cp.cos(2 * cp.pi * cp.arange(nperseg) / (nperseg - 1)))
384
windowed = segment * window
385
segments.append(windowed)
386
387
if segments:
388
segments = cp.stack(segments)
389
# FFT each segment
390
fft_segments = cp.fft.rfft(segments, axis=1)
391
# Compute power and average
392
power = cp.mean(cp.abs(fft_segments) ** 2, axis=0)
393
freqs = cp.fft.rfftfreq(nperseg, 1/fs)
394
return freqs, power
395
else:
396
return None, None
397
398
# Example usage
399
fs = 1000 # Sampling frequency
400
t = cp.arange(0, 10, 1/fs)
401
signal = cp.sin(2*cp.pi*50*t) + 0.5*cp.sin(2*cp.pi*120*t) + 0.2*cp.random.random(len(t))
402
403
freqs, psd = power_spectral_density(signal, fs)
404
if psd is not None:
405
peak_freq_idx = cp.argmax(psd)
406
peak_freq = freqs[peak_freq_idx]
407
print(f"Peak frequency: {peak_freq:.1f} Hz")
408
```