0% found this document useful (0 votes)
13 views7 pages

FFT Implementation in Python

This document provides an overview of using Fast Fourier Transform (FFT) in Python, highlighting the capabilities of both numpy and scipy libraries for signal processing. It includes examples of generating signals, calculating FFT and inverse FFT, and visualizing results, as well as practical applications such as analyzing electricity demand data and implementing filters. The document emphasizes the efficiency of built-in FFT functions and encourages further exploration of FFT applications in science and engineering.

Uploaded by

01231001
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views7 pages

FFT Implementation in Python

This document provides an overview of using Fast Fourier Transform (FFT) in Python, highlighting the capabilities of both numpy and scipy libraries for signal processing. It includes examples of generating signals, calculating FFT and inverse FFT, and visualizing results, as well as practical applications such as analyzing electricity demand data and implementing filters. The document emphasizes the efficiency of built-in FFT functions and encourages further exploration of FFT applications in science and engineering.

Uploaded by

01231001
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

This notebook contains an excerpt from the Python Programming and Numerical Methods - A Guide

for Engineers and Scientists, the content is also available at Berkeley Python Numerical Methods.

The copyright of the book belongs to Elsevier. We also have this interactive book online for a better
learning experience. The code is released under the MIT license. If you find this content useful, please
consider supporting the work on Elsevier or Amazon!

< 24.3 Fast Fourier Transform (FFT) | Contents | 24.5 Summary and Problems >

FFT in Python
In Python, there are very mature FFT functions both in numpy and scipy. In this section, we will take a look of both
packages and see how we can easily use them in our work. Let’s first generate the signal as before.

import [Link] as plt


import numpy as np

[Link]('seaborn-poster')
%matplotlib inline

# sampling rate
sr = 2000
# sampling interval
ts = 1.0/sr
t = [Link](0,1,ts)

freq = 1.
x = 3*[Link](2*[Link]*freq*t)

freq = 4
x += [Link](2*[Link]*freq*t)

freq = 7
x += 0.5* [Link](2*[Link]*freq*t)

[Link](figsize = (8, 6))


[Link](t, x, 'r')
[Link]('Amplitude')

[Link]()

FFT in Numpy
EXAMPLE: Use fft and ifft function from numpy to calculate the FFT amplitude spectrum and inverse FFT to obtain
the original signal. Plot both results. Time the fft function using this 2000 length signal.
from [Link] import fft, ifft

X = fft(x)
N = len(X)
n = [Link](N)
T = N/sr
freq = n/T

[Link](figsize = (12, 6))


[Link](121)

[Link](freq, [Link](X), 'b', \


markerfmt=" ", basefmt="-b")
[Link]('Freq (Hz)')
[Link]('FFT Amplitude |X(freq)|')
[Link](0, 10)

[Link](122)
[Link](t, ifft(X), 'r')
[Link]('Time (s)')
[Link]('Amplitude')
plt.tight_layout()
[Link]()

/Users/qingkaikong/miniconda3/lib/python3.6/site-
packages/ipykernel_launcher.py:13: UserWarning: In Matplotlib 3.3
individual lines on a stem plot will be added as a LineCollection
instead of individual lines. This significantly improves the
performance of a stem plot. To remove this warning and switch to the
new behaviour, set the "use_line_collection" keyword argument to
True.
del [Link][0]
/Users/qingkaikong/miniconda3/lib/python3.6/site-
packages/numpy/core/[Link]: ComplexWarning: Casting complex
values to real discards the imaginary part
return array(a, dtype, copy=False, order=order)

%timeit fft(x)

36.2 µs ± 775 ns per loop (mean ± std. dev. of 7 runs, 10000 loops
each)

FFT in Scipy
EXAMPLE: Use fft and ifft function from scipy to calculate the FFT amplitude spectrum and inverse FFT to obtain
the original signal. Plot both results. Time the fft function using this 2000 length signal.
from [Link] import fft, ifft

X = fft(x)

[Link](figsize = (12, 6))


[Link](121)

[Link](freq, [Link](X), 'b', \


markerfmt=" ", basefmt="-b")
[Link]('Freq (Hz)')
[Link]('FFT Amplitude |X(freq)|')
[Link](0, 10)

[Link](122)
[Link](t, ifft(X), 'r')
[Link]('Time (s)')
[Link]('Amplitude')
plt.tight_layout()
[Link]()

/Users/qingkaikong/miniconda3/lib/python3.6/site-
packages/ipykernel_launcher.py:9: UserWarning: In Matplotlib 3.3
individual lines on a stem plot will be added as a LineCollection
instead of individual lines. This significantly improves the
performance of a stem plot. To remove this warning and switch to the
new behaviour, set the "use_line_collection" keyword argument to
True.
if __name__ == '__main__':

%timeit fft(x)

14.8 µs ± 471 ns per loop (mean ± std. dev. of 7 runs, 100000 loops
each)

Now we can see that the built-in fft functions are much faster and easy to use, especially for the scipy version.
Here is the results for comparison:

Implemented DFT: ~120 ms


Implemented FFT: ~16 ms
Numpy FFT: ~40 µs
Scipy FFT: ~12 µs

More examples
Let us see some more examples how to use FFT in real-world applications.

Electricity demand in California


First, we will explore the electricity demand from California from 2019-11-30 to 2019-12-30. You can download
data from U.S. Energy Information Administration. Here, I have already downloaded the data, therefore, we will
use it directly.

The electricity demand data from California is stored in ‘[Link]’ in 3 columns. Remember we learned
how to read CSV file using numpy. Here, we will use another package - pandas, which is a very popular package to
deal with time series data. We will not teach you this package here, as an exercise, you should learn how to use it
by yourself. Let us read in the data first.
import pandas as pd

The read_csv function will read in the CSV file. Pay attention to the parse_dates parameter, which will find the
date and time in column one. The data will be read into a pandas DataFrame, we use df to store it. Then we will
change the header in the original file to something easier to use.

df = pd.read_csv('./data/[Link]',
delimiter=',', parse_dates=[1])
[Link](columns={'Timestamp (Hour Ending)':'hour',
'Total CAL Demand (MWh)':'demand'},
inplace=True)

We can plot the data and see how the electricity demand is changing over time.

[Link](figsize = (12, 6))


[Link](df['hour'], df['demand'])
[Link]('Datetime')
[Link]('California electricity demand (MWh)')
[Link](rotation=25)
[Link]()

/Users/qingkaikong/miniconda3/lib/python3.6/site-
packages/pandas/plotting/_converter.py:129: FutureWarning: Using an
implicitly registered datetime converter for a matplotlib plotting
method. The converter was registered by pandas on import. Future
versions of pandas will require you to explicitly register
matplotlib converters.

To register the converters:


>>> from [Link] import
register_matplotlib_converters
>>> register_matplotlib_converters()
[Link](msg, FutureWarning)

From the plotted time series, it is hard to tell there are some patterns behind the data. Let us transform the data
into frequency domain and see if there is anything interesting.

X = fft(df['demand'])
N = len(X)
n = [Link](N)
# get the sampling rate
sr = 1 / (60*60)
T = N/sr
freq = n/T

# Get the one-sided specturm


n_oneside = N//2
# get the one side frequency
f_oneside = freq[:n_oneside]

[Link](figsize = (12, 6))


[Link](f_oneside, [Link](X[:n_oneside]), 'b')
[Link]('Freq (Hz)')
[Link]('FFT Amplitude |X(freq)|')
[Link]()
We see some clear peaks in the FFT amplitude figure, but it is hard to tell what are they in terms of frequency. Let
us plot the results using hours and highlight some of the hours associated with the peaks.

# convert frequency to hour


t_h = 1/f_oneside / (60 * 60)

[Link](figsize=(12,6))
[Link](t_h, [Link](X[:n_oneside])/n_oneside)
[Link]([12, 24, 84, 168])
[Link](0, 200)
[Link]('Period ($hour$)')
[Link]()

/Users/qingkaikong/miniconda3/lib/python3.6/site-
packages/ipykernel_launcher.py:2: RuntimeWarning: divide by zero
encountered in true_divide

We can now see some interesting patterns, i.e. three peaks associate with 12, 24, and 84 hours. These peaks mean
that we see some repeating signal every 12, 24 and 84 hours. This makes sense and corresponding to our human
activity pattern. The FFT can help us to understand some of the repeating signal in our physical world.

Filtering a signal using FFT


Filtering is a process in signal processing to remove some unwanted part of the signal within certain frequency
range. There are low-pass filter, which tries to remove all the signal above certain cut-off frequency, and high-pass
filter, which does the opposite. Combining low-pass and high-pass filter, we will have bandpass filter, which means
we only keep the signals within a pair of frequencies. Using FFT, we can easily do this. Let us play with the following
example to illustrate the basics of a band-pass filter. Note: we just want to show the idea of filtering using very
basic operations, in reality, the filtering process are much more sophisticated.

EXAMPLE: We can use the signal we generated at the beginning of this section (the mixed sine waves with 1, 4,
and 7 Hz), and high-pass filter this signal at 6 Hz. Plot the filtered signal and the FFT amplitude before and after
the filtering.

from [Link] import fftfreq

[Link](figsize = (8, 6))


[Link](t, x, 'r')
[Link]('Amplitude')
[Link]('Original signal')
[Link]()
# FFT the signal
sig_fft = fft(x)
# copy the FFT results
sig_fft_filtered = sig_fft.copy()

# obtain the frequencies using scipy function


freq = fftfreq(len(x), d=1./2000)

# define the cut-off frequency


cut_off = 6

# high-pass filter by assign zeros to the


# FFT amplitudes where the absolute
# frequencies smaller than the cut-off
sig_fft_filtered[[Link](freq) < cut_off] = 0

# get the filtered signal in time domain


filtered = ifft(sig_fft_filtered)

# plot the filtered signal


[Link](figsize = (12, 6))
[Link](t, filtered)
[Link]('Time (s)')
[Link]('Amplitude')
[Link]()

# plot the FFT amplitude before and after


[Link](figsize = (12, 6))
[Link](121)
[Link](freq, [Link](sig_fft), 'b', \
markerfmt=" ", basefmt="-b")
[Link]('Before filtering')
[Link](0, 10)
[Link]('Frequency (Hz)')
[Link]('FFT Amplitude')
[Link](122)
[Link](freq, [Link](sig_fft_filtered), 'b', \
markerfmt=" ", basefmt="-b")
[Link]('After filtering')
[Link](0, 10)
[Link]('Frequency (Hz)')
[Link]('FFT Amplitude')
plt.tight_layout()
[Link]()

/Users/qingkaikong/miniconda3/lib/python3.6/site-
packages/numpy/core/[Link]: ComplexWarning: Casting complex
values to real discards the imaginary part
return array(a, dtype, copy=False, order=order)

Print to PDF
/Users/qingkaikong/miniconda3/lib/python3.6/site-
packages/ipykernel_launcher.py:31: UserWarning: In Matplotlib 3.3
individual lines on a stem plot will be added as a LineCollection
instead of individual lines. This significantly improves the
performance of a stem plot. To remove this warning and switch to the
new behaviour, set the "use_line_collection" keyword argument to
True.
/Users/qingkaikong/miniconda3/lib/python3.6/site-
packages/ipykernel_launcher.py:38: UserWarning: In Matplotlib 3.3
individual lines on a stem plot will be added as a LineCollection
instead of individual lines. This significantly improves the
performance of a stem plot. To remove this warning and switch to the
new behaviour, set the "use_line_collection" keyword argument to
True.

From the above example, by assigning any absolute frequencies’ FFT amplitude to zero, and returning back to time
domain signal, we achieve a very basic high-pass filter in a few steps. You can try to implement a simple low-pass or
bandpass filter by yourself. Therefore, FFT can help us get the signal we are interested in and remove the ones that
are unwanted.

There are also many amazing applications using FFT in science and engineering and we will leave you to explore by
yourself.

< 24.3 Fast Fourier Transform (FFT) | Contents | 24.5 Summary and Problems >

© Copyright 2020.

Common questions

Powered by AI

FFT significantly improves efficiency in signal processing by reducing computational complexity compared to traditional methods like the discrete Fourier transform (DFT). It accelerates the processing time from ~120 ms (DFT) to ~16 ms (FFT), with numpy and scipy implementations further reducing it to microseconds (~40 µs with numpy and ~12 µs with scipy). This speed allows FFT to be used in real-time applications such as filtering signals or analyzing frequency components swiftly, surpassing traditional methods .

Plotting the FFT amplitude involves transforming a time-domain signal into its frequency-domain counterparts, represented by amplitude versus frequency plots. This visualization allows the identification of predominant frequencies within the signal. For example, in analyzing mixed sine waves, sharp peaks on the FFT plot indicate dominant frequencies, aiding in signal decomposition, interference analysis, or noise identification. Such analysis is crucial for diagnostics and optimizing systems that rely on specific frequency bands .

FFT's ability to accelerate data processing has revolutionized modern engineering and sciences by enabling real-time analysis and control across numerous applications. Its speed and efficiency allow for quick decomposition and interpretation of large datasets, critical in wireless communication, image processing, and real-time system monitoring. FFT has made it feasible to handle the increasing data volumes requisite for today's computational models and analytics, facilitating advancements and innovations in technology and research fields .

FFT allows transforming time-series data into the frequency domain, revealing periodic signals that may not be apparent in the time domain. For example, when analyzing California's electricity demand data, FFT showed clear peaks corresponding to 12, 24, and 84 hours, indicating repeating patterns associated with human activity. This transformation helps identify the frequency and intensity of periodic signals, making FFT a powerful tool for time-series analysis .

FFT is used to design a band-pass filter by transforming the time-domain signal to the frequency domain, then zeroing out FFT amplitudes outside the desired frequency range, and transforming it back to isolate desired frequencies. Practical applications include telecommunications where band-pass filters isolate specific frequencies for transmission, audio processing to separate vocal components from music, or within medical devices to filter noise from vital signals, enhancing clarity and accuracy in diverse engineering fields .

Pandas provides a versatile and efficient framework for handling and preprocessing large sets of time-series data, facilitating operations like data parsing, resampling, and cleaning, which are essential steps before applying FFT. In the analysis of California's electricity demand, pandas was used to read and organize data into a DataFrame, enabling easy manipulation and visualization. FFT can then be applied to this clean data set to analyze frequency components, combining the data handling strengths of pandas with the frequency analysis capabilities of FFT for deeper insights .

The interactive features and examples in the Python Numerical Methods online book offer practical, hands-on learning experiences, allowing engineers and scientists to apply theoretical concepts directly to real-world data and problems. Features such as live coding examples, editable plots, and step-by-step tutorials enable users to experiment, see immediate results, and better understand concepts like FFT. This interactive approach caters to various learning styles, promotes active learning, and helps solidify understanding, making it a superior educational resource .

Both scipy and numpy offer FFT functions, but scipy's implementation is faster, as indicated by a performance of ~12 µs per operation compared to numpy's ~40 µs. This improved efficiency of scipy makes it preferable for applications requiring high-speed processing or handling large datasets. Additionally, scipy integrates more features for signal processing beyond basic FFT, while numpy focuses on fundamental array operations, making scipy better suited for advanced applications .

Transforming the electricity demand data into the frequency domain using FFT revealed repeating signals at 12, 24, and 84-hour intervals. These frequencies correlate to daily activities and weekly cycles inherent in human behavior, such as work and rest periods. It suggests how energy consumption patterns reflect societal rhythms, providing insights into demand forecasting and power grid management .

Applying a high-pass filter using FFT to a mixed signal containing sine waves filters out frequencies below a designated cut-off. In the example, a mixed signal composed of 1, 4, and 7 Hz sine waves was high-pass filtered at 6 Hz, effectively attenuating the 1 and 4 Hz components. This was achieved by zeroing out FFT amplitudes of frequencies below the threshold, which, when returned to the time domain, left a filtered signal dominated by frequencies above the cut-off. FFT processing allows precise frequency-targeted filtering that can isolate specific signal components .

You might also like