happy

Description:

happy is a new addition to the rapidtide suite. It’s complementary to rapidtide - it’s focussed on fast, cardiac signals in fMRI, rather than the slow, LFO signals we are usually looking at. It’s sort of a Frankenprogram - it has three distinct jobs, which are related, but are very distinct.

The first thing happy does is try to extract a cardiac waveform from the fMRI data. This is something I’ve been thinking about for a long time. Words go here

The second task is to take this raw estimate of the cardiac waveform, and clean it up using a deep learning filter. The original signal is useful, but pretty gross, but I figured you should be able to exploit the pseudoperiodic nature of the signal to greatly improve it. This is also a testbed to work on using neural nets to process time domain signals. It seemed like a worthwhile project, so it got grafted in.

The final task (which was actually the initial task, and the reason I wrote happy to begin with) is to implement Henning Voss’ totally cool hypersampling with analytic phase projection (guess where the name “happy” comes from). This is fairly straightforward, as Voss describes his method very clearly. But I have lots of data with no simultaneously recorded cardiac signals, and I was too lazy to go find datasets with pleth data to play with, so that’s why I did the cardiac waveform extraction part.

Inputs:

Happy needs a 4D BOLD fMRI data file (space by time) as input. This can be Nifti1 or Nifti2. If you have a simultaneously recorded cardiac waveform, it will happily use it, otherwise it will try to construct (and refine) one. NOTE: the 4D input dataset needs to be completely unpreprocessed - gradient distortion correction and motion correction can destroy the relationship between slice number and actual acquisition time, and slice time correction does not behave as expected for aliased signals (which the cardiac component in fMRI most certainly is), and in any case we need the slice time offsets to construct our waveform.

Outputs:

Outputs are space or space by time Nifti or text files, depending on what the input data file was, and some text files containing textual information, histograms, or numbers. File formats and naming follow BIDS conventions for derivative data for fMRI input data. Output spatial dimensions and file type match the input dimensions and file type (Nifti1 in, Nifti1 out). Depending on the file type of map, there can be no time dimension, a time dimension that matches the input file, or something else, such as a time lag dimension for a correlation map.

BIDS Outputs:

Name

Extension(s)

Content

When present

XXX_commandline

.txt

The command line used to run happy

Always

XXX_formattedcommandline

.txt

The command line used to run happy, attractively formatted

Always

XXX_desc-rawapp_info

.nii.gz

The analytic phase projection map of the cardiac waveform

Always

XXX_desc-app_info

.nii.gz

The analytic phase projection map of the cardiac waveform, voxelwise minimum subtracted

Always

XXX_desc-normapp_info

.nii.gz

The analytic phase projection map of the cardiac waveform, voxelwise minimum subtracted and normalized

Always

XXX_desc-apppeaks_hist

.tsv.gz, .json

Not sure

Always

XXX_desc-apppeaks_hist_centerofmass

.txt

Not sure

Always

XXX_desc-apppeaks_hist_peak

.txt

Not sure

Always

XXX_desc-slicerescardfromfmri_timeseries

.tsv.gz, .json

Cardiac timeseries at the time resolution of slice acquisition ((1/TR * number of slices / multiband factor

Always

XXX_desc-stdrescardfromfmri_timeseries

.tsv.gz, .json

Cardiac timeseries at standard time resolution (25.O Hz)

Always

XXX_desc-cardpulsefromfmri_timeseries

.tsv.gz, .json

The average (over time from minimum) of the cardiac waveform over all voxels

Always

XXX_desc-cardiaccyclefromfmri_timeseries

.tsv.gz, .json

The average (over a single cardiac cycle) of the cardiac waveform over all voxels

Always

XXX_desc-cine_info

.nii.gz

Average image of the fMRI data over a single cardiac cycle

Always

XXX_desc-cycleaverage_timeseries

.tsv.gz, .json

Not sure

Always

XXX_desc-maxphase_map

.nii.gz

Map of the average phase where the maximum amplitude occurs for each voxel

Always

XXX_desc-minphase_map

.nii.gz

Map of the average phase where the minimum amplitude occurs for each voxel

Always

XXX_desc-processvoxels_mask

.nii.gz

Map of all voxels used for analytic phase projection

Always

XXX_desc-vessels_map

.nii.gz

Amplitude of variance over a cardiac cycle (large values are assumed to be vessels)

Always

XXX_desc-vessels_mask

.nii.gz

Locations of voxels with variance over a cardiac cycle that exceeds a threshold (assumed to be vessels)

Always

XXX_desc-arteries_map

.nii.gz

High variance vessels with early maximum values within the cardiac cycle

Always

XXX_desc-veins_map

.nii.gz

High variance vessels with late maximum values within the cardiac cycle

Always

XXX_info

.json

Run parameters and derived values found during the run (quality metrics, derived thresholds, etc.)

Always

XXX_memusage

.csv

Memory statistics at multiple checkpoints over the course of the run

Always

XXX_runtimings

.txt

Detailed timing information

Always

Usage:

Hypersampling by Analytic Phase Projection - Yay!.

usage: happy [-h] [--cardcalconly] [--skipdlfilter]
             [--usesuperdangerousworkaround] [--slicetimesareinseconds]
             [--model MODELNAME] [--mklthreads NTHREADS] [--numskip SKIP]
             [--motskip SKIP] [--motionfile MOTFILE] [--motionhp HPFREQ]
             [--motionlp LPFREQ] [--nomotorthogonalize] [--motpos]
             [--nomotderiv] [--discardmotionfiltered] [--estmask MASKNAME]
             [--minhr MINHR] [--maxhr MAXHR] [--minhrfilt MINHR]
             [--maxhrfilt MAXHR] [--hilbertcomponents NCOMPS]
             [--envcutoff CUTOFF] [--notchwidth WIDTH] [--invertphysiosign]
             [--cardiacfile FILE[:COL]]
             [--cardiacfreq FREQ | --cardiactstep TSTEP]
             [--cardiacstart START] [--forcehr BPM]
             [--respirationfile FILE[:COL]]
             [--respirationfreq FREQ | --respirationtstep TSTEP]
             [--respirationstart START] [--forcerr BreathsPM] [--spatialglm]
             [--temporalglm] [--stdfreq FREQ] [--outputbins BINS]
             [--gridbins BINS] [--gridkernel {old,gauss,kaiser}]
             [--projmask MASKNAME] [--projectwithraw] [--fliparteries]
             [--arteriesonly] [--version] [--detailedversion]
             [--aliasedcorrelation] [--upsample] [--estimateflow]
             [--noprogressbar] [--infotag tagkey tagvalue] [--debug]
             [--nodetrend DETRENDORDER] [--noorthog] [--disablenotch]
             [--nomask] [--nocensor] [--noappsmooth] [--nophasefilt]
             [--nocardiacalign] [--saveinfoastext] [--saveintermediate]
             [--increaseoutputlevel] [--decreaseoutputlevel]
             fmrifilename slicetimename outputroot

Positional Arguments

fmrifilename

The input data file (BOLD fmri file or NIRS text file)

slicetimename

Text file containing the offset time in seconds of each slice relative to the start of the TR, one value per line, OR the BIDS sidecar JSON file.NB: FSL slicetime files give slice times in fractions of a TR, BIDS sidecars give slice times in seconds. Non-json files are assumed to be the FSL style (fractions of a TR) UNLESS the –slicetimesareinseconds flag is used.

outputroot

The root name for the output files

Processing steps

--cardcalconly

Stop after all cardiac regressor calculation steps (before phase projection).

Default: False

--skipdlfilter

Disable deep learning cardiac waveform filter.

Default: True

--usesuperdangerousworkaround

Some versions of tensorflow seem to have some weird conflict with MKL whichI don’t seem to be able to fix. If the dl filter bombs complaining about multiple openmp libraries, try rerunning with the secret and inadvisable ‘–usesuperdangerousworkaround’ flag. Good luck!

Default: False

--slicetimesareinseconds

If a non-json slicetime file is specified, happy assumes the file is FSL style (slice times are specified in fractions of a TR). Setting this flag overrides this assumption, and interprets the slice time file as being in seconds. This does nothing when the slicetime file is a .json BIDS sidecar.

Default: False

--model

Use model MODELNAME for dl filter (default is model_revised - from the revised NeuroImage paper.

Default: “model_revised”

Performance

--mklthreads

Use NTHREADS MKL threads to accelerate processing (defaults to 1 - more threads up to the number of cores can accelerate processing a lot, but can really kill you on clusters unless you’re very careful. Use at your own risk

Default: 1

Preprocessing

--numskip

Skip SKIP tr’s at the beginning of the fMRI file (default is 0).

Default: 0

--motskip

Skip SKIP tr’s at the beginning of the motion regressor file (default is 0).

Default: 0

--motionfile

Read 6 columns of motion regressors out of MOTFILE file (.par or BIDS .json) (with timepoints rows) and regress them, their derivatives, and delayed derivatives out of the data prior to analysis.

--motionhp

Highpass filter motion regressors to HPFREQ Hz prior to regression.

--motionlp

Lowpass filter motion regressors to LPFREQ Hz prior to regression.

--nomotorthogonalize

Do not orthogonalize motion regressors prior to regressing them out of the data.

Default: True

--motpos

Include motion position regressors.

Default: False

--nomotderiv

Do not use motion derivative regressors.

Default: True

--discardmotionfiltered

Do not save data after motion filtering.

Default: True

Cardiac estimation tuning

--estmask

Generation of cardiac waveform from data will be restricted to voxels in MASKNAME and weighted by the mask intensity. If this is selected, happy will only make a single pass through the data (the initial vessel mask generation pass will be skipped).

--minhr

Limit lower cardiac frequency search range to MINHR BPM (default is 40).

Default: 40.0

--maxhr

Limit upper cardiac frequency search range to MAXHR BPM (default is 140).

Default: 140.0

--minhrfilt

Highpass filter cardiac waveform estimate to MINHR BPM (default is 40).

Default: 40.0

--maxhrfilt

Lowpass filter cardiac waveform estimate to MAXHR BPM (default is 1000).

Default: 1000.0

--hilbertcomponents

Retain NCOMPS components of the cardiac frequency signal to Hilbert transform (default is 1).

Default: 1

--envcutoff

Lowpass filter cardiac normalization envelope to CUTOFF Hz (default is 0.4 Hz).

Default: 0.4

--notchwidth

Set the width of the notch filter, in percent of the notch frequency (default is 1.5).

Default: 1.5

--invertphysiosign

Invert the waveform extracted from the physiological signal. Use this if there is a contrast agent in the blood.

Default: False

External cardiac waveform options

--cardiacfile

Read the cardiac waveform from file FILE. If COL is an integer, and FILE is a text file, use the COL’th column. If FILE is a BIDS format json file, use column named COL. If no file is specified, estimate the cardiac signal from the fMRI data.

--cardiacfreq

Cardiac waveform in cardiacfile has sample frequency FREQ (default is 32Hz). NB: –cardiacfreq and –cardiactstep are two ways to specify the same thing.

Default: -32.0

--cardiactstep

Cardiac waveform in cardiacfile has time step TSTEP (default is 1/32 sec). NB: –cardiacfreq and –cardiactstep are two ways to specify the same thing.

Default: -32.0

--cardiacstart

The time delay in seconds into the cardiac file, corresponding to the first TR of the fMRI file (default is 0.0)

--forcehr

Force heart rate fundamental detector to be centered at BPM (overrides peak frequencies found from spectrum). Usefulif there is structured noise that confuses the peak finder.

External respiration waveform options

--respirationfile

Read the respiration waveform from file FILE. If COL is an integer, and FILE is a text file, use the COL’th column. If FILE is a BIDS format json file, use column named COL.

--respirationfreq

Respiration waveform in respirationfile has sample frequency FREQ (default is 32Hz). NB: –respirationfreq and –respirationtstep are two ways to specify the same thing.

Default: -32.0

--respirationtstep

Respiration waveform in respirationfile has time step TSTEP (default is 1/32 sec). NB: –respirationfreq and –respirationtstep are two ways to specify the same thing.

Default: -32.0

--respirationstart

The time delay in seconds into the respiration file, corresponding to the first TR of the fMRI file (default is 0.0)

--forcerr

Force respiratory rate fundamental detector to be centered at BreathsPM (overrides peak frequencies found from spectrum). Usefulif there is structured noise that confuses the peak finder.

Output processing

--spatialglm

Generate framewise cardiac signal maps and filter them out of the input data.

Default: False

--temporalglm

Generate voxelwise aliased synthetic cardiac regressors and filter them out of the input data.

Default: False

Output options

--stdfreq

Frequency to which the physiological signals are resampled for output. Default is 25.

Default: 25.0

Phase projection tuning

--outputbins

Number of output phase bins (default is 32).

Default: 32

--gridbins

Width of the gridding kernel in output phase bins (default is 3.0).

Default: 3.0

--gridkernel

Possible choices: old, gauss, kaiser

Convolution gridding kernel. Default is kaiser

Default: “kaiser”

--projmask

Phase projection will be restricted to voxels in MASKNAME (overrides normal intensity mask.)

--projectwithraw

Use fMRI derived cardiac waveform as phase source for projection, even if a plethysmogram is supplied.

Default: False

--fliparteries

Attempt to detect arterial signals and flip over the timecourses after phase projection (since relative arterial blood susceptibility is inverted relative to venous blood).

Default: False

--arteriesonly

Restrict cardiac waveform estimation to putative arteries only.

Default: False

Version options

--version

Show simplified version information and exit

--detailedversion

Show detailed version information and exit

Miscellaneous options.

--aliasedcorrelation

Attempt to calculate absolute delay using an aliased correlation (experimental).

Default: False

--upsample

Attempt to temporally upsample the fMRI data (experimental).

Default: False

--estimateflow

Estimate blood flow using optical flow (experimental).

Default: False

--noprogressbar

Will disable showing progress bars (helpful if stdout is going to a file).

Default: True

--infotag

Additional key, value pairs to add to the info json file (useful for tracking analyses).

Debugging options (probably not of interest to users)

--debug

Turn on debugging information.

Default: False

--nodetrend

Disable data detrending.

Default: 3

--noorthog

Disable orthogonalization of motion confound regressors.

Default: True

--disablenotch

Disable subharmonic notch filter.

Default: False

--nomask

Disable data masking for calculating cardiac waveform.

Default: True

--nocensor

Bad points will not be excluded from analytic phase projection.

Default: True

--noappsmooth

Disable smoothing app file in the phase direction.

Default: True

--nophasefilt

Disable the phase trend filter (probably not a good idea).

Default: True

--nocardiacalign

Disable alignment of pleth signal to fMRI derived cardiac signal.

Default: True

--saveinfoastext

Save the info file in text format rather than json.

Default: True

--saveintermediate

Save some data from intermediate passes to help debugging.

Default: False

--increaseoutputlevel

Increase the number of intermediate output files.

Default: 0

--decreaseoutputlevel

Decrease the number of intermediate output files.

Default: 0

Example:

Extract the cardiac waveform and generate phase projections

Case 1: When you don’t have a pleth recording

There are substantial improvements to the latest versions of happy. In the old versions, you actually had to run happy twice - the first time to estimate the vessel locations, and the second to actually derive the waveform. Happy now combines these operations interpolation a single run with multiple passes - the first pass locates voxels with high variance, labels them as vessels, then reruns the derivation, restricting the cardiac estimation to these high variance voxels. This gives substantially better results.

Using the example data in the example directory, try the following:

happy \
    rapidtide/data/examples/src/sub-HAPPYTEST.nii.gz \
    rapidtide/data/examples/src/sub-HAPPYTEST.json \
    rapidtide/data/examples/dst/happytest

This will perform a happy analysis on the example dataset. To see the extracted cardiac waveform (original and filtered), you can use showtc (also part of them rapidtide package):

showtc \
    rapidtide/data/examples/src/happytest_desc-slicerescardfromfmri_timeseries.json:cardiacfromfmri,cardiacfromfmri_dlfiltered \
    --format separate