Convolution Example — Pulse Smoothing and Cross-Correlation

This example convolves a rectangular pulse with a Gaussian smoothing kernel using transforms.convolve(), then detects a time delay between two delayed signals via cross-correlation.

Example Code

"""IMSL Convolution example: rectangular pulse convolved with Gaussian kernel.

Also demonstrates cross-correlation of two delayed signals.

Outputs:
- Summary table printed to stdout
- SVG plot saved to test_output/demo_imsl_convolution.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 convolve_real, correlate_real


def run_demo_imsl_convolution() -> Dict[str, object]:
    """Run IMSL convolution/correlation example.

    Convolves a rectangular pulse with a Gaussian smoothing kernel, then
    computes the cross-correlation of two time-shifted pulses to detect delay.

    Args:
        None

    Returns:
        Dict[str, object]: Result dict with keys ``conv_peak`` (float),
            ``detected_lag`` (int), and ``plot_path`` (str).
    """
    N = 128
    # Rectangular pulse signal
    x = np.zeros(N)
    x[40:60] = 1.0

    # Gaussian kernel
    sigma = 5.0
    k_range = np.arange(-15, 16)
    h = np.exp(-0.5 * (k_range / sigma) ** 2)
    h /= h.sum()

    # Convolution
    conv_result = convolve_real(x, h)
    conv_peak = float(conv_result.max())

    # Cross-correlation: detect delay between two pulses
    x1 = np.zeros(N)
    x1[30] = 1.0
    x2 = np.zeros(N)
    delay = 8
    x2[30 + delay] = 1.0

    corr_result = correlate_real(x1, x2)
    center = N - 1
    detected_lag = int(np.argmax(corr_result) - center)

    print("\nIMSL Convolution Example")
    print("-" * 45)
    print(f"{'Convolution peak amplitude':<30} {conv_peak:>10.4f}")
    print(f"{'True delay (samples)':<30} {delay:>10}")
    print(f"{'Detected lag from correlation':<30} {detected_lag:>10}")
    print("-" * 45)

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

    fig, axes = plt.subplots(3, 1, figsize=(10, 9))

    # Signal and kernel
    t = np.arange(N)
    axes[0].plot(t, x, color="#6d28d9", linewidth=1.5, label="Rect pulse x")
    ax0b = axes[0].twinx()
    k_plot = np.arange(len(h)) - 15
    ax0b.fill_between(k_plot + 50, h, alpha=0.4, color="#f59e0b", label="Gaussian h")
    axes[0].set_xlabel("Sample")
    axes[0].set_ylabel("x[n]")
    axes[0].set_title("Input Signal (rect pulse) and Gaussian Kernel")
    axes[0].legend(loc="upper left")
    axes[0].grid(True, alpha=0.3)

    # Convolution output
    t_conv = np.arange(len(conv_result))
    axes[1].plot(t_conv, conv_result, color="#7c3aed", linewidth=1.5)
    axes[1].set_xlabel("Sample")
    axes[1].set_ylabel("(x * h)[n]")
    axes[1].set_title("Convolution Output (rect pulse ∗ Gaussian)")
    axes[1].grid(True, alpha=0.3)

    # Correlation
    lags = np.arange(len(corr_result)) - center
    axes[2].plot(lags, corr_result, color="#059669", linewidth=1.5)
    axes[2].axvline(-delay, color="#dc2626", linestyle="--", linewidth=1.2,
                    label=f"True lag = {-delay}")
    axes[2].set_xlabel("Lag (samples)")
    axes[2].set_ylabel("R_{x1,x2}[lag]")
    axes[2].set_title("Cross-Correlation (delay detection)")
    axes[2].legend()
    axes[2].grid(True, alpha=0.3)
    axes[2].set_xlim(-30, 30)

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

    return {
        "conv_peak": conv_peak,
        "detected_lag": detected_lag,
        "plot_path": str(plot_path),
    }


if __name__ == "__main__":
    run_demo_imsl_convolution()

Plot Output

Three-panel plot showing pulse, convolved output, and cross-correlation

Three-panel plot: original rectangular pulse (top), Gaussian-smoothed output (middle), and cross-correlation lag plot detecting the time delay (bottom).

Console Output

IMSL Convolution Example
---------------------------------------------
Convolution peak amplitude         0.9556
True delay (samples)                    8
Detected lag from correlation          -8
---------------------------------------------