DEcomposition and Component Analysis of Exponential Signals (DECAES)
DECAES is a fast Julia implementation of the MATLAB toolbox from the UBC MRI Research Centre for computing voxelwise T2-distributions from multi spin-echo MRI images using the extended phase graph algorithm with stimulated echo corrections. Post-processing of these T2-distributions allows for the computation of measures such as the myelin water fraction (MWF) or the luminal water fraction (LWF).
DECAES is written in the open-source Julia programming language.
Julia and command line interfaces are available through this package.
The examples repository additionally provides a MATLAB interface via the MATLAB function decaes.m
.
If you use DECAES in your research, please cite our work.
Installation
In Julia v1.3 or later you can install DECAES from the Pkg REPL:
pkg> add DECAES
Command Line Interface
This toolbox provides a command line interface (CLI) for processing from the terminal. The CLI takes image files as inputs and performs one or both of T2-distribution computation and T2-parts analysis, the latter of which performs post-processing of the T2-distribution to calculate parameters such as the MWF or LWF. The input image must be one of the following file types:
- NIfTI file with extension
.nii
, or gzip compressed NIfTI file with extension.nii.gz
- MATLAB file with extension
.mat
- Philips PAR/REC file pair with extensions
.par
and.rec
(or.PAR
and.REC
) - Philips XML/REC file pair with extensions
.xml
and.rec
(or.XML
and.REC
)
All output files are saved as .mat
files in format v7.3
.
- Note: if your data is in DICOM format, the freely available
dcm2niix
tool is able to convert DICOM files into NIfTI format.
Basic usage
There are two equivalent ways to use the CLI, assuming DECAES is already installed:
1. Helper script: Create a script called e.g. decaes.jl
with the following contents:
using DECAES # load the package
main() # call CLI entrypoint function
This script can then be invoked from the command line as follows:
$ export JULIA_NUM_THREADS=4 # set JULIA_NUM_THREADS > 1 to enable parallel processing
$ julia decaes.jl <COMMAND LINE ARGS>
2. Julia -e
flag: The contents of the above script can be written directly at the command line using the -e
(for "evaluate") flag:
$ export JULIA_NUM_THREADS=4
$ julia -e 'using DECAES; main()' -- <COMMAND LINE ARGS>
Documentation
Find package documentation at the above link, which includes:
- The command line interface API, available command line arguments, and examples
- API reference detailing how to use DECAES.jl from within Julia
- Other internals and algorithmic details
Examples repository
See the examples repository for a walk-through guide for using the CLI, including example CPMG data for performing MWI, as well as a script for calling the CLI from MATLAB.
Citing this work
If you use DECAES in your research, please cite the following:
@article{DECAES.jl-2020,
title = {{{DECAES}} - {{DEcomposition}} and {{Component Analysis}} of {{Exponential Signals}}},
author = {Doucette, Jonathan and Kames, Christian and Rauscher, Alexander},
year = {2020},
month = may,
issn = {1876-4436},
doi = {10.1016/j.zemedi.2020.04.001},
journal = {Zeitschrift Fur Medizinische Physik},
keywords = {Brain,Luminal Water Imaging,MRI,Myelin Water Imaging,Prostate},
language = {eng},
pmid = {32451148}
}
Benchmarks
Comparison of processing time on various data sets.
The MATLAB implementation uses the scripts contained within the MWI_NNLS_toolbox_0319
folder in the ubcmwf github repository.
The Julia implementation uses DECAES.jl.
Processor: 3.60GHz Intel Core i7-7700 with 4 CPU cores/8 threads:
Toolbox | Parallelism | Image Size | T2-Distribution | Speedup | Total Time | Speedup |
---|---|---|---|---|---|---|
MWI_NNLS_toolbox_0319 | 4 workers + parfor | 240x240x48x48 + mask | 01h:29m:35s | - | 01h:30m:37s | - |
DECAES | 4 threads | 240x240x48x48 + mask | 00h:01m:35s | 57X | 00h:02m:34s | 35X |
DECAES | 8 threads | 240x240x48x48 + mask | 00h:01m:24s | 64X | 00h:02m:14s | 41X |
MWI_NNLS_toolbox_0319 | 4 workers + parfor | 240x240x113x56 + mask | 02h:25m:19s | - | 02h:27m:52s | - |
DECAES | 4 threads | 240x240x113x56 + mask | 00h:02m:34s | 57X | 00h:04m:00s | 37X |
DECAES | 8 threads | 240x240x113x56 + mask | 00h:02m:20s | 62X | 00h:03m:38s | 41X |
MWI_NNLS_toolbox_0319 | 4 workers + parfor | 240x240x48x48 | 02h:53m:13s | - | 02h:54m:24s | - |
DECAES | 8 threads | 240x240x48x48 | 00h:03m:35s | 48X | 00h:04m:11s | 42X |
MWI_NNLS_toolbox_0319 | 4 workers + parfor | 240x240x113x56 | 09h:35m:17s | - | 09h:39m:33s | - |
DECAES | 8 threads | 240x240x113x56 | 00h:11m:49s | 49X | 00h:12m:36s | 46X |
Processor: 2.10GHz Intel Xeon Gold 6130 with 16 CPU cores/32 threads:
Toolbox | Parallelism | Image Size | T2-Distribution | Total Time |
---|---|---|---|---|
DECAES | 4 threads | 240x240x48x48 + mask | 04m:01s | 04m:14s |
DECAES | 8 threads | 240x240x48x48 + mask | 02m:13s | 02m:28s |
DECAES | 16 threads | 240x240x48x48 + mask | 01m:11s | 01m:24s |
DECAES | 32 threads | 240x240x48x48 + mask | 00m:57s | 01m:09s |
DECAES | 4 threads | 240x240x113x56 + mask | 05m:56s | 06m:25s |
DECAES | 8 threads | 240x240x113x56 + mask | 03m:45s | 04m:21s |
DECAES | 16 threads | 240x240x113x56 + mask | 02m:09s | 02m:37s |
DECAES | 32 threads | 240x240x113x56 + mask | 01m:40s | 02m:09s |
Note: images sizes which include "+ mask" used brain masks generated with the BET tool (done automatically using the --bet
flag for DECAES, and manually for MATLAB) and only processed voxels within the brain mask.
The T2-Distribution column shows the time taken to complete the most costly step of the analysis pipeline, calling the function T2mapSEcorr
.
This function performs the voxelwise nonnegative least-squares (NNLS) analysis to compute T2-distributions.
The Total Time column includes image loading and saving time, Julia startup and compilation time, BET brain mask generation, and the post-processing step of calling the T2partSEcorr
.
Note that MATLAB startup time is not included in the Total Time.
Notes regarding parallelism:
- MATLAB parallelism is implemented via
parfor
loops, executing the independent voxelwise T2-distribution computations in parallel. MATLABparfor
loops are rather restrictive, as each loop iteration is executed on separate MATLAB processes. Each loop iteration must be completed independent from each other, which among other restrictions, means memory cannot be shared between loop iterations. - Julia parallelism is implemented via the more flexible task-based multi-threading model of parallelism. Communication between threads is possible, and memory can be easily shared and reused among threads. This allows one to perform memory allocation up front: thread-local memory buffers, containing e.g. pre-allocated matrices for intermediate calculations, can be created outside of the parallel loop and efficiently re-used.
- Julia multithreading makes use of hyperthreads by default.
It is possible to configure MATLAB to use hyperthreads in
parfor
loops, though it is not generally beneficial and indeed we found a ~20% slowdown.