Scrubbing rs-fMRI images using nilean.clean_img

Summary of what happened:

I am trying to use the load_confounds function from nilearn.interfaces.fmriprep in conjunction with clean_img from nilearn.image, with the goal of having a new cleaned image object. It doesn’t seem like the scrubbing paremeters are working, however, as there are the same amounts of volumes pre and post clean_img. I was wondering if I was doing something wrong here.

This seems to only happen when I use clean_img for this, because when I load the same confounds into a masker object when doing fit_transform it seems to remove the appropriate volumes. It’s important for my analysis that I have a separate cleaned image file with volumes removed before extraction, so I was hoping for some help. Thank you :slight_smile:

Command used (and if a helper script was used, a link to the helper script or the command generated):

regressors, sample_mask = load_confounds(subject_file, strategy=("motion", "wm_csf", "scrub"), \
                                            motion='full', wm_csf='basic', scrub=5, fd_threshold=0.5, std_dvars_threshold=1.5)

new_image = nli.clean_img(subject_file, detrend=True, confounds=regressors, standardize='zscore_sample', high_pass=.008, low_pass=.09, t_r=tr, sample_mask=sample_mask)
img_data = new_image.get_fdata()

print(img_data.shape) # still outputs (97, 115, 97, 900) when there should be less than 900 volumes after scrubbing.

Any advice on how to go about this? Thanks so much!!


Hi @mamandola,

What are the values of sample_mask? I also do not see a sample_mask argument for clean_img. I think what you get from this will be regressors with one-hot encoded vectors of volumes to remove, for use in a GLM, which is different from what you want. If your sample mask is boolean indicating what volumes to keep, you can just index the fourth dimension of your original images data to extract just those time points. It also looks like sample_mask can be passed into nilearn.signal.clean - Nilearn.

Best,
Steven

Ah - okay I see. Thanks so much for the clarification. sample_mask is an array of 898 values, so I should use this to manually remove the volumes that aren’t in sample_mask?

As for regressors, if I feed them into my clean_img command, they should be applied to the output, correct? I’m pulling data from a list particular voxels using nibabel rather than a masker image, so I was hoping to use the output of clean_img.

Thanks,
Matt

Hi @mamandola,

If the values of sample_mask is a boolean vector indicating the correct volumes to remove based on your criteria, then yes.

Yes, from the documentation (nilearn.image.clean_img - Nilearn):

confounds numpy.ndarray, str or list of

Confounds timeseries. optional Shape must be (instant number, confound number), or just (instant number,) The number of time instants in signals and confounds must be identical (i.e. signals.shape[0] == confounds.shape[0]). If a string is provided, it is assumed to be the name of a csv file containing signals as columns, with an optional one-line header. If a list is provided, all confounds are removed from the input signal, as if all were in the same array.

Best,
Steven

Thanks so much for your help :slight_smile:

1 Like

Hi Steven,

Sorry to bother you again, but just wanted to pick your brain for a quick second. So, if I were to get an array from sample_mask, and I were to use time_series = masker.fit_transform(subject_file), could I then do something like time_series = time_series[sample_mask] in order to extract data from only the volumes that survived scrubbing?

There is a sample_mask argument for the NiftiLabelsMasker, but just wanted to check.

Thanks!
-Matt

Hi @mamandola,

You can use sample mask directly in nilearn.signal.clean - Nilearn, otherwise if you do it manually you would need to make sure that you are only indexing the 4th dimension of your timeseries. It is hard to to tell from the limited code because I do not know what masker you are using. It seems like nilearn.maskers.NiftiMasker - Nilearn has a fit_transform method that accepts sample_mask as an argument.

Best,
Steven

1 Like

Ahhh, ok, it was a silly mistake on my part. I was loading sample_mask into the NiftiLabelsMasker command, rather than the fit_transform command. Thanks so much.