Why do nltools Brain_Data classes always have 238955 voxels?

I’m new to fMRI data and am just trying to get a feel for the structure of data. I’ve followed some of the dart brains tutorials and have been looking into a dataset that I’m interested in. I was totally confused to see that for all the different datasets that I look at, the number of voxels is always 235955. This is despite the the dimensions of the images (as far as i can ascertain) being much bigger - for example around 90 x 100 x 90 or larger. Can anyone explain why this is? Thanks!

Hi @Steve_Sizzou and welcome to neurostars!

There isn’t really enough information here for us to answer this. Some things that could help are links to the datasets, a description of the data, and code you are using to analyze the data and get that 235955 figure. One possibility is that you are only looking at voxels in a brain mask (that is, only at places where there is a brain) and ignoring the non-brain areas.

Best,
Steven

Hi @Steven Thanks for the fast reply! of course this needs an example, sorry for my low effort post haha Here is an example of my conundrum with data from the Dart brains course, and the data from the study forrest project.


import os
import glob
import datalad.api as dl
from bids import BIDSLayout
import nibabel as nib
from nltools.data import Brain_Data


#################################################
# example from the dartbrains course

localizer_path = 'dartbrains_data/Localizer'
#dl.clone(source='https://gin.g-node.org/ljchang/Localizer', path=localizer_path)
ds = dl.Dataset(localizer_path)

file_list = glob.glob(os.path.join(localizer_path, '*', 'fmriprep', 'sub*'))
# need to drop "dartbrains_data/Localizer" from the paths
for k in range(0, len(file_list)):
    file_list[k] = file_list[k].replace('dartbrains_data/Localizer/', '')

file_list.sort()
for f in file_list[:2]:
    result = ds.get(f)

layout = BIDSLayout(localizer_path, derivatives=True)

sub = 'S01'
data_loc_brain_data = Brain_Data(layout.get(subject=sub, task='localizer',
                                 scope='derivatives', suffix='bold', extension='nii.gz', return_type='file'))

data_loc_nib = nib.load('/dartbrains_data/Localizer/derivatives/fmriprep/sub-S01/func/sub-S01_task-localizer_space-MNI152NLin2009cAsym_desc-preproc_bold.nii.gz')

print(data_loc_brain_data.shape())
# returns (128, 238955)
print(data_loc_nib.shape)
# returns (91, 109, 91, 128)  ... but 91*109*91 = 902629! which is considerably more than in the
# Brain_Data class so where did the other voxels go?



#################################################
# example from the study forrest dataset

#dl.clone(source='https://github.com/OpenNeuroDatasets/ds001769.git', path=localizer_path)
# or in terminal
#datalad install https://github.com/OpenNeuroDatasets/ds001769.git

path = 'data/ds001769'
ds = dl.Dataset(path)

result = ds.status(annex='all')

# get everything for subject 1
file_list = os.listdir('data/ds001769/sub-01/ses-movie/func')
for idx, file in enumerate(file_list):
    file_list[idx] = os.path.join('sub-01/ses-movie/func', file_list[idx])

for file in file_list:
   result = ds.get(file)

run1_brain_data = Brain_Data('data/ds001769/sub-01/ses-movie/func/sub-01_ses-movie_task-movie_run-1_space-T1w_desc-unsmDenoised_bold.nii.gz')

run1_nib = nib.load('data/ds001769/sub-01/ses-movie/func/sub-01_ses-movie_task-movie_run-1_space-T1w_desc-unsmDenoised_bold.nii.gz')

print(run1_brain_data.shape())
# returns  (451, 238955)
print(run1_nib.shape)
# returns (80, 80, 35, 451) but 80*80*35 = 224000 Which is less voxels that in the brain_data class,
# so where did the extra voxels come from???

You can see if the first scenario there are voxels missing, and in the second scenario there are new voxels added, I find this quite confusing :slight_smile:

Hi @Steve_Sizzou ,

I don’t know these tools but you may find the explanation in the code of Brain_Data:
https://nltools.org/_modules/nltools/data/brain_data.html#Brain_Data

It looks like the image is loaded with nib.load as well and the extra operations after must be at the origin of the discrepancy.

Hi @Steve_Sizzou, to extend what @Steven and @jsein said, there’s some helpful info here (under nltools.prefs) about the nltools default mask:

“By default all operations are performed in MNI152 2mm space . Thus any files loaded with be resampled to this space by default.You can control this on a per-file loading basis using the mask argument of Brain_Data.”