How can I binarize and threshold images in Nilearn?

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]

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.)

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.

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?

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).

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

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