{ "cells": [ { "cell_type": "markdown", "metadata": { "kernel": "SoS" }, "source": [ "## Benefits and Pitfalls" ] }, { "cell_type": "markdown", "metadata": { "kernel": "SoS" }, "source": [ "
\n", "The conventional inversion recovery experiment is considered the gold standard T1 mapping technique for several reasons. A typical protocol has a long TR value and a sufficient number of inversion times for stable fitting (typically 5 or more) covering the range [0, TR]. It offers a wide dynamic range of signals (up to [-kM0, kM0]), allowing a number of inversion times where high SNR is available to sample the signal recovery curve (Fukushima 1981). T1 maps produced by inversion recovery are largely insensitive to inaccuracies in excitation flip angles and imperfect spoiling (Stikov et al. 2015), as all parameters except TI are constant for each measurement and only a single acquisition is performed (at TI) during each TR. One important pulse sequence design consideration is to avoid acquiring at inversion times where the signal for T1 values of the tissue-of-interest is nulled, as the magnitude images at this TI time will be dominated by Rician noise which can negatively impact the fit under low SNR circumstances (Figure 6). Inversion recovery can also often be acquired using commonly available standard pulse sequences available on most MRI scanners by setting up a customized acquisition protocol, and does not require any additional calibration measurements.\n", "
" ] }, { "cell_type": "markdown", "metadata": { "kernel": "SoS" }, "source": [ "\n", "\n", "Figure 6. Monte Carlo simulations (mean and standard deviation (STD), blue markers) and fitted T1 values (mean and STD, red and green respectively) generated for a T1 value of 900 ms and 5 TI values linearly spaced across the TR (ranging from 1 to 5 s). A bump in T1 STD occurs near TR = 3000 ms, which coincides with the TR where the second TI is located near a null point for this T1 value. \n", "\n", "
" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "kernel": "Octave", "tags": [ "hidecode" ] }, "outputs": [], "source": [ "%use octave\n", "\n", "% Verbosity level 0 overrides the disp function and supresses warnings.\n", "% Once executed, they cannot be restored in this session\n", "% (kernel needs to be restarted or a new notebook opened.)\n", "VERBOSITY_LEVEL = 0;\n", "\n", "if VERBOSITY_LEVEL==0\n", " % This hack was used to supress outputs from external tools\n", " % in the Jupyter Book.\n", " function disp(x)\n", " end\n", " warning('off','all')\n", "end\n", "\n", "try\n", " cd qMRLab\n", "catch\n", " try\n", " cd ../../../qMRLab\n", " catch\n", " cd ../qMRLab\n", " end\n", "end\n", "\n", "startup\n", "clear all\n", "\n", "%% Setup parameters\n", "% All times are in seconds\n", "% All flip angles are in degrees\n", "\n", "TR_range = 1000:100:5000; % in seconds\n", "\n", "x = struct;\n", "x.T1 = 900; % in seconds\n", "\n", "Opt.SNR = 25;\n", "Opt.M0 = 1;\n", "Opt.FAexcite = 90; % Excitation flip angle\n", "Opt.FAinv = 180; % Inversion flip angle\n", "\n", "%% Monte Carlo data simulation\n", "% Simulate noisy signal data 1,000 time, fit the data, then calculate the means and standard deviations of the data and fitted T1\n", "% Data is calculated by calculating the a and b values of Eq. 4 from the full analytical equations (Eq. 1)\n", "\n", "Model = inversion_recovery; \n", "\n", "for ii = 1:length(TR_range)\n", " Opt.TR = TR_range(ii);\n", " Opt.T1 = x.T1;\n", " TI_lowres(ii,:) = linspace(0.05, Opt.TR, 6)';\n", " Model.Prot.IRData.Mat = [TI_lowres(ii,:)];\n", " [ra,rb] = Model.ComputeRaRb(x,Opt);\n", " x.rb = rb;\n", " x.ra = ra;\n", " for jj = 1:1000\n", " [FitResult{ii,jj}, noisyData{ii,jj}] = Model.Sim_Single_Voxel_Curve(x,Opt,0); \n", " fittedT1(ii,jj) = FitResult{ii,jj}.T1;\n", " noisyData_array(ii,jj,:) = noisyData{ii,jj}.IRData;\n", " end\n", " \n", " for kk=1:length(TI_lowres(ii,:))\n", " data_mean(ii,kk) = mean(noisyData_array(ii,:,kk));\n", " data_std(ii,kk) = std(noisyData_array(ii,:,kk));\n", " end\n", " \n", " T1_mean(ii) = mean(fittedT1(ii,:));\n", " T1_std(ii) = std(fittedT1(ii,:));\n", "end\n", "\n", "%% Calculate the noiseless data at a higher TI resolution to plot the ideal signal curve.\n", "%\n", "\n", "for ii = 1:length(TR_range)\n", " TI_highres(ii,:) = linspace(0.05, TR_range(ii), 500);\n", " Model.Prot.IRData.Mat = [TI_highres(ii,:)];\n", " Opt.TR = TR_range(ii);\n", " Opt.T1 = x.T1;\n", " [ra,rb] = Model.ComputeRaRb(x,Opt);\n", " x.rb = rb;\n", " x.ra = ra;\n", "\n", " data_noiseless(ii,:) = Model.equation(x);\n", "end" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "kernel": "SoS", "tags": [ "hidecode" ] }, "outputs": [ { "data": { "text/html": [ "" ], "text/vnd.plotly.v1+html": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "\n", "Despite a widely acknowledged robustness for measuring accurate T1 maps, inversion recovery is not often used in studies. An important drawback of this technique is the need for long TR values, generally on the order of a few T1 for general models (e.g. Eqs. 1 and 4), and up to 5T1 for long TR approximated models (Eq. 3). It takes about to 10-25 minutes to acquire a single-slice T1 map using the inversion recovery technique, as only one TI is acquired per TR (2-5 s) and conventional cartesian gradient readout imaging acquires one phase encode line per excitation (for a total of ~100-200 phase encode lines). The long acquisition time makes it challenging to acquire whole-organ T1 maps in clinically feasible protocol times. Nonetheless, it is useful as a reference measurement for comparisons against other T1 mapping methods, or to acquire a single-slice T1 map of a tissue to get T1 estimates for optimization of other pulse sequences.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "kernel": "Python3" }, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Tags", "kernelspec": { "display_name": "SoS", "language": "sos", "name": "sos" }, "language_info": { "codemirror_mode": "sos", "file_extension": ".sos", "mimetype": "text/x-sos", "name": "sos", "nbconvert_exporter": "sos_notebook.converter.SoS_Exporter", "pygments_lexer": "sos" }, "sos": { "kernels": [ [ "Octave", "octave", "Octave", "#dff8fb" ], [ "Python3", "python3", "Python3", "#FFD91A" ], [ "SoS", "sos", "", "" ] ], "panel": { "displayed": true, "height": 0, "style": "side" }, "version": "0.17.2" } }, "nbformat": 4, "nbformat_minor": 2 }