How to compute EEG connectivity and visualize it using a circular graph

The objective is to compute EEG connectivity and visualize it using a circular graph.

Thanks to the documentation, the following code was drafted to achieve this objective.

However, I am not sure whether the node order printed on the circular graph, is tally with the connectivity array produced from the ‘connectivity_methods’ output.

I really appreciate if someone can confirm whether the following code is actually answering the objective, specifically the mapping of node order to connectivity array produced from the ‘connectivity_methods’ output.

import numpy as np
import mne
from mne.connectivity import spectral_connectivity
from mne.viz import circular_layout, plot_connectivity_circle
import matplotlib.pyplot as plt


# Generate data
np.random.seed ( 42 )

label_names = ['FP1', 'FP2', 'F3', 'F4', 'F7', 'F8', 'C3', 'C4',
               'T3', 'T4', 'O1', 'O2']
lh_labels = ['FP1', 'F7', 'F3','C3','T3','O1']
rh_labels = ['FP2', 'F8', 'F4','C4','T4','O2']


n_epochs = 5
n_channels = len(label_names)
n_times = 1000
data = np.random.rand ( n_epochs, n_channels, n_times )
# Set sampling freq
sfreq = 250  # A reasonable random choice



# 10Hz sinus waves with random phase differences in each channel and epoch
# Generate 10Hz sinus waves to show difference between connectivity
# over time and over trials. Here we expect con over time = 1
for i in range ( n_epochs ):
        for c in range ( n_channels ):
            wave_freq = 10
            epoch_len = n_times / sfreq
            # Introduce random phase for each channel
            phase = np.random.rand ( 1 ) * 10
            # Generate sinus wave
            x = np.linspace ( -wave_freq * epoch_len * np.pi + phase,
                              wave_freq * epoch_len * np.pi + phase, n_times )
            data [i, c] = np.squeeze ( np.sin ( x ) )



info = mne.create_info(ch_names=label_names,
                       ch_types=['eeg'] * len(label_names),
                       sfreq=sfreq)


epochs = mne.EpochsArray(data, info)

# Define freq bands
Freq_Bands = {"delta": [1.25, 4.0],
              "theta": [4.0, 8.0],
              "alpha": [8.0, 13.0],
              "beta": [13.0, 30.0],
              "gamma": [30.0, 49.0]}


n_freq_bands = len ( Freq_Bands )
# Convert to tuples for the mne function
fmin = tuple ( [list ( Freq_Bands.values () ) [f] [0] for f in range ( len ( Freq_Bands ) )] )
fmax = tuple ( [list ( Freq_Bands.values () ) [f] [1] for f in range ( len ( Freq_Bands ) )] )

# Connectivity methods
connectivity_methods = ["plv"]
n_con_methods = len ( connectivity_methods )

# # Calculate PLV and wPLI - the MNE python implementation is over trials
con, freqs, times, n_epochs, n_tapers = spectral_connectivity (
    epochs, method=connectivity_methods,
    mode="multitaper", sfreq=sfreq, fmin=fmin, fmax=fmax,
    faverage=True, verbose=0 )



node_order = lh_labels +rh_labels # Is this order tally with the con arrangement?
node_angles = circular_layout ( epochs.ch_names, node_order, start_pos=90,
                                group_boundaries=[0, len ( epochs.ch_names ) // 2] )

conmat = con [:, :, 0]
fig = plt.figure ( num=None, figsize=(8, 8), facecolor='black' )
plot_connectivity_circle ( conmat, epochs.ch_names, n_lines=300,
                           node_angles=node_angles,
                           title='All-to-All Connectivity '
                                 'Condition (PLI)_Delta', fig=fig )

Hi @balandongiv ,

For plot_connectivity_circle it is important that the list of node names passed corresponds to the order of the nodes in the connectivity matrix. As long as this is provided correctly, you may change the node angles as you wish.

Your code provides the correct results since the connectivity matrix conmat has the same order as label_names or epochs.ch_names. You can change node_order depending on how you want it arranged, try node_order = lh_labels + rh_labels[::-1].

Cheers !

1 Like