Rapidtide after fMRIPrep usage questions

I’m interested in running Rapidtide on my resting-state fMRI dataset to remove physiological noise from cardiac, respiratory, and sLFO signals. I’ve already run fMRIPrep 24.1.0rc2 on my data and have cardiac and respiratory recordings in BIDS format from the scanner. From reading the documentation, it seems like Rapidtide only removes sLFO signals that it extracts from the fMRI data itself, and doesn’t actually use the raw physiological recordings as inputs. I’m confused about whether I need to do additional preprocessing with my cardiac/respiratory data, and whether I should be running Happy (which does take physiological files as input) on my data as well. What’s the recommended workflow here? Should I run Happy first to process the physiological data, then use those outputs somehow with Rapidtide? Or does Rapidtide’s sLFO removal already capture the physiological noise I’m concerned about? Any guidance on how to best utilize both the Rapidtide pipeline and my physiological recordings would be greatly appreciated.

1 Like

@bbfrederick, would you mind taking a look at this?

I believe that rapidtide is supposed to work better without external physio recordings than with them, but I could be wrong.

Interesting - I got pretty much the same question on Github recently. The issue discussion (now closed) is here: Request for more documentation on denoising · Issue #235 · bbfrederick/rapidtide · GitHub. Most of it migrated verbatim into the documentation here: rapidtide — rapidtide 3.1.4 documentation .

The TL;DR is that you can use rapidtide with physiological recordings, but you probably shouldn’t, because it’s not good at removing aliased signals (but if you have a 400ms or shorter TR, then go to it!). Happy is a better tool for cardiac signal removal. The main reason rapidtide accepts physiological recordings was to use simultaneously recorded NIRS signals filtered down to the sLFO band, which works well, but almost nobody has data like that, and the sLFO regressor you bootstrap out of the BOLD data itself works as well if not better (since it is extracted from the brain, it is the most representative of what the sLFO signal looks like in the brain).

In terms of order of operations, if you really want to clean every last scrap of physiological noise out of your data:

  1. Apply happy to the NON-preprocessed fMRI data (preprocessing removes information happy needs to work) and use the --temporalregression argument to generate a file cleaned of cardiac signal. Happy uses the precise sample timing of each voxel to generate an aligned, aliased cardiac regressor which can be linearly regressed out of the data.
  2. Rename that cleaned data file (XXX_desc-cardfilterCleaned_bold.nii.gz) with a suitably BIDSy name implying that it is a raw fmri file, then run it through fmriprep.
  3. Run rapidtide on the preprocessed data file (in native, T1, or MNI coordinates - I’d recommend the MNI) to pull out the sLFO noise.
  4. Do whatever it is you want to do with clean BOLD data.

Respiration is a little tricky; if your TR is <= ~800ms, it’s not aliased, so you can remove it with a simple filter or use rapidtide with the respiratory waveform. The signal itself is synchronous across the whole head, since it’s mostly a combination of actual respiratory correlated motion and apparent motion caused by susceptibility shifts caused by lung inflation. So it will be at a single delay. But the shape of the signal impressed onto the fMRI data is not necessarily the shape of the signal you get from a respiratory bellows - the mapping between chest wall position and the resulting fMRI signal is not strictly linear, so you might want to do a polynomial expansion of the bellows waveform (the waveform, its square, its cube, etc) and a few derivatives to deal with misalignment between the BOLD and physio data.

Hope that’s helpful!

1 Like

This is great, thank you for the helpful response, @bbfrederick!

Just a quick follow-up: I ran happy on my multi-echo rest data on each echo individually using the external respiratory and cardiac data and the --temporalregression parameter. I compared the cleaned data file (XXX_desc-cardfilterCleaned_bold.nii.gz) with the raw file and it looks like the cleaned file is skull stripped. Is this something that usually happens while running happy?

Temporal regression is only performed on voxels within the projection mask. If you don’t explicitly set the projection mask, it sets the projection mask to be equal to the process mask, which, if you have not set IT explicitly, is in turn calculated from the raw EPI data using the make_epi_mask function from nilearn. That’s the most common path (I assume you didn’t set either of those masks explicitly). So that will limit the fit to the brain.

If you want to perform the regression all over the image (not just the brain), specify the projection mask on the command line (--projmask MASKNAME), and make it a 3D volume that is non-zero in all the voxels you want to perform regression on (for example, fill it with ones).