Source code for macro_eeg_model.evaluation.coherence_computer

# external imports
from scipy.signal import windows
import numpy as np


[docs] class CoherenceComputer: """ A class responsible for computing the coherence between signals. Attributes ---------- fs : int The sampling frequency of the signals. _window_type : str The type of window used for smoothing signals before coherence computation. """
[docs] def __init__(self, fs, window_type='hann'): """ Initializes the CoherenceComputer with the given sampling frequency and window type. Parameters ---------- fs : int The sampling frequency of the signals. window_type : str, optional The type of window to apply for smoothing the signals before coherence computation (default is 'hann'). """ self.fs = fs self._window_type = window_type
[docs] def compute_coherence_matched(self, sig1, sig2, smooth_signals=True): """ Computes the coherence between two signals using :py:meth:`_compute_coherence`, with an option to smooth the signals before computation using :py:meth:`_smooth_signal`. Parameters ---------- sig1 : numpy.ndarray The first signal array. sig2 : numpy.ndarray The second signal array. smooth_signals : bool, optional If True, applies a smoothing window to the signals before computing coherence (default is True). Returns ------- tuple A tuple containing: - positive_freqs (numpy.ndarray): The array of positive frequency values. - positive_coherence (numpy.ndarray): The coherence values corresponding to the positive frequencies. Raises ------ AssertionError If the two signals do not have the same shape. """ assert sig1.shape == sig2.shape, "The two signals must have the same shape." if sig1.ndim == 1: sig1 = sig1[np.newaxis, :] sig2 = sig2[np.newaxis, :] if smooth_signals: sig1 = np.array([self._smooth_signal(epoch) for epoch in sig1]) sig2 = np.array([self._smooth_signal(epoch) for epoch in sig2]) positive_freqs, positive_coherence = self._compute_coherence(sig1, sig2) return positive_freqs, positive_coherence
[docs] def _compute_coherence(self, sig1, sig2): """ Computes the coherence between two signals using their cross-spectrum and power spectra. Parameters ---------- sig1 : numpy.ndarray The first signal array with shape (nr_epochs, n_samples). sig2 : numpy.ndarray The second signal array with the same shape as `sig1`. Returns ------- tuple A tuple containing: - positive_freqs (numpy.ndarray): The array of positive frequency values. - positive_coherence (numpy.ndarray): The coherence values corresponding to the positive frequencies. """ # Compute the FFT of each epoch fft_sig1 = np.fft.fft(sig1, axis=1) fft_sig2 = np.fft.fft(sig2, axis=1) # Compute the cross-spectrum cross_spectrum = np.mean(fft_sig1 * np.conj(fft_sig2), axis=0) # Compute the power spectra power_spectrum_sig1 = np.mean(np.abs(fft_sig1) ** 2, axis=0) power_spectrum_sig2 = np.mean(np.abs(fft_sig2) ** 2, axis=0) # Compute the evaluation coh = np.abs(cross_spectrum) ** 2 / (power_spectrum_sig1 * power_spectrum_sig2) # Compute the frequency values freqs = np.fft.fftfreq(sig1.shape[1], 1 / self.fs) positive_freqs = freqs[:sig1.shape[1] // 2] positive_coherence = coh[:sig1.shape[1] // 2] return positive_freqs, positive_coherence
[docs] def _smooth_signal(self, signal): """ Applies a smoothing window to a signal. Parameters ---------- signal : numpy.ndarray The input signal array to be smoothed. Returns ------- numpy.ndarray The smoothed signal. """ window = windows.get_window(self._window_type, signal.size) return signal * window