Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Frequency Decomposition of Zonal Wind Variability Using the Fourier Transform

Authors
Affiliations
University at Albany (SUNY)
Florida Institute of Technology
University at Albany (SUNY)
Texas A&M University
University at Albany (SUNY)
Duke University
University of Georgia
University at Albany (SUNY)

Overview

Tropical low-level winds vary on a wide range of time scales, from the annual cycle driven by solar forcing, to intraseasonal fluctuations associated with the Madden–Julian Oscillation (MJO), and interannual signals linked to ENSO. A useful way to characterize a field’s variability is to partition its total variance into these time-scale bands.

In this notebook we use the Fast Fourier Transform (FFT) to decompose daily 850-hPa zonal wind (u850u_{850}) from the NCEP–NCAR Reanalysis into a set of frequency bands and map the spatial structure of each one. The workflow is:

  1. Load daily u850u_{850} from the public Pythia Zarr store.

  2. Build the power spectrum at a single tropical grid point and identify the dominant peaks (annual cycle and its harmonics).

  3. Loop over every grid point, compute the FFT, and sum the explained variance inside each band:

    • Annual cycle (~365 days)

    • Intraseasonal (20–90 days, including the MJO band)

    • Interannual (2–7 years, including ENSO)

    • Background (periods longer than 100 days)

    • Subseasonal (periods shorter than 80 days)

  4. Map the explained variance (%) for each band and the total standard deviation, then interpret the resulting patterns.

The result is a set of maps showing where in the tropics each time-scale band carries most of the u850u_{850} variability.

Prerequisites

ConceptsImportanceNotes
The Discrete Fourier TransformNecessaryFrequencies, periods, and Fourier coefficients
Fourier Power Spectrum and Spectral FilteringNecessaryPower spectrum and explained variance
Anomaly Time SeriesHelpfulBackground on the same 850-hPa zonal wind dataset
  • Time to learn: 20 minutes


Imports

We use xarray and s3fs to read the cloud-hosted Zarr dataset, numpy for the FFT and the band-integration math, and matplotlib/cartopy to map the variance partition.

Access data

We use the same NCEP–NCAR Reanalysis Kanamitsu et al., 2002 zonal wind dataset as in Anomaly Time Series. The variable of interest is daily zonal wind, uwnd, on a global latitude–longitude grid; we will use only the lowest pressure level (level=0, 850 hPa).

Loading...

Spectral analysis

We start with a single grid point to build intuition for the FFT-based power spectrum, and then extend the same calculation to every grid point in the dataset to obtain maps of variance per frequency band.

Before carrying out the spectral analysis, let’s look at the global u850u_{850} field on the first day of the record. The X marker indicates the eastern Indian Ocean grid point used for the single-location example below.

<cartopy.mpl.gridliner.Gridliner at 0x7f7dc1e255d0>
/home/runner/micromamba/envs/spectral-cookbook-dev/lib/python3.11/site-packages/cartopy/io/__init__.py:263: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_physical/ne_110m_coastline.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
<Figure size 1000x500 with 2 Axes>

We will start by performing the FFT at a single location. We pick a grid point over the eastern Indian Ocean (0°N, 90°E), indicated by the X in the map above. This region is dominated by deep tropical convection and is a hotspot of intraseasonal variability associated with the MJO, so it is a useful place to look for energetic signals on several time scales.

<Figure size 640x480 with 1 Axes>

Before applying the FFT we center the series by subtracting its time mean. This removes the zero-frequency (DC) Fourier coefficient, so the spectrum describes only the variability of the time series, not its absolute level.

<Figure size 640x480 with 1 Axes>

We now compute the FFT of the centered series and convert frequencies to periods with T=1/∣f∣T = 1/|f| (the zero-frequency bin is set to ∞\infty to avoid division by zero). The power spectrum is ∣x^k∣2|\hat{x}_k|^2. By Parseval’s theorem, the sum of the power equals the total variance of the series, so each bin can be expressed as the fraction of variance it explains:

explained variance(fk)  =  100  ×  ∣x^k∣2∑k∣x^k∣2    [%].\text{explained variance}(f_k)\;=\;100\;\times\;\frac{|\hat{x}_k|^2}{\sum_k |\hat{x}_k|^2}\;\;[\%].
/tmp/ipykernel_4458/537958354.py:5: RuntimeWarning: divide by zero encountered in divide
  periods = np.where(freqs != 0, 1 / np.abs(freqs), np.inf)
<Figure size 640x480 with 1 Axes>

Clear spectral peaks appear at 365 days (annual cycle) and at its harmonics. Refer back to Fourier Power Spectrum and Spectral Filtering to cover this topic in depth.

We now generalize the single-point calculation to every grid point and partition the variance into a set of frequency bands. Each band is targeted at a specific kind of tropical variability:

BandPeriod rangeVariability captured
Annual Cycle (AC)364–366 daysSeasonal cycle
Intraseasonal (IS)20–90 daysMJO and related convective fluctuations
Interannual (IA)2–7 yearsENSO and other low-frequency modes
Background (BG)> 100 daysAll low-frequency variability (includes AC and IA)
Subseasonal (SS)< 80 daysAll high-frequency variability (includes IS)

For every grid point, the procedure is:

  1. Extract the time series and center it by removing the time mean.

  2. Compute the FFT and convert each frequency bin to its period T=1/∣f∣T = 1/|f|.

  3. Build the power spectrum ∣x^k∣2|\hat{x}_k|^2 and the explained-variance spectrum (% of total variance).

  4. Apply a boolean frequency mask for each band and sum the contributions inside it.

  5. Store both the variance (units of m2 s−2\mathrm{m^2\,s^{-2}}) and the explained variance (%) of every band on the original spatial grid.

As a quick sanity check, we apply the annual-cycle mask to the single-point spectrum computed above. At this Indian Ocean grid point the annual band alone explains about 5.8% of the total u850u_{850} variance:

np.float32(0.1229185)
(17167, 2, 25, 144)

Next, we pull the underlying NumPy array out of the xarray dataset and reshape it from (time, lat, lon) to (time, lat * lon). Collapsing the spatial dimensions into one makes it easy to iterate over grid points in a single loop.

We also allocate empty arrays — one per band — to hold the variance and the explained variance (%) at every grid point, and we set the period limits that define each band.

We now loop over every grid point and repeat the single-location analysis: center the series, compute the FFT and the explained-variance spectrum, then sum the contribution of each band using the boolean masks. The results are stored in the flat (lat*lon,) arrays allocated above.

/tmp/ipykernel_4458/2317136713.py:15: RuntimeWarning: divide by zero encountered in divide
  periods = np.where(freqs != 0, 1 / np.abs(freqs), np.inf)

We reshape the flat per-grid-point arrays back to (lat, lon) so they can be plotted on a map. We also convert variances to standard deviations (the square root of the band variance), which share the same units as the original wind speeds and are easier to compare with the total u850u_{850} standard deviation.

Plots

With the variance partition stored on the original grid, we can now answer two complementary questions:

  1. Where is u850u_{850} most variable in absolute terms? — answered by the total standard deviation map.

  2. What kind of variability dominates at each location? — answered by the explained-variance map of each band.

Total standard deviation

The map below shows the total standard deviation of daily 850-hPa zonal wind. It marks the regions where u850u_{850} is most variable overall, without yet distinguishing between time scales. The largest values appear over the Indian Ocean and the maritime continent, consistent with the strong seasonal monsoon reversal and intense intraseasonal convective activity in that sector. Additional centers of action are found in the extratropical storm tracks of both hemispheres.

<Figure size 800x500 with 2 Axes>

Explained variance by frequency band

The next figure shows the explained variance (%) at each grid point for the five frequency bands defined above, on a common 0–90% color scale. Bright colors indicate that the band carries most of the local u850u_{850} variance; dark colors indicate that little of the variability lives in that band.

<Figure size 1200x600 with 7 Axes>

The maps highlight that different physical regimes dominate u850u_{850} variability at different time scales:

  • Annual cycle (AC). The largest fraction of variance (up to ~90%) is concentrated in the monsoon belts, most notably over the Indian Ocean and the maritime continent, as well as in the African and East Asian monsoon sectors. These are the regions where the seasonal reversal of the trade winds is strongest.

  • Subseasonal (SS, < 80 days). Outside the monsoon belts, subseasonal variability dominates and explains a large fraction of the variance (~70% or more), particularly in the midlatitudes, where transient eddies and storm-track activity drive most of the day-to-day fluctuations.

  • Intraseasonal (IS, 20–90 days). A more modest contribution (~20–30%) is found within the tropical band, especially over the Indian Ocean and the western Pacific. This is the spectral fingerprint of the Madden–Julian Oscillation and related convectively coupled waves.

  • Interannual (IA, 2–7 years). A small but coherent contribution (a few percent) appears in the central and eastern equatorial Pacific, consistent with the imprint of ENSO on the low-level zonal flow.

  • Background (BG, > 100 days). This broad low-frequency envelope mirrors the AC pattern (which it contains), confirming that the annual cycle accounts for the bulk of low-frequency variability in u850u_{850}.


Summary

In this notebook we used the Fast Fourier Transform to decompose daily NCEP–NCAR 850-hPa zonal wind into five frequency bands and mapped how each band contributes to the total variability in the tropics.

Key takeaways:

  • The FFT lets us go from a time series to a power spectrum; thanks to Parseval’s theorem, each frequency bin can be expressed as a fraction of the total variance.

  • Summing the explained variance inside a band (“integrating the spectrum”) yields the contribution of that band to the local variability, a robust way to compare time scales across regions.

  • For u850u_{850}, the annual cycle dominates the monsoon belts (especially over the Indian Ocean), while the subseasonal band dominates in the midlatitudes, the intraseasonal band captures MJO activity in the tropics, and the interannual band carries an ENSO-like signal in the equatorial Pacific.

  • The background and subseasonal envelopes are intentionally broad and overlap with the narrower physical bands; together they confirm where low- vs. high-frequency processes account for the bulk of the variance.

What’s next?

This variance partition provides a first look at where variability occurs in frequency space. However, individual FFT frequencies can be noisy and not all peaks are statistically significant.

The next notebook, Spectral Analysis of Tropical Variability and the MJO, improves on this by using Welch’s method to smooth spectra, testing peaks against an AR(1) red-noise background, and applying a 20–90 day bandpass filter to isolate the MJO signal. It also uses lead–lag correlations and Hovmöller diagrams to examine MJO propagation and convection–circulation coupling.

A complementary approach is the EOF track (2D EOFs → 3D EOFs → Extended EOFs → Multivariate EOFs), which separates variability into spatial patterns instead of frequency bands. This method is particularly useful for identifying large-scale phenomena such as ENSO and the MJO.

References
  1. Kanamitsu, M., Ebisuzaki, W., Woollen, J., Yang, S.-K., Hnilo, J. J., Fiorino, M., & Potter, G. L. (2002). Ncep–doe amip-ii reanalysis (r-2). Bulletin of the American Meteorological Society, 83(11), 1631–1644.