CONN Toolbox

Extract and plot ROI-to-ROI connectivity matrix

February 2017

The CONN toolbox is a very efficient MATLAB-based tool to perform functional connectivity analysis and I've been an enthusiastic user ever since I discovered it. It provides a robust analysis pipeline from raw files to second-level adavanced statistical results as well as a very nice and intuitive GUI - making it one of the best fcMRI toolbox for both beginner and expert. I worked a great deal with it for ROI-to-ROI analysis of within and between network connectivity. One feature that is not (yet) implemented in CONN is the possibility to plot a graphical representation of network connectivity matrix. The purpose of this tutorial is therefore to show how to extract (and export to CSV) connectivity matrix from CONN results folder and then plot them, using either Matlab or Python.

  • A full version of the MATLAB / Python scripts used can be found on my GitHub repository
Salience network connectivity matrices (beta, T and p-values)

ROI.mat structure

CONN ROI.mat file is created when clicking "Results Explorer" in the bottom left of the CONN 2nd-level interface. This MAT structure can be found in the folder /results/secondlevel/FIRSTLEVEL_NAME/GROUP/SESSION/ and contains the following fields (see this post)

  • names: names of the source ROIs
  • h: beta values displayed in CONN 2nd-level interface, which corresponds to the average Fischer transformed pairwise correlations of specified contrast
  • F: statistical values, depending on the statistical test (see statsname field)
  • p: one-tailed p-values

  • 1) Using MATLAB

    Extract connectivity matrix

    The following code extract all the pairwise correlations in the ROI.mat file

    % Define analysis path
    wdir 		= 'C:/Users/Raphael/Desktop/These/conn_example/results/secondlevel';
    corr_net 	= 'Salience';
    corr_group 	= 'AllSubjects';
    corr_run 	= 'rest';
    corr_folder = [ wdir '/' corr_net '/' corr_group '/' corr_run '/' ];
    
    load([corr_folder 'ROI.mat']);
    
    numROI  	= size(ROI, 2);
    corr_name 	= ROI(1).names(1:numROI);
    
    corr_h   	= [];   % Beta value
    corr_F  	= [];   % Statistic value
    corr_p   	= [];   % One-tailed p value
    
    for i = 1:numROI
    	corr_h = [ corr_h ; ROI(i).h(1:numROI) ];
    	corr_F = [ corr_F ; ROI(i).F(1:numROI) ];
    	corr_p = [ corr_p ; ROI(i).p(1:numROI) ];
    end
    

    Export to CSV

    Now we can export it to CSV file (by default in the same folder as ROI.mat file

    % array2table does not work with '-' in var names
    corr_name2 	= strrep(corr_name, '-', '_');
    T_h        	= array2table(corr_h, 'RowNames', corr_name2, 'VariableNames', corr_name2);
    T_F        	= array2table(corr_F, 'RowNames', corr_name2, 'VariableNames', corr_name2);
    T_p        	= array2table(corr_p, 'RowNames', corr_name2, 'VariableNames', corr_name2);
    
    writetable( T_h, [corr_folder 'beta_' corr_net '_' corr_group '_' corr_run '.csv'], 'WriteVariableNames', true, 'WriteRowNames', true, 'delimiter', 'semi' );
    writetable( T_F, [corr_folder 'F_' corr_net '_' corr_group '_' corr_run '.csv'], 'WriteVariableNames', true, 'WriteRowNames', true, 'delimiter', 'semi');
    writetable( T_p, [corr_folder 'p_' corr_net '_' corr_group '_' corr_run '.csv'], 'WriteVariableNames', true, 'WriteRowNames', true, 'delimiter', 'semi');
    

    Statistics

    The following lines compute uncorrected, bonferroni and FDR-corrected p-values

    anti_corr_net = False;
    
    % Case two or several anti-correlated networks (ex: Default and Dorsal Attention)
    if anti_corr_net
        tail      = 'two-sided';
        corr_p    = 2*min(corr_info.corr_p, 1-corr_info.corr_p);
    
    % Case single network
    else
        tail      = 'one-sided';
    
    end
    
    % Compute Bonferroni and FDR correction
    % conn_fdr function is in conn main folder
    alpha_bonf            		= 0.05 / ((numROI)*(numROI-1)/2);
    vector_fdr                      = nonzeros(triu(corr_info.corr_p)');
    vector_fdr(isnan(vector_fdr))   = [];
    corr_p_fdr            		= conn_fdr(vector_fdr);
    
    % WRITE OUTPUT
    fprintf('\nANALYSIS INFO');
    fprintf('\n--------------------------------------');
    fprintf(['\nNetwork:\t ' corr_net]);
    fprintf(['\nGroup:\t\t ' corr_group]);
    fprintf(['\nRun:\t\t ' corr_run]);
    fprintf('\nSTATISTICS');
    fprintf('\n--------------------------------------');
    fprintf([ '\n' num2str(numROI) ' x ' num2str(numROI-1) ' ROIs matrix ; ' tail]);
    fprintf([ '\np-uncorrected:\t\t\t\t\t ' num2str(numel(corr_p(corr_p <= 0.05))/2)  ]);
    fprintf([ '\np-bonferroni (alpha = ' num2str(round(alpha_bonf, 5)) '):\t ' num2str(numel(corr_p(corr_p <= alpha_bonf))/2) ]);
    fprintf([ '\np-FDR corrected:\t\t\t\t ' num2str(numel(corr_p_fdr(corr_p_fdr <= 0.05))) ]);
    fprintf('\n--------------------------------------\n');
    
    MATLAB Output:
    ANALYSIS INFO
    --------------------------------------
    Network:	 DMN
    Group:		 Controls(1).Patients(-1)
    Run:		 rest
    STATISTICS
    --------------------------------------
    5 x 4 ROIs matrix ; one-sided
    p-uncorrected:                  4
    p-bonferroni (alpha = 0.005):   1
    p-FDR corrected:                1
    --------------------------------------
    

    Plotting brain connectivity matrix

    Once we extracted and exported the connectivity matrix in text format, we can plot it using Matlab imagesc command. I will detail here for beta values (corr_h matrix) but if you want to plot F or p values you can check the full script on my GitHub repository

    % Remove upper triangle + diagonal
    corr = tril(corr, -1)
    
    % Start plotting
    fig = figure;
    set(gcf,'Units','inches', 'Position',[0 0 6 4])
    
    im = imagesc(corr, clim );
    
    clim = [ 0 1 ];
    colormap(flipud(hot(10)));
    
    h = colorbar('eastoutside');
    xlabel(h, 'h', 'FontSize', 14);
    
    
    % Title, axis
    title('Salience Network', 'FontSize', 14);
    set(gca, 'XTick', (1:numROI));
    set(gca, 'YTick', (1:numROI));
    set(gca, 'Ticklength', [0 0])
    grid off
    box off
    
    % Labels
    set(gca, 'XTickLabel', corr_name, 'XTickLabelRotation', 0);
    set(gca, 'YTickLabel', corr_name);
    

    With some adaptation, the previous code also works for between-network connectivity matrix (blue denotes negative correlations)


    2) Using Python

    The previous connectivity matrices can also be extracted and plot using Python (requires numpy, scipy, pandas and seaborn packages). Apart form being free, Python has several advantages compared to Matlab, with notably the possibility to emphasize networks separation (see example below), and to annotate values in each cell of the heatmap plot. The only trick is in the importation and conversion of the original MAT file to a Pandas dataframe.

    Code:
    import numpy as np
    import pandas as pd
    import seaborn as sns
    import matplotlib.pyplot as plt
    import os
    import scipy.io
    
    sns.set(style="white", context='paper', font_scale=1, font='monospace')
    
    def extract_conn_correl_mat():
    
        # Analysis Information
        wdir             = 'C:/Users/Raphael/Desktop/These/CONN_Club_Neuro/Conn_ClubNeuro_Example/results/secondlevel'
        correl_net       = 'Salience'
        correl_group     = 'AllSubjects'
        correl_run       = 'rest'
        correl_type      = 'p'
        correl_folder    = os.path.join(wdir, correl_net, correl_group, correl_run )
    
        # Load .mat file
        mdata           = scipy.io.loadmat(os.path.join(correl_folder, 'ROI.mat'))
        mdata           = mdata['ROI']
        mdtype          = mdata.dtype
        ndata           = {n: mdata[n] for n in mdtype.names}
        mcol            = ['names', 'h', 'F', 'p']
    
        mcorr           = pd.DataFrame(np.concatenate([ndata[c] for c in mcol], axis=0)).transpose()
        mcorr.columns   = mcol
        mcorr.names     = np.concatenate(mcorr.names[0][0])
        mcorr.names     = mcorr.names.str.split('.').str.get(0)
    
        # Extract selected values
        if correl_type == 'beta':
            corr = pd.DataFrame(np.concatenate([mcorr.h[c] for c in mcorr.h.keys()], axis=0 ), index=mcorr.names)
        elif correl_type == 'F':
            corr = pd.DataFrame(np.concatenate([mcorr.F[c] for c in mcorr.F.keys()], axis=0 ), index=mcorr.names)
        elif correl_type == 'p':
            corr = pd.DataFrame(np.concatenate([mcorr.p[c] for c in mcorr.p.keys()], axis=0 ), index=mcorr.names)
    
        corr            = corr.iloc[:, 0:corr.shape[0]]
        corr.columns    = mcorr.names
    
        # Export to csv
        corr.to_csv(os.path.join(correl_folder, correl_type + '_' + correl_net + '_' + correl_group + '_' + correl_run + '_corr_mat.csv'), sep=';', decimal='.')
    
        # Plot
        plot_correl_matrix(corr, correl_type, correl_net, correl_group, correl_run, correl_folder )
    
    def plot_correl_matrix(corr, correl_type, correl_net, correl_group, correl_run, correl_folder ):
    
        # Mask diagonal
        mask = np.zeros_like(corr, dtype=np.bool)
        mask[np.triu_indices_from(mask, k=1)] = True
    
        # Define plot properties
        if correl_type == 'F':
            vmin    = 0
            vmax    = 10
            annot   = False
            cmap    = "YlOrRd"
    
        elif correl_type == 'beta' :
            vmin    = 0
            vmax    = 1
            annot   = True
            cmap    = "YlOrRd"
    
        elif correl_type == 'p' :
            vmin    = 0
            vmax    = 0.1
            annot   = False
            cmap    = "YlOrRd_r"
    
        f, ax = plt.subplots()
        sns.heatmap(corr, mask=mask, vmin=vmin,  vmax=vmax, square=True, cmap=cmap, annot=annot, cbar=True, xticklabels=False, yticklabels=True, linewidths=.0 )
    
        plt.xticks(rotation=0)
        plt.ylabel('')
        plt.xlabel('')
        plt.title(correl_type + '_' + correl_net + '_' + correl_group + '_' + correl_run)
    
    	# Emphasize networks separation
    	#    networks = np.array(pd.read_csv(os.path.join(correl_folder, 'networks_level_values.csv')))
    	#    for i, network in enumerate(networks):
    	#        if i and network != networks[i - 1 ]:
    	#            ax.axhline(len(networks) - i, c="w")
    	#            ax.axvline(i, c="w")
    	#            f.tight_layout()
    
        plt.savefig(os.path.join(correl_folder,  correl_type + '_' + correl_net + '_' + correl_group + '_' + correl_run + '.png'), dpi=300)
    
    if __name__ =='__main__':
    
        extract_conn_correl_mat()