T1, MTR and MTsat in-vivo

3 healthy participants were scanned with the following MTsat protocol:

The following code cell loads all the necessary Python packages, defines common functions and downloads the data to /tmp/VENUS directory. If data already exists, the download will be skipped.

The number of data points per kernel-density estimations (KDE) were limited to 10k for faster visualization. Lower and upper limits of the distributions are set according to the original publication.

Tip

  • You can use the legend on the right to display a selection of KDEs. For example, double click on G1VENUS to single out vendor-neutral distributions acquired on the GE scanner.

  • At the top right corner of the plot background, you can switch the hover mode to compare data on hover to compare KDEs point by point.

import plotly.graph_objs as go
import plotly.express as px
from plotly import tools, subplots
import numpy as np
import pandas as pd
import ipywidgets as widgets
import math
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
from ipywidgets import interact, interactive, fixed, interact_manual
from IPython.core.display import display, HTML
init_notebook_mode(connected=True)
import scipy.io as sio
import random
random.seed(123)
from plotly.subplots import make_subplots

from repo2data.repo2data import Repo2Data
import os 
data_req_path = os.path.join("..", "binder", "data_requirement.json")
repo2data = Repo2Data(data_req_path)
data_path = repo2data.install()[0]
derivativesDir = os.path.join(data_path,"qMRFlow")

sessions = ['vendor750rev','vendorPRIrev','vendorSKYrev',
           'rth750rev','rthPRIrev','rthSKYrev']
sides = ["negative","negative","negative","positive","positive","positive"]
pointpos = [0,0,-0.14,0.14,0,0]
convert_tag = {'rth750':'G1<sub>VENUS</sub>','rthPRI':'S1<sub>VENUS</sub>','rthSKY':'S2<sub>VENUS</sub>',
               'vendor750':'G1<sub>NATIVE</sub>','vendorPRI':'S1<sub>NATIVE</sub>','vendorSKY':'S2<sub>NATIVE</sub>'}
colors = {'rth750':'rgba(255,8,30,1)','rthPRI':'rgba(255,117,0,1)','rthSKY':'rgba(255,220,0,1)',
         'vendor750':'rgba(0,75,255,1)','vendorPRI':'rgba(24,231,234,1)','vendorSKY':'rgba(24,234,141,1)'}
colors_line = {'rth750':'rgba(255,8,30,0.35)','rthPRI':'rgba(255,117,0,0.35)','rthSKY':'rgba(255,220,0,0.35)',
         'vendor750':'rgba(0,75,255,0.35)','vendorPRI':'rgba(24,231,234,0.35)','vendorSKY':'rgba(24,234,141,0.35)'}

def plot_ridgelines(subject,sessions,metric,region,colors,sides,sampN,leg,lowlim,uplim):
    df = pd.DataFrame()
    traces = []
    for jj in range(0,len(sessions),1):
        avg_array  = []
        std_array  =  []
        cur_region = derivativesDir + '/sub-' + subject  + '/ses-' + sessions[jj] + '/stat/sub-' + subject + '_ses-' + sessions[jj] + '_desc-' + region + '_metrics.mat'
        cur_contents = sio.loadmat(cur_region)
        cur_contents = cur_contents[metric]
        cur_contents = np.delete(cur_contents, np.where(cur_contents < lowlim))
        cur_contents = np.delete(cur_contents, np.where(cur_contents > uplim))
        cur_tag = sessions[jj][0:-3]
        cur_contents = random.sample(list(cur_contents),sampN)
        traces.append(go.Violin(
            x=cur_contents,
            name = convert_tag[cur_tag],
            marker=dict(
            opacity = 0.7,    
            outliercolor='rgba(255, 255, 255, 0.6)',
            line=dict(
                outliercolor='rgba(219, 64, 82, 0.6)',
                outlierwidth=2)),
            line_color= colors[cur_tag],
            legendgroup= convert_tag[cur_tag],
            showlegend=leg,
            side=sides[jj],
            pointpos = pointpos[jj]))
    return traces

def plot_mosaic(metric,axis_title,lowlim,uplim):
    nSamp = 10000
    traces1 = plot_ridgelines('invivo1',sessions,metric,'wm',colors,sides,nSamp,True,lowlim,uplim)
    traces2 = plot_ridgelines('invivo1',sessions,metric,'gm',colors,sides,nSamp,False,lowlim,uplim)
    traces3 = plot_ridgelines('invivo2',sessions,metric,'wm',colors,sides,nSamp,False,lowlim,uplim)
    traces4 = plot_ridgelines('invivo2',sessions,metric,'gm',colors,sides,nSamp,False,lowlim,uplim)
    traces5 = plot_ridgelines('invivo3',sessions,metric,'wm',colors,sides,nSamp,False,lowlim,uplim)
    traces6 = plot_ridgelines('invivo3',sessions,metric,'gm',colors,sides,nSamp,False,lowlim,uplim)
    fig = make_subplots(rows=3, cols=2,
                   subplot_titles=("P1 White Matter", "P1 Gray Matter", "P2 White Matter", "P2 Gray Matter", "P3 White Matter", "P3 Gray Matter"),
                   vertical_spacing = 0.08,
                   shared_xaxes=True)
    for trace in traces1:
        fig.add_trace(trace,row=1, col=1)
    for trace in traces2:
        fig.add_trace(trace,row=1, col=2)
    for trace in traces3:
        fig.add_trace(trace,row=2, col=1)
    for trace in traces4:
        fig.add_trace(trace,row=2, col=2)
    for trace in traces5:
        fig.add_trace(trace,row=3, col=1)
    for trace in traces6:
        fig.add_trace(trace,row=3, col=2)
    axis_template = dict(linecolor = 'white', 
                     showticklabels = True,
                     tickfont=dict(color="white",size=12), 
                     gridcolor = 'rgba(255,255,255,0.2)')
    fig.update_yaxes(axis_template,showgrid=False)
    fig.update_traces(orientation='h')
    fig.update_layout(paper_bgcolor = '#1c2a3d',plot_bgcolor = '#1c2a3d')
    fig.update_traces(meanline=dict(visible=True,color="white",width=3),
                      points= 'outliers', # show all points
                      jitter=0.1,
                      width=3)  # add some jitter on points for better visibility
                      #scalemode='count')
    fig.update_xaxes(axis_template)
    fig.update_layout(width=800,height=950,title=f"VENUS vs NATIVE in-vivo {metric} distributions for each participant (P)", title_font_color="white")
    fig.update_annotations(font=dict(color="white", family = "Courier"))
    for i in range(1,7): 
        fig['layout']['xaxis{}'.format(i)]['title']= axis_title
    fig.for_each_xaxis(lambda axis: axis.title.update(font=dict(color = 'white', size=12,family="Courier"),standoff=0))
    fig.update_layout(
        legend=dict(
            y = 0.5,
            font=dict(
                family="Courier",
                size=16,
                color="white")))
    return fig

import warnings
warnings.filterwarnings('ignore')
---- repo2data starting ----
/Users/agah/opt/anaconda3/envs/jbnew/lib/python3.6/site-packages/repo2data
Config from file :
../binder/data_requirement.json
Destination:
/tmp/VENUS

Info : /tmp/VENUS already downloaded

VENUS vs NATIVE T1 distributions

Note

Reproduces Figure 5d-g from the article for the Participant-3.

_images/invivo_t1_p3.jpg

Fig. 1 vendor-native and VENUS quantitative T1 maps from P3 are shown in one axial slice.

The following KDEs agree well with the qualitative observations from the Fig. 1 above: Inter-vendor agreement (G1-vs-S1 and G1-vs-S2) of VENUS is superior to that of vendor-native T1 maps, both in the GM and WM.

fig =  plot_mosaic('T1','T1 (s)',0.5,3)
fig.show()