CSD

The cross power spectral density (CSD) is a measure of the common frequency content between two signals. It is calculated by taking the Fourier transform of the cross-correlation between the two signals.

Like Welch’s method for power spectral density, this function estimates the CSD by dividing the signals into overlapping segments, computing the cross-periodogram for each segment pair, and averaging the results.

Excel Usage

=CSD(x, y, fs, window, nperseg, noverlap, nfft, spectral_detrend, return_onesided, spectral_scaling, avg_method)
  • x (list[list], required): Time series of measurement values for first signal.
  • y (list[list], required): Time series of measurement values for second signal.
  • fs (float, optional, default: 1): Sampling frequency.
  • window (str, optional, default: “hann”): Desired window to use.
  • nperseg (int, optional, default: null): Length of each segment.
  • noverlap (int, optional, default: null): Number of points to overlap between segments.
  • nfft (int, optional, default: null): Length of the FFT used.
  • spectral_detrend (str, optional, default: “constant”): Specifies how to detrend each segment.
  • return_onesided (bool, optional, default: true): If True, return a one-sided spectrum for real data.
  • spectral_scaling (str, optional, default: “density”): Selects between ‘density’ and ‘spectrum’.
  • avg_method (str, optional, default: “mean”): Method to use when averaging periodograms.

Returns (list[list]): A 2D array representing frequencies and cross spectral density.

Example 1: Basic CSD

Inputs:

x y
1 2 3 4 5 4 3 2 1 1.1 2.1 3.1 4.1 5.1 4.1 3.1 2.1 1.1

Excel formula:

=CSD({1,2,3,4,5,4,3,2,1}, {1.1,2.1,3.1,4.1,5.1,4.1,3.1,2.1,1.1})

Expected output:

Result
0 0.111111 0.222222 0.333333 0.444444
4.49611 10.5132 3.43142 0.263405 0.179396
0 5.26328e-16 -7.89492e-16 8.22387e-17 1.39806e-16
Example 2: CSD with median averaging

Inputs:

x y avg_method
1 2 1 2 1 2 1 2 2 1 2 1 2 1 2 1 median

Excel formula:

=CSD({1,2,1,2,1,2,1,2}, {2,1,2,1,2,1,2,1}, "median")

Expected output:

Result
0 0.125 0.25 0.375 0.5
0 -4.10865e-33 0 -0.666667 -1.33333
0 0 0 0 0
Example 3: CSD with spectrum scaling

Inputs:

x y spectral_scaling nperseg
0 1 0 -1 0 1 0 -1 0 1 0 -1 0 1 0 -1 spectrum 4

Excel formula:

=CSD({0,1,0,-1,0,1,0,-1}, {0,1,0,-1,0,1,0,-1}, "spectrum", 4)

Expected output:

Result
0 0.25 0.5
0 0.5 0
0 0 0
Example 4: CSD with scalar-compatible inputs

Inputs:

x y
3 3.2

Excel formula:

=CSD(3, 3.2)

Expected output:

Result
0
0
0

Python Code

Show Code
import numpy as np
from scipy.signal import csd as scipy_csd

def csd(x, y, fs=1, window='hann', nperseg=None, noverlap=None, nfft=None, spectral_detrend='constant', return_onesided=True, spectral_scaling='density', avg_method='mean'):
    """
    Estimate the cross power spectral density (Pxy) using Welch's method.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.csd.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        x (list[list]): Time series of measurement values for first signal.
        y (list[list]): Time series of measurement values for second signal.
        fs (float, optional): Sampling frequency. Default is 1.
        window (str, optional): Desired window to use. Default is 'hann'.
        nperseg (int, optional): Length of each segment. Default is None.
        noverlap (int, optional): Number of points to overlap between segments. Default is None.
        nfft (int, optional): Length of the FFT used. Default is None.
        spectral_detrend (str, optional): Specifies how to detrend each segment. Valid options: Constant, Linear, None. Default is 'constant'.
        return_onesided (bool, optional): If True, return a one-sided spectrum for real data. Default is True.
        spectral_scaling (str, optional): Selects between 'density' and 'spectrum'. Valid options: Density, Spectrum. Default is 'density'.
        avg_method (str, optional): Method to use when averaging periodograms. Valid options: Mean, Median. Default is 'mean'.

    Returns:
        list[list]: A 2D array representing frequencies and cross spectral density.
    """
    try:
        def to_1d(v):
            if isinstance(v, list):
                if all(isinstance(row, list) for row in v):
                    return np.array([float(x) for row in v for x in row], dtype=float)
                return np.array([float(x) for x in v], dtype=float)
            return np.array([float(v)], dtype=float)

        x_arr = to_1d(x)
        y_arr = to_1d(y)

        detrend = spectral_detrend
        if detrend == "False":
            detrend = False

        f, pxy = scipy_csd(
            x_arr, 
            y_arr, 
            fs=float(fs), 
            window=window, 
            nperseg=int(nperseg) if nperseg is not None else None, 
            noverlap=int(noverlap) if noverlap is not None else None, 
            nfft=int(nfft) if nfft is not None else None, 
            detrend=detrend, 
            return_onesided=bool(return_onesided), 
              scaling=spectral_scaling,
            average=avg_method
        )

        return [f.tolist(), pxy.real.tolist(), pxy.imag.tolist()]
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

Time series of measurement values for first signal.
Time series of measurement values for second signal.
Sampling frequency.
Desired window to use.
Length of each segment.
Number of points to overlap between segments.
Length of the FFT used.
Specifies how to detrend each segment.
If True, return a one-sided spectrum for real data.
Selects between 'density' and 'spectrum'.
Method to use when averaging periodograms.