Source code for medusa.connectivity.phase_connectivity

import scipy.signal as sp_signal
import numpy as np
from medusa import transforms
from numba import jit
import warnings


[docs]@jit(nopython=True, cache=True, parallel=True) def reshape_angles_loops(phase_data): """ Additional method require for the implementation of PLV, PLI, and wPLI in Numba. It receives the phases of the signal and return the PLV, PLI and wPLI connectivity matrices. NOTE: The shape of "phase_data" is [n_channels x n_samples], not the usual [n_samples x n_channels] Parameters ---------- phase_data : numpy 2D matrix phases of the MEEG Signal. [n_channels x n_samples]. Returns ------- plv : numpy 2D square matrix plv-based connectivity matrix. [n_channels x n_channels]. pli : numpy 2D square matrix pli-based connectivity matrix. [n_channels x n_channels]. wpli : numpy 2D square matrix wpli-based connectivity matrix. [n_channels x n_channels]. """ n_cha = phase_data.shape[0] m = np.empty((phase_data.shape[0] * phase_data.shape[0], phase_data.shape[1])) for i in range(n_cha): for j in range(n_cha): m[n_cha * i + j] = phase_data[i] - phase_data[j] n = np.empty((phase_data.shape[0] * phase_data.shape[0])) for i in range(m.shape[0]): n[i] = np.mean(np.sign(np.sin(m[i]))) pli_vector = np.absolute(n) pli = np.reshape(pli_vector, (n_cha, n_cha)) plv_vector = np.divide( np.absolute(np.sum(np.exp(1j * m), axis=1)), phase_data.shape[1]) plv = np.reshape(plv_vector, (n_cha, n_cha)) imz = np.sin(m) num = np.empty((phase_data.shape[0] * phase_data.shape[0])) den = np.empty((phase_data.shape[0] * phase_data.shape[0])) for i in range(m.shape[0]): num[i] = np.absolute( np.mean(np.multiply(np.absolute(imz[i]), np.sign(imz[i])))) den[i] = np.mean(np.absolute(imz[i])) wpli_vector = np.divide(num, den) wpli = np.reshape(wpli_vector, (n_cha, n_cha)) return plv, pli, wpli
def __phase_connectivity_numba(data): """ This method implements three phase-based connectivity parameters using Numba: PLV, PLI, and wPLI. REFERENCES: PLV: Mormann, F., Lehnertz, K., David, P., & Elger, C. E. (2000). Mean phase coherence as a measure for phase synchronization and its application to the EEG of epilepsy patients. Physica D: Nonlinear Phenomena, 144(3-4), 358-369. PLI: Nolte, G., Bai, O., Wheaton, L., Mari, Z., Vorbach, S., & Hallett, M. (2004). Identifying true brain interaction from EEG data using the imaginary part of coherency. Clinical neurophysiology, 115(10), 2292-2307. wPLI: Vinck, M., Oostenveld, R., Van Wingerden, M., Battaglia, F., & Pennartz, C. M. (2011). An improved index of phase-synchronization for electrophysiological data in the presence of volume-conduction, noise and sample-size bias. Neuroimage, 55(4), 1548-1565. NOTE: PLV is sensitive to volume conduction effects Parameters ---------- data : numpy 2D matrix MEEG Signal. [n_samples x n_channels]. Returns ------- plv : numpy 2D square matrix plv-based connectivity matrix. [n_channels x n_channels]. pli : numpy 2D square matrix pli-based connectivity matrix. [n_channels x n_channels]. wpli : numpy 2D square matrix wpli-based connectivity matrix. [n_channels x n_channels]. """ # Error check if type(data) != np.ndarray: raise ValueError("Parameter data must be of type numpy.ndarray") if data.shape[0] < data.shape[1]: warnings.warn("Warning: Signal dimensions flipped out. If you have more" " samples than channels, comment this " "line") data = data.T # Variable initialization num_chan = data.shape[1] # Connectivity computation phase_data = np.transpose(np.angle(sp_signal.hilbert(np.transpose(data)))) phase_data = np.ascontiguousarray(phase_data.T) # angles_1 = np.reshape(np.tile(phase_data, (num_chan, 1)), # (len(phase_data), num_chan * num_chan), # order='F') # angles_2 = np.tile(phase_data, (1, num_chan)) # pli_vector = abs(np.mean(np.sign(np.sin(angles_1 - angles_2)), axis=0)) plv, pli, wpli, = reshape_angles_loops(phase_data) return plv, pli, wpli, def __phase_connectivity_cpu(data): """ This method implements three phase-based connectivity parameters using CPU: PLV, PLI, and wPLI. REFERENCES: PLV: Mormann, F., Lehnertz, K., David, P., & Elger, C. E. (2000). Mean phase coherence as a measure for phase synchronization and its application to the EEG of epilepsy patients. Physica D: Nonlinear Phenomena, 144(3-4), 358-369. PLI: Nolte, G., Bai, O., Wheaton, L., Mari, Z., Vorbach, S., & Hallett, M. (2004). Identifying true brain interaction from EEG data using the imaginary part of coherency. Clinical neurophysiology, 115(10), 2292-2307. wPLI: Vinck, M., Oostenveld, R., Van Wingerden, M., Battaglia, F., & Pennartz, C. M. (2011). An improved index of phase-synchronization for electrophysiological data in the presence of volume-conduction, noise and sample-size bias. Neuroimage, 55(4), 1548-1565. NOTE: PLV is sensitive to volume conduction effects Parameters ---------- data : numpy 2D matrix MEEG Signal. [n_samples x n_channels]. Returns ------- plv : numpy 2D square matrix plv-based connectivity matrix. [n_channels x n_channels]. pli : numpy 2D square matrix pli-based connectivity matrix. [n_channels x n_channels]. wpli : numpy 2D square matrix wpli-based connectivity matrix. [n_channels x n_channels]. """ # Error check if type(data) != np.ndarray: raise ValueError("Parameter data must be of type numpy.ndarray") if data.shape[0] < data.shape[1]: warnings.warn("Warning: Signal dimensions flipped out. If you have more" " samples than channels, comment this " "line") data = data.T # Variable initialization num_chan = data.shape[1] # Connectivity computation phase_data = np.transpose(np.angle(sp_signal.hilbert(np.transpose(data)))) phase_data = np.ascontiguousarray(phase_data) angles_1 = np.reshape(np.tile(phase_data, (num_chan, 1)), (len(phase_data), num_chan * num_chan), order='F') angles_2 = np.tile(phase_data, (1, num_chan)) pli_vector = abs(np.mean(np.sign(np.sin(angles_1 - angles_2)), axis=0)) pli = np.reshape(pli_vector, (num_chan, num_chan), order='F') plv_vector = np.divide( abs(np.sum(np.exp(1j * (angles_1 - angles_2)), axis=0)), data.shape[0]) plv = np.reshape(plv_vector, (num_chan, num_chan), order='F') imz = np.sin(angles_1 - angles_2) with np.errstate(divide='ignore', invalid='ignore'): wpli_vector = np.divide( abs(np.mean(np.multiply(abs(imz), np.sign(imz)), axis=0)), np.mean(abs(imz), axis=0) ) wpli = np.reshape(wpli_vector, (num_chan, num_chan), order='F') return plv, pli, wpli, def __phase_connectivity_gpu(data): """ This method implements three phase-based connectivity parameters using GPU: PLV, PLI, and wPLI. REFERENCES: PLV: Mormann, F., Lehnertz, K., David, P., & Elger, C. E. (2000). Mean phase coherence as a measure for phase synchronization and its application to the EEG of epilepsy patients. Physica D: Nonlinear Phenomena, 144(3-4), 358-369. PLI: Nolte, G., Bai, O., Wheaton, L., Mari, Z., Vorbach, S., & Hallett, M. (2004). Identifying true brain interaction from EEG data using the imaginary part of coherency. Clinical neurophysiology, 115(10), 2292-2307. wPLI: Vinck, M., Oostenveld, R., Van Wingerden, M., Battaglia, F., & Pennartz, C. M. (2011). An improved index of phase-synchronization for electrophysiological data in the presence of volume-conduction, noise and sample-size bias. Neuroimage, 55(4), 1548-1565. NOTE: PLV is sensitive to volume conduction effects Parameters ---------- data : numpy 2D matrix MEEG Signal. [n_samples x n_channels]. Returns ------- plv : numpy 2D square matrix plv-based connectivity matrix. [n_channels x n_channels]. pli : numpy 2D square matrix pli-based connectivity matrix. [n_channels x n_channels]. wpli : numpy 2D square matrix wpli-based connectivity matrix. [n_channels x n_channels]. """ import tensorflow as tf # Error check if type(data) != np.ndarray: raise ValueError("Parameter data must be of type numpy.ndarray") if data.shape[0] < data.shape[1]: warnings.warn("Warning: Signal dimensions flipped out. If you have more" " samples than channels, comment this " "line") data = data.T # Variable initialization num_chan = data.shape[1] # Connectivity computation phase_data = tf.math.angle(transforms.hilbert(data)) angles_1 = tf.transpose( tf.reshape( tf.transpose(tf.tile(phase_data, (num_chan, 1))), (num_chan * num_chan, len(phase_data))) ) angles_2 = tf.tile(phase_data, (1, num_chan)) pli_vector = tf.math.abs( tf.math.reduce_mean( tf.math.sign( tf.math.sin(tf.math.subtract(angles_1, angles_2))), axis=0)) pli = tf.reshape(pli_vector, (num_chan, num_chan)) plv_vector = tf.math.divide( tf.math.abs( tf.math.reduce_sum( tf.math.exp( tf.math.scalar_mul( 1j, tf.cast( tf.math.subtract(angles_1, angles_2), 'complex64'))), axis=0)), data.shape[0]) plv = tf.reshape(plv_vector, (num_chan, num_chan)) imz = tf.math.sin(tf.math.subtract(angles_1, angles_2)) wpli_vector = tf.math.divide( tf.math.abs(tf.math.reduce_mean( tf.math.multiply( tf.math.abs(imz), tf.math.sign(imz)), axis=0)), tf.math.reduce_mean(tf.math.abs(imz), axis=0)) wpli = tf.reshape(wpli_vector, (num_chan, num_chan)) return plv, pli, wpli,
[docs]def phase_connectivity(data): """ This method implements three phase-based connectivity parameters: PLV, PLI, and wPLI. REFERENCES: PLV: Mormann, F., Lehnertz, K., David, P., & Elger, C. E. (2000). Mean phase coherence as a measure for phase synchronization and its application to the EEG of epilepsy patients. Physica D: Nonlinear Phenomena, 144(3-4), 358-369. PLI: Nolte, G., Bai, O., Wheaton, L., Mari, Z., Vorbach, S., & Hallett, M. (2004). Identifying true brain interaction from EEG data using the imaginary part of coherency. Clinical neurophysiology, 115(10), 2292-2307. wPLI: Vinck, M., Oostenveld, R., Van Wingerden, M., Battaglia, F., & Pennartz, C. M. (2011). An improved index of phase-synchronization for electrophysiological data in the presence of volume-conduction, noise and sample-size bias. Neuroimage, 55(4), 1548-1565. NOTE: PLV is sensitive to volume conduction effects Parameters ---------- data : numpy 2D matrix MEEG Signal. [n_samples x n_channels]. Returns ------- plv : numpy 2D square matrix plv-based connectivity matrix. [n_channels x n_channels]. pli : numpy 2D square matrix pli-based connectivity matrix. [n_channels x n_channels]. wpli : numpy 2D square matrix wpli-based connectivity matrix. [n_channels x n_channels]. """ from medusa import tensorflow_integration # Error check if not np.issubdtype(data.dtype, np.number): raise ValueError('data matrix contains non-numeric values') if tensorflow_integration.check_tf_config(autoconfig=True): plv, pli, wpli, = __phase_connectivity_gpu(data) else: # plv, pli, wpli, = __phase_connectivity_numba(data) plv, pli, wpli, = __phase_connectivity_cpu(data) return plv, pli, wpli,