Creating subplots with plot_connectivity_circle

Hey everyone,

I am trying to create a 3-part plot with mne_connectivity.viz.plot_connectivity_circle using coherence data that I have already processed** - where each subplot would visualize coherence at a different frequency band. So to begin with, I am having trouble with the example here which uses the following:

fig, axes = plt.subplots(1, 3, figsize=(8, 4), facecolor='black',
                         subplot_kw=dict(polar=True))
no_names = [''] * len(label_names)
for ax, method in zip(axes, con_methods):
    plot_connectivity_circle(con_res[method], no_names, n_lines=300,
                             node_angles=node_angles, node_colors=label_colors,
                             title=method, padding=0, fontsize_colorbar=6,
                             ax=ax)

In the example, the 3-part subplot calls on a dict object “con_res.” However this is a collection of 3 arrays collected from some other dataset using 3 methods (I really don’t understand what they’re doing to create it here):

con_methods = ['pli', 'wpli2_debiased', 'ciplv']
con = spectral_connectivity_epochs(
    label_ts, method=con_methods, mode='multitaper', sfreq=sfreq, fmin=fmin,
    fmax=fmax, faverage=True, mt_adaptive=True, n_jobs=1)

# con is a 3D array, get the connectivity for the first (and only) freq. band
# for each method
con_res = dict()
for method, c in zip(con_methods, con):
    con_res[method] = c.get_data(output='dense')[:, :, 0]

So essentially, I want to manually create a dict that contains 3 different arrays that can be called on in the function similar to how they do with (con_res[method],…).

If I replace the dict with a single array (theta, for instance), the code “works” and returns 1 subplot + 2 blank ones. But if I try to add my 3 arrays into a dict manually and then call on it, I recieve the following error:


  File ~\AppData\Local\mne-python\1.4.2_0\lib\site-packages\mne\viz\circle.py:198 in _plot_connectivity_circle
    if con.ndim == 1:

AttributeError: 'dict' object has no attribute 'ndim'

Here is what I have tried:

import numpy as np
import matplotlib.pyplot as plt
import mne
from mne.viz import circular_layout
from mne_connectivity.viz import plot_connectivity_circle
import pandas as pd
    
#excel matrices each with coherence in a single frequency band
dft = pd.read_excel("Theta_Differences.xlsx")
theta=dft.to_numpy()

dfb = pd.read_excel("Beta_Differences.xlsx")
beta=dfb.to_numpy()

dflg = pd.read_excel("Low_Gamma_Differences.xlsx")
low_gamma=dflg.to_numpy()


#Here I try to create a dict containing the 3 arrays
con_bands={"Theta":theta,"beta":beta,"Low Gamma":low_gamma}

#A list of the 8 recorded regions
node_order= ["rACC", "PrL", "cACC", "CA1", "mEC", "OFC", "aPCx", "pPPx"]
label_names = ["rACC", "PrL", "cACC", "CA1", "mEC", "OFC", "aPCx", "pPPx"]
node_angles = circular_layout(label_names, node_order, start_pos=90)

###########################
#Single circle graph (works)
fig, ax = plt.subplots(figsize=(8, 8), facecolor='black',
                       subplot_kw=dict(polar=True))
plot_connectivity_circle(theta, label_names, n_lines=28, node_angles=node_angles, title="Change in Coherence from Baseline (Theta)" )
fig.tight_layout()


#################
##Subplot (Error)

fig, axes = plt.subplots(1, 3, figsize=(8, 4), facecolor='black',
                         subplot_kw=dict(polar=True))
no_names = [''] * len(label_names)
for ax, method in zip(axes, con_bands):
    plot_connectivity_circle(con_bands, no_names, n_lines=28, node_angles=node_angles, padding=0, fontsize_colorbar=6,
                             ax=ax )

I realize this is an embarrassingly bad attempt. But I have pretty much zero python experience, so I’m really just trying one thing after another to see if I can get something to happen. For anyone with time to waste, I am also on discord! Thank you!

The function spectral_connectivity_epochs allows you to compute connectivity using multiple different methods all at once (because this is more efficient than making 3 separate function calls for the 3 methods).

So con_res here basically just splits the output of spectral_connectivity_epochs by putting each of the different method names as keys, and the different method results as values.

I think what’s missing from your attempt is in the for-loop that calls plot_connectivity_circle you need to pass con_bands[method] rather than just con_bands. And while you’re at it, change the looping variable name from method to band (to reflect what you’re doing):

for ax, band in zip(axes, con_bands):
    plot_connectivity_circle(con_bands[band], no_names, n_lines=28, node_angles=node_angles, padding=0, fontsize_colorbar=6,
                             ax=ax )

Thanks so much for the reply! I really appreciate your time!

So oddly enough, I actually tried this! And when I do, I get the first plot. But the second and third are missing. Initially I thought I must’ve had the con_bands[band] part wrong. But I went back and tried running the example with the sample data - and it also is no longer drawing the second or third plots! I receive 1 completed circle graph along with 2 blank circle graphs.

Is something wrong with my MNE library?

I was thinking it may be the library. So I went home and tried it on another PC, and I’m getting the same problem. I receive no errors, so it’s a real head-scratcher

Edit: I’m not sure why, but saving the plot directly to file actually shows all of the plots. It just won’t show up in the plots frame in Spyder (Saving from the plots frame also doesn’t work).

Try adding this to the top of your script:

import matplotlib.pyplot as plt
plt.ion()

that might fix it.

No affect, unfortunately.

For now, I’m at least able to output a few figures (which, honestly, I thought would take me months - not days. So I’m still pretty stoked to get anything).

When I get back to it tomorrow, I’m trying to see if I can change the color of the scale/lines so I can reflect negative numbers (even if it’s not necessarily conventional).

(I feel like you deserve to see them since you helped haha)
All Frequencies
Low Gamma
Theta

1 Like

not sure what’s going wrong; this works for me (yields a figure with 3 circular plots):

import matplotlib.pyplot as plt
import numpy as np
from mne_connectivity.viz import plot_connectivity_circle

rng = np.random.default_rng(seed=73)
plt.ion()

bands = dict(
    alpha=rng.uniform(size=(10, 10)),
    beta=rng.uniform(size=(10, 10)),
    gamma=rng.uniform(size=(10, 10)),
)
node_names = list('abcdefghij')

fig, axs = plt.subplots(1, 3, facecolor='k', subplot_kw=dict(polar=True))

for ax, band in zip(axs, bands):
    plot_connectivity_circle(bands[band], node_names=node_names, title=band, ax=ax)

EDIT: I just saw that you mentioned the Spyder plots pane. I’ll guess that this is the problem. Embedded plot panes in IDEs like Spyder or PyCharm often do funny/custom things to “intercept” matplotlib plots and display them where they want them; unfortunately side effects like this are not uncommon.