DSC parameter estimation (CBV, CBF)#
Show code cell source
# import statements
import os
import numpy as np
from matplotlib import pyplot as plt
import csv
import pandas as pd
import seaborn as sns
from plotting_results_nb import plot_bland_altman, bland_altman_statistics
import json
from pathlib import Path
Test data#
Data summary: Simulated signal time curves representing perfusion scenarios typical of grey and white matter.
Detailed info:
Transit time distribution: gamma variate distribution with shape parameter lambda = 1 (negative exponential)
AIF modelled using a gamma variate function with shape parameter alfa = 1.5 and scale parameter beta = 3
Arterial delay not included
Arterial dispersion not included
Tissue and Arterial SNR = 200
TR = 1.243 s
TE = 29 ms
Reference values: Reference values are the parameters used to generate the data. The following combinations of CBV and CBF are included for
white matter CBV 2 ml/100ml and CBF 5, 10, 15, 20, 25, 30, 35 ml/100ml/min
grey matter CBV 4 ml/100ml and CBF 10, 20, 30, 40, 50, 60, 70 ml/100ml/min.
Source: arthur-chakwizira/BezierCurveDeconvolution
Ref: Non-parametric deconvolution using Bézier curves for quantification of cerebral perfusion in dynamic susceptibility contrast MRI (https://doi.org/10.1007/s10334-021-00995-0)
Equivalent simulations have previously been used to evaluate perfusion estimation techniques for DSC-MRI:
Wu et al. 2003 (DOI 10.1002/mrm.10522)
Mouridsen et al. 2006 (DOI 10.1016/j.neuroimage.2006.06.015)
Chappell et al. 2015 (10.1002/mrm.25390)
Tolerances
CBV: a_tol=1 ml/100ml, r_tol=0.1
CBF: a_tol=15 ml/100ml/min, r_tol=0.1
Visualize test data#
To get an impression of the test data, the concentration time curves of the test data are plotted below.
#plot test data
filename = ('../test/DSCmodels/data/dsc_data.csv')
# read from CSV to pandas
df1 = pd.read_csv(filename)
no_voxels = len(df1.label)
fig, ax = plt.subplots(1, 1, sharex='col', sharey='row', figsize=(6,6))
for currentvoxel in range(no_voxels):
a = df1['C_tis'][currentvoxel]
c = np.fromstring(a, dtype=float, sep=' ')
ax.plot(c)
ax.set_ylabel('C (mM)', fontsize=14)
ax.set_xlabel('index', fontsize=14)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14);
Import data#
# Load the meta data
meta = json.load(open("../test/results-meta.json"))
# Loop over each entry and collect the dataframe
df = []
for entry in meta:
if (entry['category'] == 'DSCmodels'):
fpath, fname, category, method, author = entry.values()
df_entry = pd.read_csv(Path(fpath, fname)).assign(author=author)
df.append(df_entry)
# Concat all entries
df = pd.concat(df)
author_list = df.author.unique()
no_authors = len(author_list)
# calculate error between measured and reference values
df['error_cbv'] = df['cbv_meas'] - df['cbv_ref']
df['error_cbf'] = df['cbf_meas'] - df['cbf_ref']
# tolerances
tolerances = { 'cbv': {'atol' : 1, 'rtol': 0.1 }, 'cbf': {'atol':15, 'rtol':0.1}}
Results#
If the tolerance lines are not shown, it means that they are outside the limits of the y-axis.
The contribution by SR_TBG_BNI_USAPhoenix uses the L-curve criterion (for more information see doi:10.1088/0031-9155/52/2/009). Additional tag was added to the contribution to indicate the method (LCC SFTR)
# set-up styling for seaborn plots
sns.set(font_scale=1.5)
sns.set_style("ticks")
fig, ax = plt.subplots(1,2, sharey='none', figsize=(12,5))
plot_bland_altman(ax[0], df, tolerances, 'cbv', ylim=(-2,2),label_xaxis='$CBV_{ref}$ (mL/100mL)',label_yaxis='$\Delta$ $CBV$ (mL/100mL)')
plot_bland_altman(ax[1], df, tolerances, 'cbf', ylim=(-20,20),label_xaxis='$CBF_{ref}$ (mL/100mL/min)',label_yaxis='$\Delta$ $CBF$ (mL/100mL/min)')
fig.tight_layout()
fig.subplots_adjust(left=0.15, top=0.95)
# Hide the legend for the left subplot
ax[0].get_legend().set_visible(False)
# Set the position of the legend
plt.legend(bbox_to_anchor=(1.05, 1), title='ContributionID', loc='upper left', borderaxespad=0, fontsize=14);
Bias results estimated CBV values combined for all voxels
resultsBA = bland_altman_statistics(data=df,par='error_cbv',grouptag='author')
print(resultsBA)
bias stdev LoA lower \
author
SR_LB_TBG_BNI_USAPhoenix_USA_LCC SFTR 0.312242 0.236365 -0.151033
LoA upper
author
SR_LB_TBG_BNI_USAPhoenix_USA_LCC SFTR 0.775517
Bias results estimated CBF values combined for all voxels
resultsBA = bland_altman_statistics(data=df,par='error_cbf',grouptag='author')
print(resultsBA)
bias stdev LoA lower LoA upper
author
SR_LB_TBG_BNI_USAPhoenix_USA_LCC SFTR -2.93965 4.107339 -10.990034 5.110734
Notes#
Additional notes/remarks
References#
Sourbron et al. Pixel-by-pixel deconvolution of bolus-tracking data: optimization and implementation, Phys Med Biol (2007), 52:429 doi:10.1088/0031-9155/52/2/009