How can I binarize and threshold images in Nilearn?

neuroimaging
nilearn
nipype
#1

Straightforward question, but if I have a list of T maps loaded using the image tools in Nilearn, how can I binarize them (i.e., all values greater than 3 are set to 1, and all values less than 3 are set to zero.

Similarly, how would one simply threshold the images (I’ve tried the image.threshold_img function, but do not seem to understand the usage when the input is a list of images via:

sample_fc_networks = [image.load_img(entry) for entry in sample_fc_network_files]

#2

how can I binarize them (i.e., all values greater than 3 are set to 1, and all values less than 3 are set to zero.

One of the easiest ways to do this in nilearn is with image.math_img:

from nilearn.image import load_img, math_img
tstat_img = load_img(...)
mask = math_img('img > 3', img=t_img)
mask.to_filename(...)

For thresholding, try the following:

sample_fc_networks = [image.threshold_img(entry, 3) for entry in sample_fc_network_files]

Nilearn lets you manipulate files at the same time as opening them, so no need to load, first. (The same is actually true for the math_img use above, too.)

#3

Is it possible to pass a variable to math_img? E.g.:

threshold = 3
mask = math_img ('img > threshold', img=t_img, threshold=threshold)

I also want to binarize a nifti file to use it later as a mask for NiftiMasker but I need the treshold to be a variable so that it can be optimized in nested cross validation. Currently I use img_threshold to set every value below the threshold to zero and after that I set every ‘left over’ value which is not zero to one. I find this pretty inconvenient and it would be nice to have a function such as math_img which also accepts variables.

How to create a pipeline with multiple inputs?
#4

The semantics of such a function would be tricky to define. What is wrong with grabbing the numpy array from the nibabel object and working from it, if you want to do more advanced operations?

#5

Nothing wrong with that I just wondered if such a function exists. I could skip a lot of code if a function as described above would exist, since it takes the nibabel object as it is and also returns a nibabel object. Working with numpy arrays means that one has to use get_data and new_img_like which can make the code look a little messy eventually. So to agree with you one can also do it manually but for reasons of readability and convenience it would be nice to have a build-in binarizer function which accepts a nibabel object, an arbitrary threshold and returns a binary nibabel object. This object could then passed over to other objects (such as NiftiMasker for example).

#6

You could use a variable in math_img by formatting the string, as in:

threshold = 3
mask = math_img(f'img > {threshold}', img=t_img)

(using whatever your preferred string formatting syntax is). Would this do what you’re hoping, @JohannesWiesner?

3 Likes
#7

Yes, that solution worked for me, thanks @rmarkello!