Sine / Cosine Transform Example — DST and DCT Roundtrip Fidelity

This example computes the DST-II and DCT-II of a triangle wave signal using transforms.dst_forward() and transforms.dct_forward(), then reconstructs the signal via the inverse transforms and verifies numerical fidelity.

Example Code

"""IMSL Sine/Cosine Transform example: DST and DCT roundtrip fidelity.

Demonstrates forward DST/DCT and reconstruction via the inverse transforms.

Outputs:
- Summary table printed to stdout
- SVG plot saved to test_output/demo_imsl_sine_cosine.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_cosine, fft_sine


def run_demo_imsl_sine_cosine() -> Dict[str, object]:
    """Run IMSL DST/DCT roundtrip demonstration.

    Applies the forward DST and DCT to a simple piecewise-linear test signal,
    then reconstructs it via the inverse transforms and reports the max
    reconstruction error.

    Args:
        None

    Returns:
        Dict[str, object]: Result dict with keys ``dst_max_error`` (float),
            ``dct_max_error`` (float), and ``plot_path`` (str).
    """
    N = 32
    t = np.linspace(0, 1, N, endpoint=False)
    x = np.where(t < 0.5, 2 * t, 2 - 2 * t)  # triangle wave

    # DST roundtrip
    X_dst = fft_sine(x)
    x_dst_back = fft_sine(X_dst, inverse=True)
    dst_max_error = float(np.max(np.abs(x_dst_back - x)))

    # DCT roundtrip
    X_dct = fft_cosine(x)
    x_dct_back = fft_cosine(X_dct, inverse=True)
    dct_max_error = float(np.max(np.abs(x_dct_back - x)))

    print("\nIMSL Sine/Cosine Transform Example (N=32, triangle wave)")
    print("-" * 50)
    print(f"{'DST max reconstruction error':<35} {dst_max_error:.2e}")
    print(f"{'DCT max reconstruction error':<35} {dct_max_error:.2e}")
    print("-" * 50)

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

    fig, axes = plt.subplots(2, 2, figsize=(12, 8))

    n_idx = np.arange(N)

    # DST spectrum
    axes[0, 0].stem(n_idx, X_dst, linefmt="#7c3aed", markerfmt="o", basefmt="k-")
    axes[0, 0].set_title("DST Coefficients")
    axes[0, 0].set_xlabel("Index k")
    axes[0, 0].set_ylabel("X_DST[k]")
    axes[0, 0].grid(True, alpha=0.3)

    # DST reconstruction
    axes[0, 1].plot(t, x, color="#1f2937", linewidth=2.0, label="Original", zorder=3)
    axes[0, 1].plot(t, x_dst_back, color="#7c3aed", linewidth=1.5,
                    linestyle="--", label=f"DST roundtrip (err={dst_max_error:.1e})")
    axes[0, 1].set_title("DST Forward + Inverse Roundtrip")
    axes[0, 1].set_xlabel("t")
    axes[0, 1].set_ylabel("x")
    axes[0, 1].legend()
    axes[0, 1].grid(True, alpha=0.3)

    # DCT spectrum
    axes[1, 0].stem(n_idx, X_dct, linefmt="#059669", markerfmt="o", basefmt="k-")
    axes[1, 0].set_title("DCT Coefficients")
    axes[1, 0].set_xlabel("Index k")
    axes[1, 0].set_ylabel("X_DCT[k]")
    axes[1, 0].grid(True, alpha=0.3)

    # DCT reconstruction
    axes[1, 1].plot(t, x, color="#1f2937", linewidth=2.0, label="Original", zorder=3)
    axes[1, 1].plot(t, x_dct_back, color="#059669", linewidth=1.5,
                    linestyle="--", label=f"DCT roundtrip (err={dct_max_error:.1e})")
    axes[1, 1].set_title("DCT Forward + Inverse Roundtrip")
    axes[1, 1].set_xlabel("t")
    axes[1, 1].set_ylabel("x")
    axes[1, 1].legend()
    axes[1, 1].grid(True, alpha=0.3)

    fig.suptitle("IMSL Sine/Cosine Transform: DST-II and DCT-II Roundtrip Fidelity",
                 fontsize=13, fontweight="bold")
    fig.tight_layout()
    fig.savefig(plot_path, format="svg")
    plt.close(fig)

    return {
        "dst_max_error": dst_max_error,
        "dct_max_error": dct_max_error,
        "plot_path": str(plot_path),
    }


if __name__ == "__main__":
    run_demo_imsl_sine_cosine()

Plot Output

2x2 panel plot showing original signal, DST/DCT spectra, and reconstructed signal

2×2 panel plot: original triangle wave (top-left), DST-II spectrum (top-right), DCT-II spectrum (bottom-left), and reconstructed signal overlaid on the original (bottom-right).

Console Output

IMSL Sine/Cosine Transform Example (N=32, triangle wave)
--------------------------------------------------
DST max reconstruction error        2.22e-16
DCT max reconstruction error        1.11e-16
--------------------------------------------------