Generate laterality indices

Import Python packages

In [1]:
from fsl.wrappers import fslstats
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
from nilearn import image, plotting
from sklearn import preprocessing
from scipy import ndimage, stats
from tqdm.notebook import trange, tqdm

import itertools
import os
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import re
import seaborn as sns

matplotlib.rcParams.update({'figure.max_open_warning': 0})

os.environ['FSLDIR'] = '/usr/local/fsl'

%load_ext line_profiler

Variables

Dataset

In [2]:
# Dataset name
dataset_name = '125_MAESTRO_Praxis-Lang_LIs'

# Subject/project_handedness
subject_conditions_regex='/[0-9][0-9][0-9]_[A-Z][A-Z][A-Z][A-Z]/|[0-9]-[0-9]_[A-Z][A-Z]'

Andreas Horn's ROIs -- HCP MMP atlas

In [3]:
# ROIs folder
roi_dir = 'Horn_MMP_HCP_atlas'

atlas_filename = 'MMP_in_MNI_corr_resampled_2mm_91x109x91.nii.gz'
labels_filename = 'HCPMMP1_on_MNI152_ICBM2009a_nlin_left-right.txt'

n_rois_per_hemisphere = 180

picks = [10, 11, 12, 15, 17, 18, 22, 29, 43, 45, 47, 48, 49, 50, 56,
         60, 63, 74, 75, 78, 79, 80, 81, 82, 83, 84, 95, 96, 97, 108,
         109, 111, 116, 117, 130, 137, 138, 139, 140, 141, 144, 145,
         148, 149, 150, 151, 157, 169, 171, 179]
         
rois_selection = ['PF', 'PFt', 'PFm', '44', '45', '6r', 'PHA3', 'AIP', 'IPS1', 'IP2', 'LIPv', 'V1']
        
# For printing additional information set this to `1` or `True`
# However, it may increase time for generating the output.
verbose = False

# Visualize ROIs or not
plots = False

input_dir = os.path.join('input_paths', dataset_name)
base_output_dir = os.path.join('results', dataset_name)
output_dir = os.path.join('results', dataset_name, roi_dir)

# Input files
# There are two *.txt files containing lists of NIfTI files that are inputs for LI analysis.
lists_of_inputs = {'praxis': os.path.join(input_dir, 'praxis-cope_1.txt'),
                   'language': os.path.join(input_dir, 'language-cope_3.txt')}

atlas_filepath = os.path.join('ROIs', roi_dir, atlas_filename)
labels_filepath = os.path.join('ROIs', roi_dir, labels_filename)

skills = ['praxis', 'language']
measures = ['voxels', 'intensities']
measures_explicit = {'voxels': 'Voxel count', 'intensities': 'Intensities'}
desc_stats = ['mean', 'sd']
measure_and_stats = ['%s_%s' % j for j in list(itertools.product(measures, desc_stats))] + ['missing_data',]
percents = [90, 80, 70, 60, 50, 40]

# Function for creating directories
# `Verbose` is taken from a global variable
def create_dir(directory, verbose=verbose):
    try:
        os.mkdir(directory)
        if verbose:
            print('Directory created: %s' % directory)
    except:
        if verbose:
            print('Parent directory doesn\'t exist or subdirectory already exists: %s' % directory)

Automatically generate output directories.

In [4]:
create_dir(base_output_dir)
create_dir(output_dir)

for subdir in ['correlations', 'figures', 'laterality_indices']:
    dir_path = os.path.join(output_dir, subdir)
    create_dir(dir_path)

for format_dir in  ['CSV', 'Excel']:
    dir_path = os.path.join(output_dir, 'laterality_indices', format_dir)
    create_dir(dir_path)

Get lists of inputs

In [5]:
raw_inputs_dfs = {}

for skill in lists_of_inputs.keys():
    if verbose:
        print('')
        print('--------')
        print(skill)
        print(lists_of_inputs[skill])
        print('---')

    raw_inputs_dfs[skill] = pd.read_csv(lists_of_inputs[skill], header=None)
    
    if verbose:
        print(raw_inputs_dfs[skill])
        print(raw_inputs_dfs[skill][0][0])

With regex, get subject codenames

Subject codename is, e.g.: 140_CISN

In [6]:
subject_info = {}
subject_filepaths = {}

for skill in lists_of_inputs.keys():
    
    subject_info[skill] = pd.DataFrame()

    handedness_codes = {'RH': 'right-handed',
                        'LH': 'left-handed',
                        'BH': 'both-handed'}

    for input_file in raw_inputs_dfs[skill][0]:
        sub_conditions = re.findall(subject_conditions_regex, input_file)
        if verbose:
            print('Sub conditions: %s' % sub_conditions)
        project, handedness = sub_conditions[0].split('_')
        if verbose:
            print('Project #: %s; Handedness: %s' % (project, handedness))
        project = project[0]
        handedness = handedness_codes[handedness]
        subject_info[skill] = subject_info[skill].append({'Subject_codename' : re.sub('/', '', sub_conditions[1]),
                                                          'Project_no' : project,
                                                          'Handedness': handedness,
                                                          'Input_filepath': input_file} , ignore_index=True)

    subject_info[skill] = subject_info[skill].set_index('Subject_codename')
    if verbose:
        print('')
        print('--------')
        print('Generic info')
        print(skill)
        print(subject_info[skill])
    
    # Just paths, and subjects as indices
    subject_filepaths[skill] = subject_info[skill]['Input_filepath']
    if verbose:
        print('')
        print('--------')
        print('Paths only')
        print(skill)
        print(subject_filepaths[skill])

Dictionary containing data frames with laterality indices

In [7]:
lis_output = {}
measures_output = {}

for skill in skills:
    lis_output[skill] = {}
    measures_output[skill] = {}
    for measure_stat in measure_and_stats:
        lis_output[skill][measure_stat] = subject_info[skill].copy()
        measures_output[skill][measure_stat] = {}
        measures_output[skill][measure_stat]['left'] = subject_info[skill].copy()
        measures_output[skill][measure_stat]['right'] = subject_info[skill].copy()

Prepare atlas data

Visualize the atlas

In [8]:
plotting.plot_roi(atlas_filepath)
plt.show()

Get information about the shape of the data in the atlas.

In [9]:
atlas_img = image.load_img(atlas_filepath)
atlas_data = atlas_img.get_fdata()
atlas_data.shape
Out[9]:
(91, 109, 91)

Read labels from a file and preview the list.

In [10]:
labels = pd.read_csv(labels_filepath, index_col=0, sep='\t', header=None)
labels = pd.Series(labels[1], index=labels.index, name='Labels')
# Depending on the input file, there may be indexing, e.g, 1-180 & 200-360.
# Other values are NAs, hence can be removed.
labels = labels[labels != 'na']
labels
Out[10]:
0
1         V1_ROI
2        MST_ROI
3         V6_ROI
4         V2_ROI
5         V3_ROI
         ...    
376    STSva_ROI
377     TE1m_ROI
378       PI_ROI
379    a32pr_ROI
380      p24_ROI
Name: Labels, Length: 360, dtype: object

Procedure for calculating LIs

Pseudocode of the procedure

Loading mask was prioritized over, e.g., skill type (praxis/language).

In other words, once the mask data was loaded, all LIs were extracted from it.

Detailed procedure:

 0. Define percentage thresholds
 1. Load Horn's ROIs
 2. For each ROI:
     A. Get masks: left hemisphere, right hemisphere, reference mask;
     B. For each subject:
         a. For each skill (praxis, language):
             alpha. Check how many zero-value voxels are there (`missing values`)
             beta. Get Z-max from reference mask
             gamma. Make sure that z-max is not an outlier
             delta. For measures (n_voxels, intensities):
                 * For each threshold:
                      - Multiply percent per Z-max (get threshold value)
                      - For each hemisphere:
                          + Count voxels above threshold
                          + Get mean value (intensity) above the threshold
                      - Calculate LIs: (m_l - m_r) / (m_l + m_r) * 100
                 * Average LI for voxel counts for thresholds
                 * SD of LIs of voxel counts for thresholds
                 * Average LI for voxel intensities (values) for thresholds
                 * SD of LIs of voxel intensities (values) for thresholds

 3. Save results (For each skill (praxis, language)):
     A. For measures (voxels, intensities):
         a. For stats (mean, sd):
             alpha. Save results

In the cell below, the above procedure was implemented in Python-is-an-executable-pseudocode manner.

In [11]:
class Mask(dict):
    def __init__(self, mask_type, atlas_img, index, roi_name, index_contralateral=None):
        super().__init__()
        
        self.mask_type = mask_type
        
        self.roi_name = roi_name
        self.atlas_img = atlas_img
        self.atlas_data = atlas_img.get_fdata()
        
        self.index = index
        self.index_contralateral = index_contralateral
        
        self.mask_data = self._get_mask_data()
        self.mask_img = self._get_mask_img()
        
    def count_voxels(self, thr_value):
        n_voxels = np.sum(self.zstat_data[self.mask_data]>thr_value)
        super().__setitem__('voxels', n_voxels)
        
    def get_percent_zero(self):
        # Count voxels with 0.0 value within the mask
        n_zero_voxels = np.sum(self.zstat_data[self.mask_data]==0)
        # Get ratio of missing values
        percent_zero = n_zero_voxels/np.sum(self.mask_data)*100
        return percent_zero
        
    def get_value(self, thr_value):

        # Intensity (values) inside a mask
        intensities_inside_mask = self.zstat_data[self.mask_data]
        # Above some threshold
        above_thr = intensities_inside_mask[intensities_inside_mask>thr_value]
        
        # Check if there are actually any intensities (values) above the threshold.
        # If not, np.mean() would return NaN
        if len(above_thr) != 0:
            # Average value inside mask, above threshold
            intensities = np.mean(above_thr)
        else:
            intensities = 0

        super().__setitem__('intensities', intensities)

    def plot_roi(self):
        # Try to use two masks, else use just one (left xor right)
        try:
            if index_contralateral is not None:
                plotting.plot_roi(self.mask_img, title=('ref_%s' % self.roi_name))
        except NameError:
            plotting.plot_roi(self.mask_img, title=('#%s %s_%s' % (self.index, self.mask_type, self.roi_name)))
    
    def set_zstat_data(self, zstat_data):
        self.zstat_data = zstat_data
    
    def get_zmax(self):
        return self.zstat_data[self.mask_data].max()
    
    def get_zmax_outlier_factor(self):
        return None
    
    def _get_mask_data(self):
        mask_data = np.zeros(self.atlas_img.shape)
        
        # Try to use two masks, else use just one (left xor right)
        try:
            mask_data[self.atlas_data==self.index] = 1
            mask_data[self.atlas_data==self.index_contralateral] = 1
        except NameError:
            mask_data[self.atlas_data==self.index] = 1
            
        return mask_data.astype('bool')
    
    def _get_mask_img(self):
        return image.new_img_like(self.atlas_img, self.mask_data, self.atlas_img.affine)



class Masks(dict):
    def __init__(self, atlas_img, index_left_hemi, index_right_hemi, roi_name):
        '''
        ref_img is reference image for data shape, it IS NOT
                `reference` in a sense of the two masks joined
                together
        '''
        super().__init__()
        
        self.m_l = Mask('left', atlas_img, index_left_hemi, roi_name)
        self.m_r = Mask('right', atlas_img, index_right_hemi, roi_name)
        self.m_ref = Mask('reference', atlas_img, index_left_hemi, roi_name, index_right_hemi)
        
        super().__setitem__('left', self.m_l)
        super().__setitem__('right', self.m_r)
        super().__setitem__('reference', self.m_ref)
        
    def plot_rois(self):
        self.m_l.plot_roi()
        self.m_r.plot_roi()
        self.m_ref.plot_roi()
        
        plt.show()
    
    def set_zstat_data(self, input_path):
        
        zstat_img = image.load_img(input_path)
        zstat_data = zstat_img.get_fdata()
        
        self.m_l.set_zstat_data(zstat_data)
        self.m_r.set_zstat_data(zstat_data)
        self.m_ref.set_zstat_data(zstat_data)
        
def calculate_laterality_indices():
    
    t = trange(1, len(labels[:n_rois_per_hemisphere])+1, desc='ROI', leave=True)
    # 2. For each ROI: 
    for index_left_hemi in t:

        # 1-180 are left hemisphere ROIs
        # 200-380 are right hemisphere ROIs
        roi_name = re.sub('_ROI', '', labels[index_left_hemi])

        status = 'ROI #%s/%s' % (index_left_hemi, n_rois_per_hemisphere)
        t.set_description(status)
        # to show immediately the update
        t.refresh() 

        # Write to log
        with open('logs/LI_progress.txt', 'w') as writer:
            writer.write(status)

        index_right_hemi = index_left_hemi + 200

        # A. Get masks: left hemisphere, right hemisphere, reference mask;
        masks = Masks(atlas_img, index_left_hemi, index_right_hemi, roi_name)
        if plots:
            masks.plot_rois()

        # B. For each subject:

        # Get any skill to retrieve subjects
        for subject in subject_filepaths[list(subject_filepaths.keys())[0]].index:

            if verbose:
                print('Subject: %s' % subject)

            # a. For each skill (praxis, language):
            for skill in lists_of_inputs.keys():
                
                if verbose:
                    print('Skill: %s' % skill)

                # Get input path
                input_path = subject_filepaths[skill].loc[subject]
                masks.set_zstat_data(input_path)
                
                if verbose:
                    print('Input path: %s' % input_path)
                    
                # alpha. Check how many zero-value voxels are there (`missing values`)
                lis_output[skill]['missing_data'].loc[subject, roi_name] = masks['reference'].get_percent_zero()

                # beta. Get Z-max from reference mask
                z_max = masks['reference'].get_zmax()
                if verbose:
                    print('Z-max: %s' % z_max)

                # gamma. Make sure that z-max is not an outlier

                # For that calculate Z-max's SD. Later these SD's will be
                # plotted on a graph to detect potential outliers.
                z_max_sd = masks['reference'].get_zmax_outlier_factor()

                # delta. For measures (voxels, intensities):

                # Prepare dictionary for the measures
                lis = {}
                for measure in measures:
                    
                    if verbose:
                        print('Measure: %s' % measure)
                
                    # Prepare list to append to
                    lis[measure] = []
                    thr_results = {'left': [], 'right': []}

                    # * For each threshold:
                    for thr_percent in percents:
                        
                        if verbose:
                            print('Thr: %s' % thr_percent)

                        # - Multiply percent per Z-max (get threshold value)
                        thr_value = z_max * (thr_percent / 100.0)

                        # - For each hemisphere:
                        for hemisphere in ('left', 'right'):
                            # + Count voxels above threshold
                            masks[hemisphere].count_voxels(thr_value)
                            # + Get mean value above the threshold
                            masks[hemisphere].get_value(thr_value)

                        # - Calculate LIs: (m_l - m_r) / (m_l + m_r) * 100:
                        # I.e., masks[hemisphere][measure]
                        m_l = masks['left'][measure]
                        m_r = masks['right'][measure]
                        
                        # Save to left-right output
                        thr_results['left'].append(m_l)
                        thr_results['right'].append(m_r)

                        if verbose:
                            print('m_l: %s' % m_l)
                            print('m_r: %s' % m_r)                        

                        # Prevent division by 0 (that generates NaNs)
                        if (m_l + m_r) != 0:
                            li = (m_l - m_r) / (m_l + m_r) * 100
                        else:
                            li = 0
                        lis[measure].append(li)
                        if verbose:
                            print('LI: %s' % li)

                    # Note, has to use specific .loc way to get Frame's view, not copy,
                    # see: https://stackoverflow.com/a/53954986/8877692
                    # * Average LI for voxel counts for thresholds
                    # * Average LI for voxel intensities for thresholds
                    average = np.mean(lis[measure])
                    if verbose:
                        print('Average LI: %s' % average)
                    lis_output[skill]['%s_mean' % measure].loc[subject, roi_name] = average

                    # * SD of LIs of voxel counts for thresholds
                    # * SD of LIs of voxel intensities for thresholds
                    deviation = np.std(lis[measure])
                    if verbose:
                        print('LI deviation: %s' % deviation)
                    lis_output[skill]['%s_sd' % measure].loc[subject, roi_name] = deviation
                    
                    # `Raw` laterality indices, for each hemishphere
                    for hemishphere in ('left', 'right'):
                        measures_output[skill]['%s_mean' % measure][hemishphere].loc[subject, roi_name] = np.mean(thr_results[hemisphere])
                        measures_output[skill]['%s_sd' % measure][hemishphere].loc[subject, roi_name] = np.std(thr_results[hemisphere])

# To time-profile the function use:
# %lprun -f calculate_laterality_indices calculate_laterality_indices()
calculate_laterality_indices()

In [12]:
def save_results():
    
    ######################
    # Laterality indices
    excel_output_path = os.path.join(output_dir, 'laterality_indices/Excel/%s-%s.xlsx' % (dataset_name, roi_dir))

    with pd.ExcelWriter(excel_output_path) as writer:
        # 3. Save results as CSV files (For each skill (praxis, language)):
        for skill in skills:

            # gamma. For measures (voxels, intensities):
            for measure in measures:

                # For stats (mean, sd):
                for stat in desc_stats:

                    df_name = '%s_%s_%s' % (skill, measure, stat)

                    csv_output_path = os.path.join(output_dir, 'laterality_indices/CSV', '%s.csv' % df_name)

                    df = lis_output[skill]['%s_%s' % (measure, stat)]

                    # As CSV
                    # CSV states for comma separated value
                    df.to_csv(csv_output_path, float_format='%.3f')

                    
                    # As Excel spreadsheet
                    df.to_excel(writer, sheet_name=df_name, float_format='%.3f')

                    if verbose:
                        print(df.mean().head())

                        print('============================')
                        print('Result saved to: %s' % csv_output_path)
        print('')
        print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++')
        print('LIs save to excel file as: %s' % excel_output_path)

    #################
    # `Raw` measures
    excel_output_path = os.path.join(output_dir, 'laterality_indices/Excel/raw_%s-%s.xlsx' % (dataset_name, roi_dir))

    with pd.ExcelWriter(excel_output_path) as writer:
        for skill in skills:
            for measure in measures:
                for stat in desc_stats:
                    for hemishphere in ('left', 'right'):

                        df_name = '%s_%s_%s_%s' % (skill, measure, stat, hemishphere)

                        df = measures_output[skill]['%s_%s' % (measure, stat)][hemishphere]

                        # As Excel spreadsheet
                        df.to_excel(writer, sheet_name=df_name, float_format='%.3f')
                        
                        if verbose:
                            print(df.mean().head())
        print('')
        print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++')
        print('`Raw` measures save to excel file as: %s' % excel_output_path)

# For code time profiling add:
# %lprun -f save_results save_results() 
save_results() 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
LIs save to excel file as: results/125_MAESTRO_Praxis-Lang_LIs/Horn_MMP_HCP_atlas/laterality_indices/Excel/125_MAESTRO_Praxis-Lang_LIs-Horn_MMP_HCP_atlas.xlsx

++++++++++++++++++++++++++++++++++++++++++++++++++++++++
`Raw` measures save to excel file as: results/125_MAESTRO_Praxis-Lang_LIs/Horn_MMP_HCP_atlas/laterality_indices/Excel/raw_125_MAESTRO_Praxis-Lang_LIs-Horn_MMP_HCP_atlas.xlsx

Statistics

Descriptive statistics

Prepare Series for praxis and language

In [13]:
# From each DataFrame drop 'Handedness', 'Input_filepath', 'Project_no' columns.
# That will leave only ROIs, thus numeric values (voxel count or intensities).
def drop_non_roi_columns(df):
    return df.drop(['Handedness', 'Input_filepath', 'Project_no'], axis=1)


# Output minus metadata columns
dfs_laterality_indices = {}

for measure in measures:
    
    dfs_laterality_indices[measure] = {}
    
    for skill in skills:
        # Disregard standard deviations, focus on means
        roi_data = drop_non_roi_columns(lis_output[skill]['%s_mean' % measure])

        dfs_laterality_indices[measure][skill] = roi_data

dfs_laterality_indices
Out[13]:
{'voxels': {'praxis':                          V1         MST          V6          V2          V3  \
  Subject_codename                                                              
  011_RZJA         -21.283267   53.080906   81.493506  -43.974554  -12.227145   
  012_OHPA          76.266056   14.351852   93.245614   -1.059588   73.663168   
  014_WKFP          43.542766   86.319444   -2.827208   62.753605   78.696748   
  015_SASN          14.592226   36.046176   74.562012  -56.935881   64.453860   
  016_NKMA          68.670748  100.000000   99.659864  -61.749167  -30.971105   
  ...                     ...         ...         ...         ...         ...   
  137_RKPW         -92.062131  -79.246795   89.681210 -100.000000  -60.168287   
  138_GZAA           1.888083   20.691148  -83.234048  -30.557167  -23.420676   
  139_SKAN         -63.378960  100.000000  100.000000  -85.813492  100.000000   
  140_CISN          36.724138   85.833333  -35.963356   83.550014   96.132700   
  141_SAKD          25.068310   93.333333   30.710415  -32.960273  -64.228048   
  
                            V4          V8          4         3b         FEF  \
  Subject_codename                                                             
  011_RZJA           69.507625   56.358280  79.708527  66.068951   62.761057   
  012_OHPA          -97.564103 -100.000000 -73.380901   2.910798 -100.000000   
  014_WKFP           93.759087   88.357236  18.306497  11.205059  -57.927842   
  015_SASN           60.792826   34.177062  47.834870  25.815586   83.875846   
  016_NKMA           91.179368   -7.268519  66.725465  84.769946   94.924326   
  ...                      ...         ...        ...        ...         ...   
  137_RKPW          -96.543210    0.000000  16.994484  70.779164  -97.785548   
  138_GZAA           83.970136 -100.000000 -43.767732  30.973857  100.000000   
  139_SKAN           93.692968  100.000000  51.019986  68.377715  100.000000   
  140_CISN          100.000000    0.000000 -21.415355  25.887142  100.000000   
  141_SAKD          -61.111111  100.000000  44.003271  23.079653  -93.722944   
  
                    ...        p47r  TGv       MBelt       LBelt          A4  \
  Subject_codename  ...                                                        
  011_RZJA          ...   99.616858  0.0  -81.548531  -43.666912   68.605294   
  012_OHPA          ...   96.969697  0.0  -84.055556 -100.000000 -100.000000   
  014_WKFP          ...  -83.333333  0.0   39.656849   84.775219   99.024390   
  015_SASN          ...  100.000000  0.0  -75.334425   55.766296   42.019704   
  016_NKMA          ...  100.000000  0.0  -44.782902  -20.709402   96.396396   
  ...               ...         ...  ...         ...         ...         ...   
  137_RKPW          ...  100.000000  0.0  -83.996463  -95.833333  -81.094901   
  138_GZAA          ...  -84.673203  0.0   29.567256  -57.407051  -57.807431   
  139_SKAN          ...  100.000000  0.0   98.039216  -93.602694  -23.316408   
  140_CISN          ...  100.000000  0.0  100.000000  100.000000  100.000000   
  141_SAKD          ... -100.000000  0.0  -12.923280  -71.510513  -45.848488   
  
                         STSva        TE1m          PI       a32pr         p24  
  Subject_codename                                                              
  011_RZJA         -100.000000 -100.000000 -100.000000  -85.858586   93.487773  
  012_OHPA          -61.203277  -94.666667   17.345726    0.000000    0.000000  
  014_WKFP           98.701299   97.033296   95.970395  -45.353535   92.094017  
  015_SASN           90.644193  100.000000   93.005952    0.000000    0.000000  
  016_NKMA          -76.226204 -100.000000   41.815541  100.000000  100.000000  
  ...                      ...         ...         ...         ...         ...  
  137_RKPW          100.000000   64.444444  -33.888889  -72.142857  -83.737908  
  138_GZAA         -100.000000 -100.000000  -39.496951   83.443223  -90.740741  
  139_SKAN          100.000000  100.000000    0.000000  100.000000    0.000000  
  140_CISN         -100.000000  100.000000    0.000000    0.000000    0.000000  
  141_SAKD         -100.000000   95.258710  -69.329574   43.492063   43.083353  
  
  [125 rows x 180 columns],
  'language':                           V1         MST          V6         V2         V3  \
  Subject_codename                                                             
  011_RZJA          -58.142048  -33.968254   80.056980  13.084075 -51.875464   
  012_OHPA         -100.000000    0.808967  -15.703804 -86.703279 -77.212032   
  014_WKFP          -29.559883  -32.777778  -73.311605 -71.092550 -41.771388   
  015_SASN          -78.488705  100.000000  100.000000  48.906905 -23.954909   
  016_NKMA          -44.083061  -76.405816  100.000000  26.625180  50.629465   
  ...                      ...         ...         ...        ...        ...   
  137_RKPW            3.604163    0.000000   89.323671  33.821146  11.065307   
  138_GZAA           -4.791819  -11.111111  100.000000  -1.878684  41.187603   
  139_SKAN           28.711699  100.000000  -41.093474  13.107497  84.788610   
  140_CISN           46.214127 -100.000000  -57.862352  50.122603  35.564091   
  141_SAKD           30.355962  100.000000    0.000000  -8.460040  49.422504   
  
                           V4          V8           4          3b         FEF  \
  Subject_codename                                                              
  011_RZJA         -30.253985   79.634748   80.292063  -83.512907   63.565988   
  012_OHPA         -84.560467   73.484160    2.103297   19.890289   59.313525   
  014_WKFP          46.931306   98.431373   91.295035   81.588694   75.183492   
  015_SASN          88.103890   95.766684   75.626080  -66.011481    5.848318   
  016_NKMA          84.405998   52.832374   35.495937  -12.882347   97.315071   
  ...                     ...         ...         ...         ...         ...   
  137_RKPW          70.100529  -78.229391   64.968254   95.833333   84.815669   
  138_GZAA          29.480201   89.335423   93.692968   95.636364  -80.696970   
  139_SKAN          35.488873  100.000000   91.640212   63.956323   89.411765   
  140_CISN          33.704912  -69.979557  -99.086758 -100.000000  -47.170253   
  141_SAKD          65.024506 -100.000000  100.000000  100.000000  100.000000   
  
                    ...        p47r    TGv       MBelt       LBelt          A4  \
  Subject_codename  ...                                                          
  011_RZJA          ...  100.000000    0.0  100.000000  100.000000   80.677185   
  012_OHPA          ...  -92.207792    0.0 -100.000000 -100.000000  -95.436508   
  014_WKFP          ...  100.000000    0.0   92.592593   98.245614   95.445070   
  015_SASN          ...  100.000000    0.0  100.000000  100.000000   52.517964   
  016_NKMA          ...  100.000000    0.0   45.151515   24.446105  100.000000   
  ...               ...         ...    ...         ...         ...         ...   
  137_RKPW          ...  100.000000    0.0    0.000000  100.000000  100.000000   
  138_GZAA          ...  100.000000 -100.0  100.000000   94.619048   99.404762   
  139_SKAN          ...  100.000000    0.0   79.487179   67.195812   42.700962   
  140_CISN          ...  100.000000    0.0    0.000000    0.000000 -100.000000   
  141_SAKD          ...  100.000000    0.0 -100.000000    0.000000  -94.867488   
  
                         STSva        TE1m          PI       a32pr         p24  
  Subject_codename                                                              
  011_RZJA          100.000000  -80.000000  100.000000   78.069610  100.000000  
  012_OHPA         -100.000000  -94.150579 -100.000000   86.044974    0.000000  
  014_WKFP          100.000000   -4.761905    5.029680   86.475096  -33.174603  
  015_SASN           74.519789  100.000000   97.332317  100.000000  -70.000000  
  016_NKMA         -100.000000  100.000000  -15.060045   96.296296  100.000000  
  ...                      ...         ...         ...         ...         ...  
  137_RKPW         -100.000000  -91.666667 -100.000000   41.959020 -100.000000  
  138_GZAA          100.000000  100.000000   99.111111   92.169540  100.000000  
  139_SKAN           59.030537   99.656357   67.094330  100.000000  100.000000  
  140_CISN         -100.000000  -99.333333    0.000000   25.534759  100.000000  
  141_SAKD           93.015873   96.768283  -95.658263   89.308176  -94.612795  
  
  [125 rows x 180 columns]},
 'intensities': {'praxis':                          V1         MST          V6          V2          V3  \
  Subject_codename                                                              
  011_RZJA          -0.114902   39.364682   70.077044   -3.494281   -1.214550   
  012_OHPA          35.589775    2.018876   53.322846   -1.708105   39.550635   
  014_WKFP           4.177032   75.452817   -0.136338   37.759028   21.489934   
  015_SASN          19.635881   20.411373   20.218132    1.957889   20.370568   
  016_NKMA          21.193651  100.000000   87.387095  -37.568967   -2.281475   
  ...                     ...         ...         ...         ...         ...   
  137_RKPW         -56.167296  -71.858530   56.533171 -100.000000  -18.856993   
  138_GZAA          -0.015644   21.788234  -22.938654   -1.508595   -1.631890   
  139_SKAN         -35.410542  100.000000  100.000000  -69.640404  100.000000   
  140_CISN          36.808739   73.392541  -19.459431   19.650418   68.363937   
  141_SAKD          -0.504553   87.500526   19.015172  -19.562492  -70.130823   
  
                            V4          V8          4         3b         FEF  \
  Subject_codename                                                             
  011_RZJA           37.551032    2.070834  56.053379  56.283697   53.718208   
  012_OHPA          -72.304924 -100.000000 -18.890959   5.742417 -100.000000   
  014_WKFP           71.632334   56.714629   0.239242  -0.556017  -40.757051   
  015_SASN           17.711830   19.680068   1.555457  -2.194408   54.438264   
  016_NKMA           69.592096   20.001573  19.578826  55.445411   72.294548   
  ...                      ...         ...        ...        ...         ...   
  137_RKPW          -73.972962    0.000000  16.557441  37.024764  -72.741099   
  138_GZAA           36.519575 -100.000000 -20.947873  18.334631  100.000000   
  139_SKAN           73.280628  100.000000   0.839097  37.427175  100.000000   
  140_CISN          100.000000    0.000000  -0.642625  21.006457  100.000000   
  141_SAKD          -57.589131  100.000000  19.251426  18.248970  -72.331730   
  
                    ...        p47r  TGv       MBelt       LBelt          A4  \
  Subject_codename  ...                                                        
  011_RZJA          ...   86.791403  0.0  -53.324304   -1.057071   54.736935   
  012_OHPA          ...   86.515771  0.0  -35.574393 -100.000000 -100.000000   
  014_WKFP          ...  -87.819524  0.0    1.880220   73.651130   86.281063   
  015_SASN          ...  100.000000  0.0  -38.321769   38.537465   19.895808   
  016_NKMA          ...  100.000000  0.0  -41.895498  -22.549756   87.581916   
  ...               ...         ...  ...         ...         ...         ...   
  137_RKPW          ...  100.000000  0.0  -70.182466  -84.688697  -54.395155   
  138_GZAA          ...  -55.909225  0.0    2.345867  -18.608403  -19.307610   
  139_SKAN          ...  100.000000  0.0   85.596029  -73.388757   23.106925   
  140_CISN          ...  100.000000  0.0  100.000000  100.000000  100.000000   
  141_SAKD          ... -100.000000  0.0  -20.253465  -21.487428   -1.289055   
  
                         STSva        TE1m          PI       a32pr         p24  
  Subject_codename                                                              
  011_RZJA         -100.000000 -100.000000 -100.000000  -53.990894   55.087328  
  012_OHPA          -18.153231  -84.974516   20.382218    0.000000    0.000000  
  014_WKFP           87.254917   70.075896   71.456392  -20.275303   70.817356  
  015_SASN           55.925649  100.000000   54.607360    0.000000    0.000000  
  016_NKMA          -35.738472 -100.000000   38.361099  100.000000  100.000000  
  ...                      ...         ...         ...         ...         ...  
  137_RKPW          100.000000   58.731808  -21.315336  -71.228768  -52.320972  
  138_GZAA         -100.000000 -100.000000   20.566988   53.916267  -54.406753  
  139_SKAN          100.000000  100.000000    0.000000  100.000000    0.000000  
  140_CISN         -100.000000  100.000000    0.000000    0.000000    0.000000  
  141_SAKD         -100.000000   69.987609  -55.775794   -9.579697   52.894552  
  
  [125 rows x 180 columns],
  'language':                           V1         MST          V6         V2         V3  \
  Subject_codename                                                             
  011_RZJA          -37.768121  -42.915241   54.856417  -0.008100 -21.572006   
  012_OHPA         -100.000000   21.166744  -21.599678 -57.358146 -54.593575   
  014_WKFP          -20.847459  -41.170117  -39.577164 -53.731041 -35.551309   
  015_SASN          -54.694809  100.000000  100.000000  19.944623 -19.597945   
  016_NKMA          -20.987725  -16.981545  100.000000  18.165820  35.275078   
  ...                      ...         ...         ...        ...        ...   
  137_RKPW           -2.586639    0.000000   51.913148   0.086706   4.389344   
  138_GZAA          -20.122189    0.772823  100.000000  -3.263140  -0.894355   
  139_SKAN           18.705908  100.000000  -20.902529   0.021401  57.382912   
  140_CISN           36.929113 -100.000000  -18.900285  19.310566  18.185027   
  141_SAKD           35.932087  100.000000    0.000000  19.251537  18.453114   
  
                           V4          V8           4          3b         FEF  \
  Subject_codename                                                              
  011_RZJA          -2.833064   36.434476   70.034646  -56.535407   20.899505   
  012_OHPA         -54.141555   41.631033   -1.596869   -2.540282   41.030203   
  014_WKFP          21.278478   86.803336   36.891086   53.632752   41.949778   
  015_SASN          55.465817   50.293474   37.229790  -56.836035   -2.683916   
  016_NKMA          56.854415   -2.908250   -0.861146  -19.533664   54.884621   
  ...                     ...         ...         ...         ...         ...   
  137_RKPW          40.660990  -71.400373   38.187503   87.148658   57.500624   
  138_GZAA           2.095243   38.057014   70.524062   69.423240  -57.978528   
  139_SKAN           1.599099  100.000000   70.039500   36.001623   70.190483   
  140_CISN           1.259217  -37.267545  -86.797569 -100.000000   -4.196282   
  141_SAKD          36.967325 -100.000000  100.000000  100.000000  100.000000   
  
                    ...        p47r    TGv       MBelt       LBelt          A4  \
  Subject_codename  ...                                                          
  011_RZJA          ...  100.000000    0.0  100.000000  100.000000   37.757231   
  012_OHPA          ...  -71.231436    0.0 -100.000000 -100.000000  -72.030635   
  014_WKFP          ...  100.000000    0.0   85.855420   86.078804   69.598091   
  015_SASN          ...  100.000000    0.0  100.000000  100.000000   18.524745   
  016_NKMA          ...  100.000000    0.0   53.920834    3.941837  100.000000   
  ...               ...         ...    ...         ...         ...         ...   
  137_RKPW          ...  100.000000    0.0    0.000000  100.000000  100.000000   
  138_GZAA          ...  100.000000 -100.0  100.000000   51.800947   84.879280   
  139_SKAN          ...  100.000000    0.0   68.970835   51.605214   18.742201   
  140_CISN          ...  100.000000    0.0    0.000000    0.000000 -100.000000   
  141_SAKD          ...  100.000000    0.0 -100.000000    0.000000  -73.173745   
  
                         STSva        TE1m          PI       a32pr         p24  
  Subject_codename                                                              
  011_RZJA          100.000000  -88.429220  100.000000   19.105044  100.000000  
  012_OHPA         -100.000000  -54.793880 -100.000000   38.544828    0.000000  
  014_WKFP          100.000000   -1.947877   -1.971295   55.274558  -42.780173  
  015_SASN           19.162030  100.000000   72.600969  100.000000  -70.887674  
  016_NKMA         -100.000000  100.000000  -18.831365   86.633087  100.000000  
  ...                      ...         ...         ...         ...         ...  
  137_RKPW         -100.000000  -87.784040 -100.000000   -0.401882 -100.000000  
  138_GZAA          100.000000  100.000000   85.792594   72.289914  100.000000  
  139_SKAN           38.361778   86.515666   55.661348  100.000000  100.000000  
  140_CISN         -100.000000  -87.186332    0.000000   19.885462  100.000000  
  141_SAKD           71.079088   34.043055  -71.440569   86.409684  -54.505301  
  
  [125 rows x 180 columns]}}

Histograms

There is not much sense in generating barplot, as there are too many ROIs. It's better to show histograms to get to know the general trend across all ROIs.

Show histograms for all 180 ROIs

In [14]:
sns.set(color_codes=True)

def plot_histogram(data, skill, color, measure, bins=30):

    
    sns.distplot(data, bins=bins, kde=False, color=color, label='%s' % skill, hist_kws={"range": [-100,100]})
    plt.axvline(x=data.mean(), color=color, label='mean %s=%.2f' % (skill, data.mean()),
                linewidth=3, linestyle=':')
    plt.ylabel('Number of ROIs')
    plt.title('LIs distribution (%s)\n%s ROIs' % (measures_explicit[measure], len(data)))
    plt.legend()


for measure in measures:
    for skill, c in zip(skills, ('b', 'r')):
    
        data = dfs_laterality_indices[measure][skill].mean().rename('Laterality index')
        
        plot_histogram(data, skill, c, measure)

        # Save figure
        output_path = os.path.join(output_dir, 'figures', 'distributions_%s.pdf' % measure)
        plt.savefig(output_path)
    plt.show()

Show histograms for selected 50 ROIs

Based on ROIs defined in picks.

In [15]:
if picks is not None:
    for measure in measures:
        for skill, c in zip(skills, ('b', 'r')):

            data = dfs_laterality_indices[measure][skill].mean().rename('Laterality index')[picks]

            plot_histogram(data, skill, c, measure, bins=40)

            # Save figure
            output_path = os.path.join(output_dir, 'figures', 'distributions_%s.pdf' % measure)
            plt.savefig(output_path)
        plt.show()

Correlations

Correlation between language and praxis

In [16]:
for measure in measures:

    corr = dfs_laterality_indices[measure]['language'].corrwith(dfs_laterality_indices[measure]['praxis'])
    
    # Important! Make sure which axis is which
    # It is controlled later on by, e.g., x.scatter(x=..., y=...)
    print('')
    print('____________')
    print('Correlations')
    print(corr.describe())

    # Get highest correlation
    max_corr_roi = corr.idxmax()
    print('---')
    print('The highest correlation is in: %s' % max_corr_roi)
    max_corr_idx = corr.index.get_loc(max_corr_roi)
    print('It\'s numeric index is: %s' % max_corr_idx)

    colors = ['lightslategray',] * n_rois_per_hemisphere
    colors[max_corr_idx] = 'crimson'

    fig = go.Figure(data=[go.Bar(x=corr.index,
                                 y=corr.round(3),
                                 marker_color=colors)],)
    fig.update_layout(xaxis=dict(title='ROIs', tickmode='linear', tickfont=dict(size=7), constrain="domain"),
                      yaxis=dict(title='Correlation',
                                 scaleanchor = 'x',
                                 scaleratio = 1),
                      title=dict(text='Correlation between praxis and language (%s)' % measures_explicit[measure],
                                 x=0.5))
    fig.show()
    
    # Save correlation data
    output_path = os.path.join(output_dir, 'correlations', 'correlation-%s-praxis_language.csv' % measure)
    corr.to_csv(output_path, index_label='ROI', float_format='%.3f')
____________
Correlations
count    180.000000
mean       0.077816
std        0.116168
min       -0.169568
25%       -0.007168
50%        0.071701
75%        0.154278
max        0.446783
dtype: float64
---
The highest correlation is in: PFt
It's numeric index is: 115
____________
Correlations
count    180.000000
mean       0.084511
std        0.114664
min       -0.210138
25%        0.009479
50%        0.076440
75%        0.147565
max        0.472038
dtype: float64
---
The highest correlation is in: PFt
It's numeric index is: 115

The least correlated region

Regardless of the result of this analysis, ultimately V1 was chosen as the control region. It was decided that a prior it is a better site, and results from this region can be also easily compared to other studies.

In [17]:
for measure in measures:

    corr = dfs_laterality_indices[measure]['language'].corrwith(dfs_laterality_indices[measure]['praxis'])
    
    print('')
    print('____________')
    print('Measure: %s' % measure)
    
    # Get highest correlation
    most_uncorr_roi = corr.abs().idxmin()
    print('---')
    print('The least correlated region is: %s, with value: %s' % (most_uncorr_roi, corr[most_uncorr_roi]))
    most_uncorr_idx = corr.index.get_loc(most_uncorr_roi)
    print('It\'s numeric index is: %s' % most_uncorr_idx)
    
    print('---')
    control = 'V1'
    print('Control region V1, correlation: %s' % (corr[control]))
    contorl_idx = corr.index.get_loc(control)
    print('It\'s numeric index is: %s' % contorl_idx)
____________
Measure: voxels
---
The least correlated region is: 3b, with value: 0.0010063683698408286
It's numeric index is: 8
---
Control region V1, correlation: -0.09553123703473743
It's numeric index is: 0

____________
Measure: intensities
---
The least correlated region is: 5m, with value: 0.0006520272496830312
It's numeric index is: 35
---
Control region V1, correlation: 0.021439770374084243
It's numeric index is: 0

Plot correlation for praxis and language LIs in selected ROIs

Praxis ROIs correlated with Language ROIs

The results below include:

  1. Correlation of LIs based on Voxel Count
  2. Correlation of LIs based on Voxel Intensities

Marks (plus signs) represent particular subjects.

In [18]:
for measure in measures:
    
    for skill in skills: 

        highest_roi = dfs_laterality_indices[measure][skill][max_corr_roi]

for measure in measures:
        
    print('')
    print('')
    print('')
    print('________________')
    print('Measure: %s' % measure)
    
    for roi_name in rois_selection:
        language = dfs_laterality_indices[measure]['language'][roi_name].round(2).rename('Language')
        praxis = dfs_laterality_indices[measure]['praxis'][roi_name].round(2).rename('Praxis')
        sub_codes = pd.Series(praxis.index)
        sub_codes.index = praxis.index
        df = pd.concat([praxis, language, sub_codes], axis=1)

        fig = px.scatter(df, x='Language', y='Praxis',
                         color='Subject_codename')

        fig.update_layout(width = 800,
                          height = 500,
                          title = dict(text='Praxis-Language Relationships in %s (%s)' % (roi_name,
                                                                                          measures_explicit[measure]),
                                       x=0.5),
                          xaxis = dict(constrain='domain',
                                       range=[-105, 105]),
                          yaxis = dict(scaleanchor = "x",
                                       scaleratio = 1,
                                       range=[-105, 105]))

        fig.update_traces(marker=dict(size=12,
                                      symbol='cross-thin',
                                      line=dict(width=1.5)))

        fig.update_layout(showlegend=False)

        fig.show()


________________
Measure: voxels


________________
Measure: intensities

Average of voxel count and intensities

Arithmetic mean of Voxel Counts and Intensities. Below the example for V1 region is presented.

In [19]:
pd.concat([dfs_laterality_indices['voxels']['language']['V1'], dfs_laterality_indices['intensities']['language']['V1']], axis=1)
Out[19]:
V1 V1
Subject_codename
011_RZJA -58.142048 -37.768121
012_OHPA -100.000000 -100.000000
014_WKFP -29.559883 -20.847459
015_SASN -78.488705 -54.694809
016_NKMA -44.083061 -20.987725
... ... ...
137_RKPW 3.604163 -2.586639
138_GZAA -4.791819 -20.122189
139_SKAN 28.711699 18.705908
140_CISN 46.214127 36.929113
141_SAKD 30.355962 35.932087

125 rows × 2 columns

In [20]:
count_and_intensity = {}

for roi_name in rois_selection:
    for skill in skills:
        count_and_intensity[skill] = pd.concat([dfs_laterality_indices['voxels'][skill][roi_name],
                                                dfs_laterality_indices['intensities'][skill][roi_name]],
                                               axis=1).mean(axis=1)

    language = count_and_intensity['language'].round(2).rename('Language')
    praxis = count_and_intensity['praxis'].round(2).rename('Praxis')
    sub_codes = pd.Series(praxis.index)
    sub_codes.index = praxis.index
    df = pd.concat([praxis, language, sub_codes], axis=1)

    fig = px.scatter(df, x='Language', y='Praxis',
                     color='Subject_codename')

    fig.update_layout(width = 800,
                      height = 500,
                      title = dict(text='Praxis-Language - Average of Voxel Count and Intensity (%s)' % roi_name,
                                   x=0.5),
                      xaxis = dict(constrain='domain',
                                   range=[-105, 105]),
                      yaxis = dict(scaleanchor = "x",
                                   scaleratio = 1,
                                   range=[-105, 105]))

    fig.update_traces(marker=dict(size=12,
                                  symbol='cross-thin',
                                  line=dict(width=1.5)))

    fig.update_layout(showlegend=False)

    fig.show()

Correlation matrix between all ROIs

Function to calculate and display correlations

In [21]:
def plot_correlation_matrix(corr, title, output_figure_filename=None, xlabel=None, ylabel=None,
                            label_font_size=12, ticks_font_size=3, xrotation=90, show_numeric_values=False,
                            fmt='.2f'):
    plt.rcParams.update(plt.rcParamsDefault)

    plt.subplots(figsize=(20, 15))

    top = cm.get_cmap('Blues', 128)
    bottom = cm.get_cmap('YlOrRd_r', 128)

    yellow_to_blue = np.vstack((top(np.linspace(0, 1, 128)),
                                bottom(np.linspace(0, 1, 128))))
    yellow_to_blue = ListedColormap(yellow_to_blue, name='OrangeBlue')

    # Optionally: cmap=sns.diverging_palette(20, 220, n=200)
    ax = sns.heatmap(corr, 
                     vmin=-1, vmax=1, center=0,
                     cmap=yellow_to_blue,
                     square=True, xticklabels=True, yticklabels=True, annot=show_numeric_values,
                     fmt=fmt)

    ax.xaxis.labelpad = 30
    ax.yaxis.labelpad = 30

    ax.set_yticklabels(ax.get_yticklabels(), size=ticks_font_size);
    ax.set_xticklabels(ax.get_xticklabels(), rotation=xrotation, size=ticks_font_size);

    ax.tick_params(axis="y", left=False, right=False, pad=-2.5)
    ax.tick_params(axis="x", bottom=False, top=False, pad=-2.5)
    
    if xlabel is not None:
        ax.set_xlabel(xlabel, size=label_font_size)
    if ylabel is not None:
        ax.set_ylabel(ylabel, size=label_font_size)

    ax.set_title(title);

    # Saving to file takes about 85% of the time
    if output_figure_filename is not None:
        plt.savefig(output_figure_filename)

Praxis-Language correlation matrices

Two separate matrices: one for voxel count and another for intensities.

In [22]:
if rois_selection is not None:

    for measure in measures:
        
        print('')
        print('')
        print('')
        print('________________')
        print('Measure: %s' % measure)
        print('')
    
        corr = pd.concat([dfs_laterality_indices[measure]['language'][rois_selection],
                          dfs_laterality_indices[measure]['praxis'][rois_selection]], axis=0).corr()
        if verbose:
            print(corr)

        title = 'Correlation between praxis and language LIs (%s)' % measure
        output_path = os.path.join(output_dir, 'figures', 'correlation_praxis_language.pdf')

        plot_correlation_matrix(corr, title, output_path, xlabel='Language', ylabel='Praxis',
                                ticks_font_size=12, xrotation=0, show_numeric_values=True)
        plt.show()

        # Save correlation matrix
        output_path = os.path.join(output_dir, 'correlations',
                                   'correlation_matrix-%s-praxis_language.csv' % measures_explicit[measure])
        corr.to_csv(output_path, float_format='%.3f')


________________
Measure: voxels



________________
Measure: intensities

VCSI Praxis-Language correlations

In [23]:
vcsi = {}
for skill in skills:
    vcsi[skill] = pd.concat([dfs_laterality_indices['voxels'][skill],
                             dfs_laterality_indices['intensities'][skill]]).groupby(level=0).mean()
In [24]:
def cross_corr_dfs(df1, df2):
    # First language, then praxis
    # Language is x (argument) praxis i y (function value)
    corr = pd.DataFrame(columns=df1.columns, index=df2.columns, dtype=np.float64)
    
    for i in df1:
        for j in df2:
            corr[i][j] = stats.pearsonr(df1[i], df2[j])[0]
    
    return corr

Correlations unthresholded

In [25]:
if rois_selection is not None:

    corr = cross_corr_dfs(vcsi['language'][rois_selection],
                          vcsi['praxis'][rois_selection])

    title = 'VCSI Praxis-Language correlations (unthresholded)'
    output_name = 'vcsi_praxis-language_correlation_matrix_unthresholded.png'
    output_path = os.path.join(output_dir, 'figures', output_name)

    plot_correlation_matrix(corr, title, output_figure_filename=output_path,
                            xlabel='Language', ylabel='Praxis',
                            ticks_font_size=12, xrotation=0, show_numeric_values=True, fmt='.3f')

Correlations above r=0.45

In [26]:
threshold = 0.45

if rois_selection is not None:

    corr = cross_corr_dfs(vcsi['language'][rois_selection],
                          vcsi['praxis'][rois_selection])
    corr[corr<threshold] = 0

    title = 'VCSI Praxis-Language correlations (r<%s)' % threshold
    output_name = 'vcsi_praxis-language_correlation_matrix_threshold_%s.png' % threshold
    output_path = os.path.join(output_dir, 'figures', output_name)

    plot_correlation_matrix(corr, title, output_figure_filename=output_path,
                            xlabel='Language', ylabel='Praxis',
                            ticks_font_size=12, xrotation=0, show_numeric_values=True)

Correlations above r=0.5

In [27]:
threshold = 0.5

if rois_selection is not None:

    corr = cross_corr_dfs(vcsi['language'][rois_selection],
                          vcsi['praxis'][rois_selection])
    corr[corr<threshold] = 0
    
    title = 'VCSI Praxis-Language correlations (r<%s)' % threshold
    output_name = 'vcsi_praxis-language_correlation_matrix_threshold_%s.png' % threshold
    output_path = os.path.join(output_dir, 'figures', output_name)

    plot_correlation_matrix(corr, title, output_figure_filename=output_path,
                            xlabel='Language', ylabel='Praxis',
                            ticks_font_size=12, xrotation=0, show_numeric_values=True)

Spearman's correlations for selected regions

In [28]:
stats.pearsonr(vcsi['language']['44'], vcsi['praxis']['PFt'])
Out[28]:
(0.4986660935776998, 3.251048642635184e-09)
In [29]:
stats.pearsonr(vcsi['language']['AIP'], vcsi['praxis']['PF'])
Out[29]:
(0.2899586553059729, 0.0010379614853119265)
In [30]:
stats.spearmanr(vcsi['language']['LIPv'], vcsi['praxis']['AIP'])
Out[30]:
SpearmanrResult(correlation=0.2775459691352829, pvalue=0.0017262379317218176)

Which filed in the correlation matrix holds the highest correlation?

In [31]:
for measure in measures:
    corr = pd.concat([dfs_laterality_indices[measure]['praxis'], dfs_laterality_indices[measure]['language']], axis=0).corr()

    one_axis_max = corr[corr!=1].max().idxmax()


    second_axis_max = corr[one_axis_max][corr[one_axis_max]!=1].idxmax()


    corr[one_axis_max][second_axis_max]

    print('Two regions with the highest correlation for _%s_ measure are: %s and %s' % (measure, one_axis_max, second_axis_max))
Two regions with the highest correlation for _voxels_ measure are: 44 and 6r
Two regions with the highest correlation for _intensities_ measure are: IFSp and IFSa
In [32]:
%%javascript
// Restart and run all placed in the toolbox UI
// Source & inspiration: https://github.com/ipython/ipython/issues/4468#issuecomment-137995309

// Check if these is already button for that in the UI.
if($(IPython.toolbar.selector.concat(' > #restart-run-all')).length == 0){
  IPython.toolbar.add_buttons_group([
        {
             'label'   : 'Restart & Run All',
             'icon'    : 'fa fa-angle-double-down',
             'callback': function(){
                 IPython.notebook.kernel.restart();
                 $(IPython.events).one('kernel_ready.Kernel',
                                       function(){IPython.notebook.execute_all_cells();});
             }
        }
    ], 'restart-run-all');
}