Skip to main content
v2026.11,858 entries · CC-BY 4.0

NumPy Fourier Transform: np.fft.fft, Frequencies and norm

How to run a NumPy Fourier transform with np.fft.fft, label frequencies with fftfreq, and pick the right norm, with a checkable four-point example.

Written and maintained by CASRAI Editorial Board

Last updated

To take a Fourier transform in NumPy, call np.fft.fft(a) on a one-dimensional array. It returns a complex array of the same length. Entry 0 is the sum of the signal, and the other entries are the coefficients of the frequencies listed by np.fft.fftfreq. Most mistakes come from three details that short tutorials skip: how the norm argument scales the result, the order in which frequencies are stored, and what the complex numbers mean. This guide covers all three, with a four-point example you can check by hand. It follows the NumPy documentation (current stable release 2.5, checked 2026-10-29).

What it is used for in research

The discrete Fourier transform rewrites a sampled signal as a sum of sinusoids, so you can see which frequencies it contains. Researchers use it to find the dominant oscillation in a time series (instrument vibration, a periodic physiological signal, a seasonal cycle), to measure how power is spread across frequency, and to filter in the frequency domain and transform back. For the wider field, see what signal processing is; for modelling time-ordered data in the time domain instead, see ARIMA models for research time series.

NumPy’s numpy.fft module defines the transform as Ak = Σ am exp(−2πi·mk/n), summed over m = 0 to n−1. The inverse differs only by the sign of the exponent and, by default, a factor of 1/n.

Install or access (official source only)

NumPy is free, open-source software. The official install page (checked 2026-10-29) gives these routes:

  • pip: pip install numpy
  • conda: conda create -n my-env, then conda activate my-env, then conda install numpy
  • Virtual environment: python -m venv my-env, then source my-env/bin/activate on macOS and Linux or my-env\Scripts\activate on Windows, then pip install numpy

If the analysis will be shared, record the environment so others can rebuild it; see sharing a reproducible conda environment and the definition of computational reproducibility. The functions below live in numpy.fft, so no extra package is needed.

Step-by-step: transform, invert and read a signal

1. Transform an array and invert it

  1. Import NumPy and create a one-dimensional real array: import numpy as np, then a = np.array([1.0, 2.0, 3.0, 4.0]).
  2. Transform it: A = np.fft.fft(a).
  3. Check the round trip: a_back = np.fft.ifft(A) returns the original values (as complex numbers with zero imaginary part).

For this input, A is [10+0j, -2+2j, -2+0j, -2-2j]. Entry 0 is 1+2+3+4 = 10, the sum of the signal, exactly as the documentation describes the zero-frequency term.

2. Attach frequencies to the bins

  1. Build the frequency axis: freqs = np.fft.fftfreq(len(a), d=dt), where d is the sample spacing, the inverse of the sampling rate. The default is 1. If dt is in seconds, the frequencies are in cycles per second (Hz).

With len(a) = 4 and d = 1, freqs is [0, 0.25, -0.5, -0.25]. The documentation gives the layout: for even n, the values [0, 1, ..., n/2-1, -n/2, ..., -1] / (d*n). Non-negative frequencies come first, then negative ones, and this matches the order of the fft output.

3. Plot amplitude against frequency

  1. Take amp = np.abs(A) and plot it against freqs. To get a plot with the zero frequency in the middle, apply np.fft.fftshift to both the spectrum and the frequencies. np.fft.ifftshift undoes the shift.

Worked example: finding two known frequencies

For real-valued signals, rfft returns only the non-negative frequencies. Build a signal sampled at 100 Hz for 1 second, made of a 5 Hz sine with amplitude 3 and a 20 Hz sine with amplitude 1:

import numpy as np
fs = 100
t = np.arange(0, 1, 1/fs)
x = 3*np.sin(2*np.pi*5*t) + 1*np.sin(2*np.pi*20*t)
X = np.fft.rfft(x)
f = np.fft.rfftfreq(len(x), d=1/fs)
amp = 2*np.abs(X)/len(x)

Running this, the two largest entries of amp are 3.0 at f = 5.0 and 1.0 at f = 20.0. The factor 2/N is a convention for one-sided spectra of sinusoids: because the signal covers whole cycles, each sine’s energy splits between a positive and a negative frequency, and rfft keeps only the positive one. The SciPy tutorial uses the plain abs(rfft(x)/N), which gives half these values; both are valid as long as you state which scaling you report.

Output and how to read it

Why is the output complex?

Each coefficient carries a magnitude and a phase. NumPy’s documentation states that np.abs(A) is the amplitude spectrum, np.abs(A)**2 is the power spectrum, and np.angle(A) gives the phase spectrum. For real input, A[0] is always purely real.

What does the norm argument do?

The norm keyword decides where the 1/n factor goes. The documentation notes that the "backward" and "forward" values were added in NumPy 1.20.0. Use the same setting for the forward and inverse call, or the round trip will be scaled wrongly.

norm Forward scaling Inverse scaling
"backward" (default; None is an alias) none 1/n
"ortho" 1/√n 1/√n
"forward" 1/n none

For the four-point example, np.fft.fft(a, norm="ortho") returns [5+0j, -1+1j, -1+0j, -1-1j], which is the default result divided by √4 = 2. With "ortho" both directions are scaled by the same factor, so the sum of squared magnitudes is preserved between the signal and its transform. In the example, the signal has 1+4+9+16 = 30, and the ortho spectrum has 25+2+1+2 = 30.

What is the difference between rfft and fft?

rfft takes real input of n points and returns n/2+1 complex points, the non-negative frequencies only. fft returns all n. Use rfftfreq for the matching frequency axis. Going back, irfft needs the original length passed as n when it was odd: from the same rfft output, the default irfft returns an even length, so pass n=5 to recover a 5-point signal.

Troubleshooting

  • Spectrum looks mirrored or frequencies look wrong. The output is not sorted from negative to positive. Use fftfreq for labels, or fftshift on both arrays together.
  • Peak heights do not match the signal amplitude. The default norm leaves the forward transform unscaled, so amplitudes grow with n. Divide by n (and double non-zero bins for a one-sided spectrum), or use norm="forward".
  • Slow on some lengths. The documentation says the FFT is most efficient when n is a power of 2. SciPy’s documentation adds that it is slowest when n is prime, and offers scipy.fft.next_fast_len to find a good length. In NumPy you can pass n to fft: a smaller n crops the input and a larger n zero-pads it.
  • IndexError from fft. The axis you passed does not exist for the array. The default is the last axis (axis=-1).
  • Single-precision input. numpy.fft promotes float32 and complex64 arrays to float64 and complex128, so the output is double precision.
  • Edge artefacts. The transform assumes the signal repeats periodically. The SciPy tutorial discusses detrending but warns that it does not necessarily improve the spectrum.

Free alternatives

Option What its documentation says
numpy.fft fft/ifft, 2-D and n-D versions (fft2, fftn), real-input versions (rfft, irfft), Hermitian-signal versions (hfft, ihfft), plus fftfreq, rfftfreq, fftshift, ifftshift.
scipy.fft The same family of transforms, plus discrete cosine and sine transforms (dct, dst), next_fast_len, a set_workers context manager for the maximum number of threads, and set_backend for third-party backends.

Both are free and open source. Choose by the features you need from the table; for a plain FFT of an array, numpy.fft is enough.

FAQ

How do I get frequencies in Hz from np.fft.fft?

Call np.fft.fftfreq(n, d=1/fs), where n is the number of samples and fs the sampling rate in Hz. Entry k of the result is the frequency of bin k of the transform.

Is the FFT output complex even for a real signal?

Yes. Take the magnitude with np.abs for amplitude and np.angle for phase. For real input, rfft returns only the non-redundant half.

Does the default scaling make ifft(fft(a)) equal a?

Yes. With the default norm="backward" the inverse applies the 1/n factor, so the round trip returns the input up to round-off.

When should I use scipy.fft instead?

When you need cosine or sine transforms, multithreaded execution via set_workers, helpers such as next_fast_len, or a third-party backend. Otherwise numpy.fft covers the standard transforms.

Sources (official docs)

All pages checked 2026-10-29.

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about NumPy Fourier Transform: np.fft.fft, Frequencies and norm

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.