Collecting image statistics from Regions-of-Interest over many subjects
Collecting basic image statistics (e.g. mean, std) from ROIs over a set of images can be done easily in Python.
EDIT (03-02-2020): check this new post for more recent contents on the subject
EDIT (23-11-2018): check roistats for a module version of this code
See the example in this Jupyter Notebook
import numpy as np
import nibabel as nib
from glob import glob
import pandas as pd
from joblib import Parallel, delayed
def roistats_from_map(map_fp, atlas, func):
m = np.array(nib.load(map_fp).dataobj)
n_labels = list(np.unique(atlas))
n_labels.remove(0)
label_values = [func(m[atlas==label]) for label in n_labels]
return label_values
def roistats_from_maps(atlas_fp, maps_fp, subjects=None, labels=None,
func=np.mean, n_jobs=7):
atlas_im = nib.load(atlas_fp)
atlas = np.array(atlas_im.dataobj)
n_labels = list(np.unique(atlas))
n_labels.remove(0)
df = Parallel(n_jobs=n_jobs, verbose=1)(\
delayed(roistats_from_map)(maps_fp[i], atlas, func)\
for i in xrange(len(maps_fp)))
columns = labels if not labels is None \
else [int(e) for e in n_labels]
res = pd.DataFrame(df, columns=columns)
res['subject'] = xrange(len(maps_fp)) if subjects is None else subjects
res = res.set_index('subject')
return res
roistats_from_maps
takes a path to the label map defining the ROIS and a
list of filepaths to the images to compute the stats from. roistats_from_map
returns
a list of values from one single map, while roistats_from_maps
parallelizes it
(using joblib) over images and compiles the
returned rows into one single table, adding it a list of subject identifiers
(if argument subjects
is given) and naming the columns with labels
(if given).
By default, the mean is computed for every region but any other NumPy function
can be passed as func
argument. Last but not least, is used for parallel processing.
Example:
atlas_fp = '/path/to/rois.nii.gz'
maps_fp = glob('/path/to/images*.nii.gz')
subjects = [10538, 12252, 55708, 12121, 11015]
names = {1: 'Middle cerebellar peduncle', 2: 'Pontine crossing tract',
3: 'Genu of corpus callosum', 4: 'Body of corpus callosum',
5: 'Splenium of corpus callosum', 6: 'Fornix',
7: 'Corticospinal tract R', 8: 'Corticospinal tract L',
9: 'Medial lemniscus R'}
df = roistats_from_maps(atlas_fp, maps_fp, subjects=subjects, labels=names.values())
#df.to_excel('/path/to/excelfile.xls')
Will return a table like:
Middle cerebellar peduncle | Pontine crossing tract | Genu of corpus callosum | Body of corpus callosum | Splenium of corpus callosum | Fornix | Corticospinal tract R | Corticospinal tract L | Medial lemniscus R | |
---|---|---|---|---|---|---|---|---|---|
subject | |||||||||
10538 | 0.000817 | 0.000895 | 0.000757 | 0.000818 | 0.000833 | 0.000849 | 0.000819 | 0.000834 | 0.000716 |
12252 | 0.000850 | 0.000896 | 0.000719 | 0.000816 | 0.000817 | 0.000850 | 0.000843 | 0.000834 | 0.000743 |
55708 | 0.000853 | 0.000929 | 0.000732 | 0.000851 | 0.000795 | 0.000922 | 0.000839 | 0.000872 | 0.000786 |
12121 | 0.000842 | 0.000926 | 0.000810 | 0.000846 | 0.000826 | 0.000868 | 0.000810 | 0.000822 | 0.000723 |
11015 | 0.000847 | 0.000879 | 0.000805 | 0.000877 | 0.000856 | 0.000839 | 0.000814 | 0.000792 | 0.000831 |
Please let me know if you liked this post by clicking the button below.