Visualization of normative modeling outputs
The Normative Modeling Framework for Computational Psychiatry. Nature Protocols. https://www.nature.com/articles/s41596-022-00696-5.
Created by Saige Rutherford
We have also built an app for interactively viewing the evaluation metrics.
Brain space extreme deviation counts
Count the number of extreme (positive & negative) deviations at each brain region and visualize the count for each hemisphere.
! git clone https://github.com/predictive-clinical-neuroscience/PCNtoolkit-demo.git
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
os.chdir('/content/PCNtoolkit-demo')
Z_df = pd.read_csv('data/Z_long_format.csv')
# Change this threshold to view more or less extreme deviations.
# Discuss with your partner what you think is an appropriate threshold and adjust the below variables accordingly.
Z_positive = Z_df.query('value > 2')
Z_negative = Z_df.query('value < -2')
positive_left_z = Z_positive.query('hemi == "left"')
positive_right_z = Z_positive.query('hemi == "right"')
positive_sc_z = Z_positive.query('hemi == "subcortical"')
negative_left_z = Z_negative.query('hemi == "left"')
negative_right_z = Z_negative.query('hemi == "right"')
negative_sc_z = Z_negative.query('hemi == "subcortical"')
positive_left_z2 = positive_left_z['ROI_name'].value_counts().rename_axis('ROI').reset_index(name='counts')
positive_right_z2 = positive_right_z['ROI_name'].value_counts().rename_axis('ROI').reset_index(name='counts')
positive_sc_z2 = positive_sc_z['ROI_name'].value_counts().rename_axis('ROI').reset_index(name='counts')
negative_left_z2 = negative_left_z['ROI_name'].value_counts().rename_axis('ROI').reset_index(name='counts')
negative_right_z2 = negative_right_z['ROI_name'].value_counts().rename_axis('ROI').reset_index(name='counts')
negative_sc_z2 = negative_sc_z['ROI_name'].value_counts().rename_axis('ROI').reset_index(name='counts')
positive_left_z2.describe()
counts | |
---|---|
count | 74.000000 |
mean | 24.432432 |
std | 6.182346 |
min | 13.000000 |
25% | 20.000000 |
50% | 23.000000 |
75% | 28.000000 |
max | 46.000000 |
positive_right_z2.describe()
counts | |
---|---|
count | 74.000000 |
mean | 24.027027 |
std | 6.164354 |
min | 11.000000 |
25% | 20.250000 |
50% | 23.000000 |
75% | 27.750000 |
max | 39.000000 |
positive_sc_z2.describe()
counts | |
---|---|
count | 28.000000 |
mean | 16.714286 |
std | 5.449140 |
min | 8.000000 |
25% | 12.000000 |
50% | 16.000000 |
75% | 21.250000 |
max | 27.000000 |
negative_left_z2.describe()
counts | |
---|---|
count | 74.000000 |
mean | 11.108108 |
std | 5.193694 |
min | 2.000000 |
25% | 7.000000 |
50% | 10.000000 |
75% | 14.000000 |
max | 27.000000 |
negative_right_z2.describe()
counts | |
---|---|
count | 74.000000 |
mean | 12.824324 |
std | 4.603031 |
min | 1.000000 |
25% | 10.000000 |
50% | 13.000000 |
75% | 14.750000 |
max | 33.000000 |
negative_sc_z2.describe()
counts | |
---|---|
count | 28.000000 |
mean | 9.142857 |
std | 6.614878 |
min | 1.000000 |
25% | 4.000000 |
50% | 7.000000 |
75% | 12.000000 |
max | 26.000000 |
! pip install nilearn
from nilearn import plotting
import nibabel as nib
from nilearn import datasets
destrieux_atlas = datasets.fetch_atlas_surf_destrieux()
fsaverage = datasets.fetch_surf_fsaverage()
Dataset created in /root/nilearn_data/destrieux_surface
Downloading data from https://www.nitrc.org/frs/download.php/9343/lh.aparc.a2009s.annot ...
...done. (1 seconds, 0 min)
Downloading data from https://www.nitrc.org/frs/download.php/9342/rh.aparc.a2009s.annot ...
...done. (1 seconds, 0 min)
# The parcellation is already loaded into memory
parcellation_l = destrieux_atlas['map_left']
parcellation_r = destrieux_atlas['map_right']
nl = pd.read_csv('data/nilearn_order.csv')
atlas_r = destrieux_atlas['map_right']
atlas_l = destrieux_atlas['map_left']
nl_ROI = nl['ROI'].to_list()
Extreme positive deviation viz
nl_positive_left = pd.merge(nl, positive_left_z2, on='ROI', how='left')
nl_positive_right = pd.merge(nl, positive_right_z2, on='ROI', how='left')
nl_positive_left['counts'] = nl_positive_right['counts'].fillna(0)
nl_positive_right['counts'] = nl_positive_right['counts'].fillna(0)
nl_positive_left = nl_positive_left['counts'].to_numpy()
nl_positive_right = nl_positive_right['counts'].to_numpy()
a_list = list(range(1, 76))
parcellation_positive_l = atlas_l
for i, j in enumerate(a_list):
parcellation_positive_l = np.where(parcellation_positive_l == j, nl_positive_left[i], parcellation_positive_l)
a_list = list(range(1, 76))
parcellation_positive_r = atlas_r
for i, j in enumerate(a_list):
parcellation_positive_r = np.where(parcellation_positive_r == j, nl_positive_right[i], parcellation_positive_r)
# you can click around in 3D space on this visualization. Scroll in/out, move the brain around, etc. Have fun with it :)
view = plotting.view_surf(fsaverage.infl_right, parcellation_positive_r, threshold=None, symmetric_cmap=False, cmap='plasma', bg_map=fsaverage.sulc_right)
view