physiopy / phys2denoise

A collection of scripts to prepare physiology data for fMRI denoise
https://phys2denoise.readthedocs.io/
Apache License 2.0
9 stars 19 forks source link

Improved RVT calculation with Hilbert transform #10

Open tsalo opened 3 years ago

tsalo commented 3 years ago

Harrison et al. (2020) proposes a new filtering approach when calculating respiration-based metrics (especially respiratory volume per unit time [RVT]) that is supposedly better able to capture atypical breathing (e.g., deep breaths). While it's just a preprint, I think it's worth looking into this method to see if it's worth supporting in phys2denoise.

Here are the details of the algorithm, taken from the manuscript:

  1. PhysIO preprocessing: Remove low frequency drifts (less than 0.01 Hz) from the breathing signal, and remove high-frequency noise above 2.0 Hz. This version of the breathing signal is used for both RETROICOR and the peak-based RVT estimate in the physiological pipelines used in the Results section. This is the raw trace shown in Panel (a) of Figure 3.
  2. Lowpass filter the data again to more aggressively remove high-frequency noise above 0.75 Hz. This is the raw trace shown in Figure 1.
  3. Decompose the signal into magnitude and phase components via the Hilbert transform.
  4. Linearly interpolate any periods where the phase time course decreases, using the procedure in Figure 2, to remove any artefactual negative frequencies. Reconstruct the oscillatory portion of the signal, cos(𝜙(𝑡)), and lowpass filter at 0.75 Hz to remove any resulting artefacts. This procedure is repeated 10 times, with the new phase timecourse re- estimated from the filtered oscillatory signal.
  5. Calculate RV and low-pass filter the signal magnitude at 0.2 Hz to remove within-cycle fluctuations. Instantaneous breathing frequency is the numerical derivative of the phase timecourse, filtered as above. Finally, estimates are thresholded to remove physiologically implausible values.
tsalo commented 3 years ago

I think I've got a mostly functional prototype up in this notebook.

CesarCaballeroGaudes commented 3 years ago

I was playing with the previous version when "there was something iffy with the way I did the filtering". It seems you got it sorted. Regarding your questions about 2*np.pi, it seems to normalize radians. Anyway, it is an scaling factor that does not influence the rest of the commands (unless the ones in the notebook)

tsalo commented 3 years ago

Thanks! That's really helpful. I was just working on moving the contents (without changes) to a new branch, so I'm going to open a draft PR if you want to add any comments directly.