Problems with using NiftiLabelsMasker

I want to use NiftiLabelsMasker to extract voxels of interest using the Destrieux-Atlas. I am working with MRI-Data (not fMRI) so the 4th dimension represents different subjects, not different time points for a single subject (In case this should be a problem related to the questions below please tell me). I created a dummy script and tried to NiftiLabelsMasker on the OASIS dataset (which is available through nilearn.datasets.fetch_oasis_vbm. I also played with the mask image (I tried to create a mask that reduces the atlas image to regions 1 and 2). But I stumpled upon 2 problems:

1.) The masking doesn’t work: Although I provide (NiftiLabelsMasker with destrieux_atlas_roi_mask I get 148 data columns (which seems to be all 148 regions reported in this paper). I expect NiftiLabelsMasker to output only 2 columns.

2.) When I look at fetch_atlas_destrieux_2009()['labels'] this array is 151 rows long. I know that the 0 represents the background but even then there are two more regions that do not appear in the final dataset (after calling fit_transform and which do not fit to the reported 148 regions in the paper above). So what happens to those two regions?

Here’s my toy script:

from nilearn.image import load_img
from nilearn.datasets import fetch_atlas_destrieux_2009
from nilearn.datasets import fetch_oasis_vbm
from nilearn.image import math_img

from nilearn.input_data import NiftiLabelsMasker

# niftilabels masker cache
niftilabelsmasker_cache = './niftilabelsmasker_cache/'

# fetch OASIS dataset
oasis_img_paths = fetch_oasis_vbm(n_subjects=10)['gray_matter_maps']

# load destrieux atlas
destrieux_atlas_dict = fetch_atlas_destrieux_2009()
destrieux_atlas = load_img(fetch_atlas_destrieux_2009()['maps'])

# get only region 1 and 2
destrieux_atlas_roi_mask = math_img('np.where(((img == 1) | (img == 2)),1,0)',img=destrieux_atlas)

# extract data
niftilabelsmasker = NiftiLabelsMasker(labels_img=destrieux_atlas,
                                      mask_img=destrieux_atlas_roi_mask,
                                      memory=niftilabelsmasker_cache)

img_data = niftilabelsmasker.fit_transform(oasis_img_paths)

I can reproduce it.
Indeed this sounds like a bug: mask_img is ignored.
Please open an issue.

1 Like

I also found an anwer to my second question: When I extract the unique labels from the destrieux atlas using numpy, I end up with the correct 148 regions:

import numpy as np
destrieux_atlas_data = destrieux_atlas.get_fdata()
destrieux_atlas_uniques = np.unique(destrieux_atlas_data)

So it seems like fetch_atlas_destrieux_2009()['labels'] is not up to date. I commented on a seemingly related issue on GitHub.

I opened up an issue on GitHub.

Certainly seems like a bug. In the meantime, a workaround would be to run this instead:

two_region_atlas = math_img("np.where((img == 1) | (img == 2), img, 0)", img=destrieux_atlas)

niftilabelsmasker = NiftiLabelsMasker(labels_img=two_region_atlas, 
                                      memory=niftilabelsmasker_cache)   
img_data = niftilabelsmasker.fit_transform(oasis_img_paths)

The modified math_img line zeros every voxel that does not belong to regions 1 and 2 while keeping the original labels for these regions only. Then, only labels_img needs to be passed into NiftiLabelsMasker; no mask_img is required.

Running this produced your desired result (a 2 column output).

1 Like