COHERENCE

Coherence is a frequency-domain measure of the linear relationship between two signals. It is the normalized cross power spectral density.

The magnitude squared coherence is defined as:

C_{xy}(f) = \frac{|P_{xy}(f)|^2}{P_{xx}(f) P_{yy}(f)}

Values range from 0 to 1, where 1 indicates perfect linear relationship and 0 indicates no relationship at that frequency.

Excel Usage

=COHERENCE(x, y, fs, window, nperseg, noverlap, nfft, spectral_detrend)
  • 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.

Returns (list[list]): A 2D array where the first row is frequencies and the second row is the magnitude squared coherence.

Example 1: Basic Coherence

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:

=COHERENCE({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
1 1 1 1 1
Example 2: Coherence with linear detrending

Inputs:

x y spectral_detrend
1 3 5 7 9 11 13 15 2 4 6 8 10 12 14 16 linear

Excel formula:

=COHERENCE({1,3,5,7,9,11,13,15}, {2,4,6,8,10,12,14,16}, "linear")

Expected output:

Result
0 0.125 0.25 0.375 0.5
NaN NaN NaN NaN NaN
Example 3: Coherence with scalar-compatible single values

Inputs:

x y
2 2.5

Excel formula:

=COHERENCE(2, 2.5)

Expected output:

Result
0
NaN
Example 4: Coherence with explicit segment length

Inputs:

x y nperseg
0 1 0 -1 0 1 0 -1 0.1 0.9 0.2 -1.1 0.1 1 0 -0.9 4

Excel formula:

=COHERENCE({0,1,0,-1,0,1,0,-1}, {0.1,0.9,0.2,-1.1,0.1,1,0,-0.9}, 4)

Expected output:

Result
0 0.25 0.5
NaN 0.987256 NaN

Python Code

Show Code
import numpy as np
from scipy.signal import coherence as scipy_coherence

def coherence(x, y, fs=1, window='hann', nperseg=None, noverlap=None, nfft=None, spectral_detrend='constant'):
    """
    Estimate the magnitude squared coherence (Cxy) using Welch's method.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.coherence.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'.

    Returns:
        list[list]: A 2D array where the first row is frequencies and the second row is the magnitude squared coherence.
    """
    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, cxy = scipy_coherence(
            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 [f.tolist(), cxy.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.