Benefits and Pitfalls#

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 protocol 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. For an example, please visit the interactive preprint of the ISMRM Reproducible Research Group 2020 Challenge on inversion recovery T1 mapping [Boudreau et al., 2023].

Hide code cell source
from repo2data.repo2data import Repo2Data
import os 
import pickle
import matplotlib.pyplot as plt
import chart_studio.plotly as py
import plotly.graph_objs as go
import numpy as np
from plotly import __version__
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
from IPython.display import display, HTML

data_req_path = os.path.join("..","..", "binder", "data_requirement.json")
repo2data = Repo2Data(data_req_path)
DATA_ROOT = os.path.join(repo2data.install()[0],"t1-book-neurolibre")
Hide code cell output
---- repo2data starting ----
/srv/conda/envs/notebook/lib/python3.8/site-packages/repo2data
Config from file :
../../binder/data_requirement.json
Destination:
../../data/qmrlab-t1-book

Info : ../../data/qmrlab-t1-book already downloaded

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.

Hide code cell source
filename = os.path.join(DATA_ROOT,"01",'figure_6.pkl')

with open(filename, 'rb') as f:
    TR_range, TI_lowres, TI_highres, T1_mean, T1_std, data_mean, data_std, data_noiseless = pickle.load(f)

config={'showLink': False, 'displayModeBar': False}

init_notebook_mode(connected=True)

data1 = [dict(
        visible = False,
        x = np.squeeze(np.asarray(TI_lowres[ii,:])),
        y = np.squeeze(np.asarray(data_mean[ii,:])),
        error_y=dict(
            type='data',
            color = ('rgb(22, 96, 167)'),
            array=np.squeeze(np.asarray(data_std[ii,:])),
            visible=True
        ),
        line = dict(
            color = ('rgb(22, 96, 167)'),
            dash = 'dot'),
        mode = 'markers',
        name = 'Monte Carlo simulated signal',
        text = 'Monte Carlo simulated signal',
        hoverinfo = 'x+y+text') for ii in range(len(TR_range))]

data1[28]['visible'] = True

data2 = [dict(
        visible = False,
        x = np.squeeze(np.asarray(TI_highres[ii,:])),
        y = np.squeeze(np.asarray(data_noiseless[ii,:])),
        line = dict(
            color = ('rgb(247, 152, 19)'),
            ),
        name = 'Noiseless signal',
        text = 'Noiseless signal',
        hoverinfo = 'x+y+text') for ii in range(len(TR_range))]

data2[28]['visible'] = True

data_meanT1 = [dict(
    visible = False,
    x = TR_range,
    y = T1_mean,
    name = 'Mean T<sub>1</sub> (s)',
    text = 'Mean T<sub>1</sub> (s)',
    hoverinfo = 'x+y+text',
    xaxis='x2',
    yaxis='y2') for ii in range(len(TR_range))]

data_meanT1[15]['visible'] = True

data_stdT1 = [dict(
    visible = False,
    x = TR_range,
    y = T1_std,
    line = dict(
        color = ('rgb(222, 22, 22)'),
        ),
    name = 'STD T<sub>1</sub> (s)',
    text = 'STD T<sub>1</sub> (s)',
    hoverinfo = 'x+y+text',
    xaxis='x2',
    yaxis='y3') for ii in range(len(TR_range))]

data_stdT1[28]['visible'] = True

data = data2 + data1 + data_meanT1 + data_stdT1

steps = []
for i in range(len(TR_range)):
    step = dict(
        method = 'restyle',  
        args = ['visible', [False] * len(data1)],
        label = str(TR_range[i])
    )
    step['args'][1][i] = True # Toggle i'th trace to "visible"
    steps.append(step)

sliders = [dict(
    x = 0,
    y = -0.02,
    active = 28,
    currentvalue = {"prefix": "TR value (ms): <b>"},
    pad = {"t": 50, "b": 10},
    steps = steps
)]

layout = go.Layout(
    width=540,
    height=540,
    margin = dict(
                t=0,
                r=25,
                b=100,
                l=75),
    annotations=[
        dict(
            x=0.5004254919715793,
            y=-0.17,
            showarrow=False,
            text='Inversion Time – TI (ms)',
            font=dict(
                family='Times New Roman',
                size=26
            ),
            xref='paper',
            yref='paper'
        ),
        dict(
            x=-0.15,
            y=0.5,
            showarrow=False,
            text='Signal (magnitude)',
            font=dict(
                family='Times New Roman',
                size=26
            ),
            textangle=-90,
            xref='paper',
            yref='paper'
        ),
        dict(
            x=0.76,
            y=0.77,
            showarrow=False,
            text='<b>TR (ms)<b>',
            font=dict(
                family='Times New Roman',
                size=14
            ),
            xref='paper',
            yref='paper'
        ),
        dict(
            x=0.40,
            y=0.35,
            showarrow=False,
            text='<b>Mean T<sub>1</sub> (ms)<b>',
            font=dict(
                family='Times New Roman',
                size=14
            ),
            textangle=-90,
            xref='paper',
            yref='paper'
        ),
        dict(
            x=1.00,
            y=0.35,
            showarrow=False,
            text='<b>STD T<sub>1</sub> (ms)<b>',
            font=dict(
                family='Times New Roman',
                size=14
            ),
            textangle=-90,
            xref='paper',
            yref='paper'
        )
    ],
    xaxis=dict(
        autorange=False,
        range=[0, 5000],
        showgrid=False,
        linecolor='black',
        linewidth=2
    ),
    yaxis=dict(
        autorange=False,
        range=[0, 1],
        showgrid=False,
        linecolor='black',
        linewidth=2
    ),
    xaxis2=dict(
        domain=[0.5, 0.90],
        anchor='y2',
        mirror = True,
        side='top',
        ticks='inside',
        showline=True,
    ),
    yaxis2=dict(
        autorange=False,
        range=[500, 1300],
        domain=[0.05, 0.65],
        anchor='x2',
        mirror = True,
        ticks='inside',
        showline=True,
    ),
    yaxis3=dict(
        autorange=False,
        range=[0, 190],
        domain=[0.05, 0.65],
        anchor='x2',
        overlaying='y2',
        side='right',
        ticks='inside',
    ),
    legend=dict(
        x=0.3,
        y=1.35,
        traceorder='normal',
        font=dict(
            family='Times New Roman',
            size=12,
            color='#000'
        ),
        bordercolor='#000000',
        borderwidth=2
    ), 
    sliders=sliders,
    plot_bgcolor='white'
)

fig = dict(data=data, layout=layout)

plot(fig, filename = 'ir_fig_6.html', config = config)
display(HTML('ir_fig_6.html'))

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.


References

1

Mathieu Boudreau, Agah Karakuzu, Julien Cohen-Adad, Ecem Bozkurt, Madeline Carr, Marco Castellaro, Luis Concha, Mariya Doneva, Seraina Dual, Alex Ensworth, Alexandru Foias, Véronique Fortier, Refaat E. Gabr, Guillaume Gilbert, Carri K. Glide-Hurst, Matthew Grech-Sollars, Siyuan Hu, Oscar Jalnefjord, Jorge Jovicich, Kübra Keskin, Peter Koken, Anastasia Kolokotronis, Simran Kukran, Nam. G. Lee, Ives R. Levesque, Bochao Li, Dan Ma, Burkhard Mädler, Nyasha Maforo, Jamie Near, Erick Pasaye, Alonso Ramirez-Manzanares, Ben Statton, Christian Stehning, Stefano Tambalo, Ye Tian, Chenyang Wang, Kilian Weis, Niloufar Zakariaei, Shuo Zhang, Ziwei Zhao, and Nikola Stikov. Results of the ismrm 2020 joint reproducible research & quantitative mr study groups reproducibility challenge on phantom and human brain t1 mapping. NeuroLibre Reproducible Preprints, 2023. doi:10.55458/neurolibre.00014.

2

Eiichi Fukushima. Experimental pulse NMR: a nuts and bolts approach. CRC Press, 1981. doi:10.1201/9780429493867.

3

Nikola Stikov, Mathieu Boudreau, Ives R. Levesque, Christine L. Tardif, Joëlle K. Barral, and G. Bruce Pike. On the accuracy of t1 mapping: searching for common ground. Magnetic Resonance in Medicine, 73(2):514–522, 2015. arXiv:https://onlinelibrary.wiley.com/doi/pdf/10.1002/mrm.25135, doi:10.1002/mrm.25135.