10000 [MRG] Allow asymmetric matrices in plot_connectome by NicolasGensollen · Pull Request #2703 · nilearn/nilearn · GitHub
[go: up one dir, main page]

Skip to content

[MRG] Allow asymmetric matrices in plot_connectome #2703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

NicolasGensollen
Copy link
Member

Addresses #1513

Description

This PR proposes to allow asymmetric matrices to be plotted as a directed graph through the plot_connectome function. Previous behaviour was to raise an error.

Example

import numpy as np
from nilearn import datasets, plotting
from nilearn.input_data import NiftiLabelsMasker
from nilearn.connectome import ConnectivityMeasure

yeo = datasets.fetch_atlas_yeo_2011()
data = datasets.fetch_development_fmri(n_subjects=10)
connectome_measure = ConnectivityMeasure(kind='correlation')
masker = NiftiLabelsMasker(labels_img=yeo['thick_17'], standardize=True,
                           memory='nilearn_cache')
time_series = []
for func, confounds in zip(data.func, data.confounds):
    time_series.append(masker.fit_transform(func, confounds=confounds))
correlation_matrices = connectome_measure.fit_transform(time_series)
mean_correlation_matrix = connectome_measure.mean_
coordinates = plotting.find_parcellation_cut_coords(labels_img=yeo['thick_17'])
# Brutal way to get asymmetric matrix...
non_symmetric = np.triu(mean_correlation_matrix)
plotting.plot_connectome(mean_correlation_matrix, coordinates,
                         edge_threshold="90%", title='symmetric')
plotting.plot_connectome(non_symmetric, coordinates,
                         edge_threshold="90%", title='asymmetric')

directed_connectome

Todo

  • Add tests (to be coming soon)
  • Showcase the functionality in an example (I don't think we have asymmetric connectivity measures implemented in Nilearn so far, so not sure if we can build a realistic example here...)

@NicolasGensollen NicolasGensollen self-assigned this Feb 17, 2021
@codecov
Copy link
codecov bot commented Feb 17, 2021

Codecov Report

Merging #2703 (6401b41) into master (8d2c5ac) will decrease coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2703      +/-   ##
==========================================
- Coverage   87.59%   87.58%   -0.01%     
==========================================
  Files         100      100              
  Lines       13171    13155      -16     
  Branches     2555     2559       +4     
==========================================
- Hits        11537    11522      -15     
+ Misses       1026     1025       -1     
  Partials      608      608              
Impacted Files Coverage Δ
nilearn/plotting/img_plotting.py 89.51% <ø> (-0.09%) ⬇️
nilearn/plotting/displays.py 88.96% <100.00%> (+0.20%) ⬆️
nilearn/plotting/__init__.py 78.57% <0.00%> (-7.15%) ⬇️
nilearn/glm/regression.py 73.07% <0.00%> (-2.62%) ⬇️
nilearn/_utils/testing.py 80.00% <0.00%> (-0.46%) ⬇️
nilearn/glm/model.py 78.90% <0.00%> (-0.33%) ⬇️
nilearn/glm/first_level/first_level.py 74.14% <0.00%> (-0.24%) ⬇️
nilearn/datasets/_testing.py 93.67% <0.00%> (-0.20%) ⬇️
nilearn/_utils/helpers.py 100.00% <0.00%> (ø)
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8d2c5ac...d2e3b1c. Read the comment docs.

@bthirion
Copy link
Member

LGTM, thx !
A possible example to get a directed graph in examples would be to estimate lag-1 correlations between regions (some simplistic Granger causality model).

@NicolasGensollen
Copy link
Member Author

Azure failure related to empty arrows crashing for matplotlib pre 3.1 (see: matplotlib/matplotlib#13658)

@NicolasGensollen NicolasGensollen force-pushed the allow-asymmetric-matrices-in-plot_connectome branch from 86ab429 to e1ed9ec Compare February 18, 2021 12:41
@NicolasGensollen
Copy link
Member Author

A possible example to get a directed graph in examples would be to estimate lag-1 correlations between regions (some simplistic Granger causality model).

This might be too simplistic, but maybe something along those lines ?

import numpy as np
from nilearn import datasets, plotting
from nilearn.input_data import NiftiLabelsMasker

def lag_correlation(time_series, lag):
    """Basic home-made lag correlation function."""
    n_subjects = len(time_series)
    n_samples, n_features = time_series[0].shape
    lag_cor = np.zeros((n_subjects, n_features, n_features))
    for subject,serie in enumerate(time_series):
        for i in range(n_features):
            for j in range(n_features):
                lag_cor[subject, i, j] = np.corrcoef(serie[lag:, i], 
                                                     serie[:-lag, j])[0, 1]
    return np.mean(lag_cor, axis=0)

# Get atlas and func data
yeo = datasets.fetch_atlas_yeo_2011()
data = datasets.fetch_development_fmri(n_subjects=10)

# Transform into time series
masker = NiftiLabelsMasker(labels_img=yeo['thick_17'], standardize=True,
                           memory='nilearn_cache')
time_series = []
for func, confounds in zip(data.func, data.confounds):
    time_series.append(masker.fit_transform(func, confounds=confounds))

# Compute node coordinates
coordinates = plotting.find_parcellation_cut_coords(labels_img=yeo['thick_17'])

# Compute lag correlation matrices and plot connectomes
for lag in [1, 10]:
    lag_cor  = lag_correlation(time_series, lag)
    plotting.plot_connectome(lag_cor, coordinates, edge_threshold="90%", 
                             title='Lag{} correlation'.format(lag))

directed_connectome2

@bthirion
Copy link
Member

Thx for the example suggestion.
IMHO it does not really make sense to find lag-10 correlations between areas: those are probably noise... I would only take lag-1, and possibly show it together with the symmetric lag-0 correlation.

@NicolasGensollen
Copy link
Member Author

IMHO it does not really make sense to find lag-10 correlations between areas: those are probably noise... I would only take lag-1, and possibly show it together with the symmetric lag-0 correlation.

Thanks for the comment! I agree and I updated one of the connectome-related examples accordingly.
Here is the link to the modified example built by CircleCI: link

@NicolasGensollen NicolasGensollen changed the title [WIP] Allow asymmetric matrices in plot_connectome [MRG] Allow asymmetric matrices in plot_connectome Feb 19, 2021
@bthirion
Copy link
Member

At least it looks OK to me.

time_series)
mean_empirical_correlation_matrix = empirical_connectome_measure.mean_
lag0_correlation = lag_correlation(time_series, 0)
assert_array_almost_equal(mean_empirical_correlation_matrix,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit weird in an example.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this is probably not super useful in an example.
I simplified this section (see d2e3b1c)

for direction in ['z', 'r', 'y']:
assert(len([patch for patch in ax.axes[direction].ax.patches
if isinstance(patch, FancyArrow)]) ==
np.prod(adjacency_matrix.shape) - 2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not related to this PR ? I'm confused.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am testing that we get the correct number of arrows in the connectome plot when setting some (2) elements of the matrix to zero and for a different display mode. If this is too redundant with other tests added in this PR, I can delete it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, sounds right.

@NicolasGensollen NicolasGensollen force-pushed the allow-asymmetric-matrices-in-plot_connectome branch from 4d67809 to d2e3b1c Compare February 22, 2021 10:46
@NicolasGensollen
Copy link
Member Author

Thanks for the reviews!
Merging.

@NicolasGensollen NicolasGensollen merged commit 647d4c1 into nilearn:master Mar 1, 2021
@NicolasGensollen NicolasGensollen deleted the allow-asymmetric-matrices-in-plot_connectome branch March 1, 2021 10:09
bthirion added a commit to bthirion/nilearn that referenced this pull request May 19, 2021
* 'master' of github.com:nilearn/nilearn:
  Release 0.7.1 (nilearn#2727)
  Add two_sided flag to get_clusters_table (nilearn#2719)
  bugfix resample only if type is not contour or contourf (nilearn#2656)
  Support atlases in plot_carpet (nilearn#2702)
  Fix whatsnew entry with public function reference (nilearn#2716)
  EHN signal.clean standardise option PSC to allow negative mean signal  (nilearn#2714)
  Replace NaNs with zeros in NiftiLabelsMasker (nilearn#2712)
  [MRG] Allow asymmetric matrices in plot_connectome (nilearn#2703)
  [MRG] Mosaic mode of displaying brain images (nilearn#2684)
  Resampling functionality for NeuroVault (nilearn#2696)
  Solving "NiftiMapsMasker and NiftiLabelsMasker cannot transform 3D images" (nilearn#2708)
  Raise warning for FirstLevelModel fit when confounds and design_matrices are both specified (nilearn#2710)
  Fixed numpy warning when img has NaNs. (nilearn#2709)
  [MRG] High variance confounds in maskers (nilearn#2697)
  fix sampling (nilearn#2706)
  [MRG] Handle nans in surf plotting (nilearn#2691)
  [FIX] get_clusters_table: ensure input is 3D and accept filenames (nilearn#2701)
  Warn in nifti masker report when no image provided to fit (nilearn#2694)
  fix for FirstLevelModel compute_contrast for multiple runs with varying matrice size or columns (nilearn#2688)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0