5 Best Ways to Perform Discrete Fourier Transform Using SciPy in Python

Rate this post

πŸ’‘ Problem Formulation: In signal processing and data analysis, the Discrete Fourier Transform (DFT) is a pivotal technique for converting discrete signals from the time domain into the frequency domain. When working with Python, specifically utilizing the SciPy library, performing a DFT allows you to analyze frequency components of a signal. For a given input signal, such as a time-series array, the desired output is a complex array representing the magnitude and phase of each frequency component of the original signal.

Method 1: Using fft from scipy.fft

The scipy.fft.fft() function computes the one-dimensional n-point discrete Fourier Transform (DFT) with the efficient Fast Fourier Transform (FFT) algorithm. It can handle complex inputs and multi-dimensional arrays, making it suitable for various applications. It returns complex-valued frequency bins, representing the signal in the frequency domain.

Here’s an example:

from scipy.fft import fft
import numpy as np

# Sample signal
t = np.linspace(0, 1, 400, endpoint=False)
signal = np.sin(2 * np.pi * 5 * t)

# Perform the discrete Fourier transform
spectrum = fft(signal)

Output of the code snippet:

[ 2.22044605e-15+0.j, 6.66133815e-16+2.22044605e-16j, ... ]

This code first imports necessary modules, creates a sample sinusoidal signal with five oscillations per unit time, and then performs the DFT using fft(). The output is an array of complex numbers representing the amplitude and phase of the signal’s frequency components.

Method 2: Using rfft from scipy.fft for Real-valued Inputs

For real-valued inputs, scipy.fft.rfft() is more efficient since it takes advantage of the symmetry properties of the FFT. This function returns only the non-negative frequency terms, as the negative frequencies are redundant for real-valued inputs. This can significantly reduce computation time for large data sets.

Here’s an example:

from scipy.fft import rfft

# Perform the real-valued discrete Fourier transform
spectrum_real = rfft(signal)

Output of the code snippet:

[ 2.22044605e-15, -1.77635684e-15, ... ]

The code snippet demonstrates the usage of rfft() by applying a real-input-optimized Fourier transform to the previously defined signal. It outputs the positive frequency components of the signal’s DFT, which is ideal for real-valued input signals.

Method 3: Using fftfreq to Obtain Frequency Bin Centers

When interpreting the results of the FFT, it’s important to know the frequency associated with each bin. The scipy.fft.fftfreq() function returns the discrete Fourier Transform sample frequencies corresponding to the bins obtained from fft().

Here’s an example:

from scipy.fft import fftfreq

# Sample rate and length of signal
sample_rate = 400
n = len(signal)

# Frequency bin centers
freq_bins = fftfreq(n, 1/sample_rate)

Output of the code snippet:

[ 0., 1., 2., ..., -3., -2., -1.]

This snippet first sets up the sample rate and calculates the length of the signal. It then uses fftfreq() to compute the center frequencies for each bin, which is essential for analyzing the frequency content of the signal.

Method 4: Using fftpack from scipy for Legacy Code

The scipy.fftpack module was the previous module for computing FFTs before scipy.fft. It’s still available for use, particularly for maintaining legacy code. However, scipy.fft now offers better performance and a more intuitive interface.

Here’s an example:

from scipy.fftpack import fft

# Perform the discrete Fourier transform using fftpack
spectrum_fftpack = fft(signal)

Output is similar to that of scipy.fft.fft(), using fft() from scipy.fftpack.

While scipy.fftpack provides backward compatibility, this example shows it is used in a similar way to scipy.fft.fft(). The output remains consistent, offering the same frequency domain representation of the sample signal.

Bonus One-Liner Method 5: Quick FFT with numpy.fft

While not part of SciPy, numpy.fft.fft() is a convenient one-liner alternative, suitable for simple use cases requiring a quick Fourier Transform without additional SciPy features.

Here’s an example:

import numpy as np

# Perform the discrete Fourier transform using numpy
spectrum_numpy = np.fft.fft(signal)

Output of the code snippet:

[ 2.22044605e-15+0.j, 6.66133815e-16+2.22044605e-16j, ... ]

This concise example shows how to achieve a DFT using NumPy’s built-in FFT function. Despite being part of a different library, it provides similar functionality and outputs to scipy.fft.fft(), making it another viable option for performing a DFT.

Summary/Discussion

  • Method 1: Using fft from scipy.fft. Offers comprehensive FFT capabilities. Best for general use with complex or multi-dimensional data.
  • Method 2: Using rfft for Real-valued Inputs. Optimal for real-valued signals, providing computational efficiency. Not suitable for complex-valued inputs.
  • Method 3: Using fftfreq to Obtain Frequency Bin Centers. Essential for frequency domain analysis after performing FFT. Does not compute FFT by itself.
  • Method 4: Using fftpack from scipy for Legacy Code. Good for compatibility with older codebases. Less efficient than scipy.fft.
  • Bonus One-Liner Method 5: Quick FFT with numpy.fft. Quick and straightforward, but lacks some sophistication of SciPy’s FFT implementations.