bbfrederick / rapidtide

rapidtide - a suite of programs for doing time lag correlation analysis on fMRI data
Apache License 2.0
75 stars 14 forks source link

Brain mask too aggressively eroded? #117

Closed themeo closed 1 year ago

themeo commented 1 year ago

Describe the bug While inspecting the EPI time-series processed through rapidtide (i.e. with the delayed lfo regressor regressed out) I noticed that the resulting image is considerably eroded compared to the original image (and brainmask). See for example here:

image

(yellow is the original brain mask).

I inspected time-courses of the zeroed voxels and there seems to be nothing wrong with them: image

In my understanding, rapidtide creates brainmasks to select voxels to estimate the global regressor, and here it may be picky as to which voxels count as reliable. However, once a refined version of the global regressor is obtained, can the delayed correlation still be obtained for the remaining voxels? I probably missed some important details about rapidtide's algorithm (e.g. the refinement and estimation of delay and correlation strength are done together).

A practical motivation for submitting this issue is that 20% of the most activated voxels of my functional localizers overlap with those zeroed voxels in the rapidtide-preprocessed images, which make me concerned that I may be losing important signal.

To Reproduce

I used options --filterband lfo --passes 3 --spatialfilt 4 in this particular case.

bbfrederick commented 1 year ago

By default, rapidtide calculates masks dynamically at run time. There are 4 masks used 1) the global mean mask, which determines which voxels are used to generate the initial global mean regressor, 2) The correlation mask, which determines which voxels you actually calculate rapidtide fits in (what you are describing here), 3) the refine mask, which selects which voxels are used to generate a refined regressor for the next fitting pass, and 4) the GLM mask, which determines which voxels have the rapidtide regressors removed.

Below is a description of how this works currently. NB: this is not how I THOUGHT is worked - until I just looked at the code just now. It built up over time, and evolved into something not quite what I designed. I'm going to fix it up, but this what it's doing as of 2.6.1, which works most of the time, but may not be what you want.

The default behavior is to first calculate the correlation mask using nilearn.masking.compute_epi_mask with default values. This is a complicated function, which I'm using as a bit of a black box. Documentation for it is here: https://nilearn.github.io/stable/modules/generated/nilearn.masking.compute_epi_mask.html#nilearn.masking.compute_epi_mask. If you have standard, non-zero-mean fMRI data, it seems to work pretty well, but you can specify your own mask using --corrmask NAME[:VALSPEC] (include any non-zero voxels in NAME in the mask. If VALSPEC is provided, only include voxels with integral values listed in VALSPEC in the mask). VALSPEC is a comma separated list of integers (1,2,7,12) and/or integer ranges (2-7,12-15) so you can make masks of complicated combinations of regions from an atlas. So for example --corrmask mymask.nii.gz:1,7-9,54 would include any voxels in mymask with values of 1, 7, 8, 9, or 54, whereas --corrmask mymask.nii.gz would include any non-zero voxels in mymask.

For the global mean mask: If --globalmeaninclude MASK[:VALSPEC] is specified, include all voxels selected by MASK[:VALSPEC]. If it is not specified, include all voxels in the mask. Then, if --globalmeanexclude MASK[:VALSPEC] is specified, remove any voxels selected by MASK[:VALSPEC] from the mask. If it is not specified, don't change the mask.

For the refine mean mask: If --refineinclude MASK[:VALSPEC] is specified, include all voxels selected by MASK[:VALSPEC]. If it is not specified, include all voxels in the mask. Then if --refineexclude MASK[:VALSPEC] is specified, remove any voxels selected by MASK[:VALSPEC] from the mask. If it is not specified, don't change the mask. Then multiply by corrmask, since you can't used voxels rwhere rapidtide was not run to do refinement.

For the GLM mask: Include all voxels, unless you are calculating a CVR map, in which case only perform the calculation on voxels exceeding 25% of the robust mean value (this is weird and will change).

Depending on your data (including pathology), and what you want to accomplish, using the default correlation mask is not ideal (and you seem to have come across one of these cases), and you may want to specify one or more of these masks. Since it sounds like you have a brain mask already, start by specifying --corrmask yourbrainmask.nii.gz

themeo commented 1 year ago

This did the trick, and thanks for the explanation, it makes sense! The only thing that perhaps would be worth changing is the documentation. When I checked the arguments, it wasn't immediately clear to me that --corrmask sets the default mask that if not modified by further arguments, will be used throughout the analysis.

In my case, the masks were different because fmriprep has its own algorithm for delineating them.