2-D Fourier Transform Example — Gaussian Blob Image

This example creates a 128×128 test image containing three Gaussian blobs at different positions and amplitudes, computes its 2-D FFT using transforms.fft_2d_forward(), shifts the spectrum to centre DC with numpy.fft.fftshift(), and visualises the log-magnitude spectrum.

Example Code

"""IMSL 2D Fourier Transform example: FFT of a 2D Gaussian blob image.

Creates a 2-D test image with three Gaussian blobs and computes its 2-D FFT
using :func:`transforms.fft_2d_forward`, then displays the log-magnitude
spectrum shifted to the DC-centre.

Outputs:
- SVG plot saved to test_output/example_imsl_2d_fft.svg
"""

from __future__ import annotations

from pathlib import Path
from typing import Dict

import matplotlib.pyplot as plt
import numpy as np

from transforms import fft_2d_forward


def _gaussian_blob(
    grid_x: np.ndarray,
    grid_y: np.ndarray,
    cx: float,
    cy: float,
    sigma: float,
    amplitude: float = 1.0,
) -> np.ndarray:
    """Generate a 2-D Gaussian blob on a coordinate grid.

    Args:
        grid_x (np.ndarray): 2-D array of x-coordinates (shape *(M, N)*).
        grid_y (np.ndarray): 2-D array of y-coordinates (shape *(M, N)*).
        cx (float): x-coordinate of the blob centre.
        cy (float): y-coordinate of the blob centre.
        sigma (float): Standard deviation (width) of the Gaussian in the same
            units as *grid_x* / *grid_y*.
        amplitude (float): Peak amplitude of the blob. Defaults to 1.0.

    Returns:
        np.ndarray: 2-D array of shape *(M, N)* with Gaussian values.
    """
    return amplitude * np.exp(-((grid_x - cx) ** 2 + (grid_y - cy) ** 2) / (2 * sigma ** 2))


def run_demo_imsl_2d_fft() -> Dict[str, object]:
    """Run IMSL 2-D FFT example: spectrum of a multi-blob Gaussian image.

    Constructs a 128×128 image consisting of three Gaussian blobs at different
    positions and computes its 2-D FFT using :func:`transforms.fft_2d_forward`.
    The log-magnitude spectrum is shifted to centre DC using
    :func:`numpy.fft.fftshift`.

    Args:
        None

    Returns:
        Dict[str, object]: Result dict with keys ``image_shape`` (tuple),
            ``spectrum_peak`` (float), and ``plot_path`` (str).
    """
    M, N = 128, 128
    x = np.linspace(-1.0, 1.0, N)
    y = np.linspace(-1.0, 1.0, M)
    grid_x, grid_y = np.meshgrid(x, y)

    image = (
        _gaussian_blob(grid_x, grid_y, cx=0.0, cy=0.0, sigma=0.15, amplitude=1.0)
        + _gaussian_blob(grid_x, grid_y, cx=0.4, cy=0.3, sigma=0.08, amplitude=0.7)
        + _gaussian_blob(grid_x, grid_y, cx=-0.35, cy=-0.25, sigma=0.10, amplitude=0.5)
    )

    spectrum_2d = fft_2d_forward(image.astype(complex))
    spectrum_shifted = np.fft.fftshift(spectrum_2d)
    log_magnitude = np.log1p(np.abs(spectrum_shifted))
    spectrum_peak = float(np.max(log_magnitude))

    print("\nIMSL 2-D FFT Example")
    print(f"  Image shape : {image.shape}")
    print(f"  Spectrum peak (log-magnitude): {spectrum_peak:.4f}")

    output_dir = Path("test_output")
    output_dir.mkdir(parents=True, exist_ok=True)
    plot_path = output_dir / "example_imsl_2d_fft.svg"

    fig, axes = plt.subplots(1, 2, figsize=(11, 5))

    im0 = axes[0].imshow(image, cmap="viridis", origin="lower", extent=[-1, 1, -1, 1])
    fig.colorbar(im0, ax=axes[0], label="Amplitude")
    axes[0].set_title("Original Image (Gaussian Blobs)")
    axes[0].set_xlabel("x")
    axes[0].set_ylabel("y")

    im1 = axes[1].imshow(log_magnitude, cmap="inferno", origin="lower")
    fig.colorbar(im1, ax=axes[1], label="log(1 + |F|)")
    axes[1].set_title("2-D FFT Magnitude Spectrum (log scale, DC-centred)")
    axes[1].set_xlabel("Frequency x")
    axes[1].set_ylabel("Frequency y")

    fig.tight_layout()
    fig.savefig(plot_path, format="svg")
    plt.close(fig)

    return {
        "image_shape": image.shape,
        "spectrum_peak": spectrum_peak,
        "plot_path": str(plot_path),
    }


if __name__ == "__main__":
    run_demo_imsl_2d_fft()

Plot Output

Original 2-D Gaussian blob image and its log-magnitude FFT spectrum

Left: original 128×128 image with three Gaussian blobs. Right: log-magnitude of the 2-D FFT spectrum, DC-centred, showing the spatial frequency content of the blobs.

Console Output

IMSL 2-D FFT Example
  Image shape : (128, 128)
  Spectrum peak (log-magnitude): 6.6985