Introduction to spant

Reading raw data and plotting

Load the spant package:

library(spant)

Get the path to a data file included with spant:

fname <- system.file("extdata", "philips_spar_sdat_WS.SDAT", package = "spant")

Read the file and save to the workspace as mrs_data:

mrs_data <- read_mrs(fname)

Output some basic information about the data:

print(mrs_data)
#> MRS Data Parameters
#> ----------------------------------
#> Trans. freq (MHz)       : 127.7861
#> FID data points         : 1024
#> X,Y,Z dimensions        : 1x1x1
#> Dynamics                : 1
#> Coils                   : 1
#> Voxel resolution (mm)   : 20x20x20
#> Sampling frequency (Hz) : 2000
#> Repetition time (s)     : 2 
#> Reference freq. (ppm)   : 4.65
#> Nucleus                 : 1H
#> Spectral domain         : FALSE
#> Number of transients    : 128 
#> Echo time (s)           : 0.03 
#> Manufacturer            : Philips

Plot the spectral region between 5 and 0.5 ppm:

plot(mrs_data, xlim = c(5, 0.5))

Basic preprocessing

Apply a HSVD filter to the residual water region and align the spectrum to the tNAA resonance at 2.01 ppm:

mrs_proc <- hsvd_filt(mrs_data)
mrs_proc <- align(mrs_proc, 2.01)
plot(mrs_proc, xlim = c(5, 0.5))

Basis simulation

Simulate a typical basis set for short TE brain analysis, print some basic information and plot:

basis <- sim_basis_1h_brain_press(mrs_proc)
print(basis)
#> Basis set parameters
#> -------------------------------
#> Trans. freq (MHz)       : 127.8
#> Data points             : 1024
#> Sampling frequency (Hz) : 2000
#> Elements                : 27
#> 
#> Names
#> -------------------------------
#> -CrCH2,Ala,Asp,Cr,GABA,Glc,Gln,
#> GSH,Glu,GPC,Ins,Lac,Lip09,
#> Lip13a,Lip13b,Lip20,MM09,MM12,
#> MM14,MM17,MM20,NAA,NAAG,PCh,
#> PCr,sIns,Tau
stackplot(basis, xlim = c(4, 0.5), labels = basis$names, y_offset = 5)

Perform ABfit analysis of the processed data (mrs_proc):

fit_res <- fit_mrs(mrs_proc, basis)

Plot the fit result:

plot(fit_res)

Unscaled amplitudes, CRLB error estimates and other useful fitting diagnostics, such as SNR, are given in the fit_res results table:

fit_res$res_tab
#>   X Y Z Dynamic Coil X.CrCH2         Ala         Asp           Cr         GABA
#> 1 1 1 1       1    1       0 8.22882e-06 3.54836e-05 4.020285e-05 1.706749e-05
#>            Glc          Gln         GSH          Glu          GPC         Ins
#> 1 2.441645e-06 3.029596e-06 2.22778e-05 6.499629e-05 1.603284e-05 5.90291e-05
#>            Lac        Lip09       Lip13a Lip13b Lip20        MM09         MM12
#> 1 5.818795e-06 2.362979e-05 2.635415e-06      0     0 9.88749e-06 6.546991e-06
#>           MM14         MM17         MM20          NAA         NAAG PCh
#> 1 2.599942e-05 2.245499e-05 9.207402e-05 5.981793e-05 1.556191e-05   0
#>            PCr         sIns Tau         tNAA          tCr         tCho
#> 1 2.101316e-05 6.508574e-06   0 7.537984e-05 6.121601e-05 1.603284e-05
#>            Glx        tLM09        tLM13        tLM20   X.CrCH2.sd       Ala.sd
#> 1 6.802589e-05 3.351728e-05 3.518183e-05 9.207402e-05 2.383751e-06 4.353303e-06
#>         Asp.sd        Cr.sd      GABA.sd       Glc.sd       Gln.sd       GSH.sd
#> 1 9.243615e-06 3.715183e-06 4.580068e-06 4.427033e-06 5.089137e-06 2.022834e-06
#>         Glu.sd      GPC.sd       Ins.sd       Lac.sd    Lip09.sd    Lip13a.sd
#> 1 5.086881e-06 2.52594e-06 2.091028e-06 5.311852e-06 4.11878e-06 1.328561e-05
#>      Lip13b.sd     Lip20.sd      MM09.sd      MM12.sd      MM14.sd      MM17.sd
#> 1 6.477217e-06 7.510906e-06 3.827216e-06 4.597881e-06 7.234422e-06 3.810262e-06
#>        MM20.sd       NAA.sd      NAAG.sd       PCh.sd       PCr.sd      sIns.sd
#> 1 8.602454e-06 1.015226e-06 1.215674e-06 2.174706e-06 3.108045e-06 7.233844e-07
#>         Tau.sd      tNAA.sd     tCr.sd      tCho.sd      Glx.sd     tLM09.sd
#> 1 3.777974e-06 7.031055e-07 5.8817e-07 2.113495e-07 3.16504e-06 1.006531e-06
#>    tLM13.sd     tLM20.sd    phase      lw        shift      asym res.deviance
#> 1 1.572e-06 3.018185e-06 11.15095 5.03894 -0.003427618 0.1764503 7.300295e-05
#>   res.niter res.info
#> 1        28        2
#>                                                        res.message bl_ed_pppm
#> 1 Relative error between `par' and the solution is at most `ptol'.   2.364083
#>   max_bl_flex_used     full_res fit_pts ppm_range     SNR      SRR      FQN
#> 1            FALSE 7.745298e-05     497       3.8 62.7919 51.44074 1.490022
#>      tNAA_lw     tCr_lw    tCho_lw auto_bl_crit_7 auto_bl_crit_5.901
#> 1 0.04565273 0.05199591 0.05438799      -8.904402          -8.947808
#>   auto_bl_crit_4.942 auto_bl_crit_4.12 auto_bl_crit_3.425 auto_bl_crit_2.844
#> 1          -8.980942         -9.003464          -9.016575           -9.02397
#>   auto_bl_crit_2.364 auto_bl_crit_1.969 auto_bl_crit_1.647 auto_bl_crit_1.384
#> 1          -9.027878          -9.027567          -9.014311          -8.963283
#>   auto_bl_crit_1.17 auto_bl_crit_0.997 auto_bl_crit_0.856 auto_bl_crit_0.743
#> 1         -8.848735          -8.694763          -8.565961          -8.488379
#>   auto_bl_crit_0.654 auto_bl_crit_0.593 auto_bl_crit_0.558 auto_bl_crit_0.54
#> 1          -8.449833           -8.43277          -8.425603         -8.422615
#>   auto_bl_crit_0.532 auto_bl_crit_0.529
#> 1           -8.42136          -8.420829

Note that signal names appended with “.sd” are the CRLB estimates for the uncertainty (standard deviation) in the metabolite quantity estimate. e.g. to calculate the percentage s.d. for tNAA:

fit_res$res_tab$tNAA.sd / fit_res$res_tab$tNAA * 100
#> [1] 0.9327501

Spectral SNR:

fit_res$res_tab$SNR
#> [1] 62.7919

Linewidth of the tNAA resonance in PPM:

fit_res$res_tab$tNAA_lw
#> [1] 0.04565273

Ratios to total-creatine

Amplitude estimates measured by the fitting method are essentially arbitrary unless scaled to a known reference signal. The simplest approach for proton-MRS is to simply divide all metabolite values by total-creatine:

fit_res_tcr_sc <- scale_amp_ratio(fit_res, "tCr")
amps <- fit_amps(fit_res_tcr_sc)
print(t(amps))
#>               [,1]
#> X.CrCH2 0.00000000
#> Ala     0.13442269
#> Asp     0.57964571
#> Cr      0.65673753
#> GABA    0.27880766
#> Glc     0.03988572
#> Gln     0.04949026
#> GSH     0.36392121
#> Glu     1.06175315
#> GPC     0.26190595
#> Ins     0.96427560
#> Lac     0.09505348
#> Lip09   0.38600671
#> Lip13a  0.04305107
#> Lip13b  0.00000000
#> Lip20   0.00000000
#> MM09    0.16151804
#> MM12    0.10694901
#> MM14    0.42471603
#> MM17    0.36681572
#> MM20    1.50408410
#> NAA     0.97716158
#> NAAG    0.25421304
#> PCh     0.00000000
#> PCr     0.34326247
#> sIns    0.10632143
#> Tau     0.00000000
#> tNAA    1.23137463
#> tCr     1.00000000
#> tCho    0.26190595
#> Glx     1.11124341
#> tLM09   0.54752475
#> tLM13   0.57471611
#> tLM20   1.50408410

Water reference scaling, AKA “absolute-quantification”

A more sophisticated approach to scaling metabolite values involves the use of a separate water-reference acquisition - which can be imported in the standard way:

fname_wref <- system.file("extdata", "philips_spar_sdat_W.SDAT", package = "spant")
mrs_data_wref <- read_mrs(fname_wref)

The following code assumes the voxel contains 100% white matter tissue and scales the metabolite values into molal (mM) units (mol / kg tissue water) based on the method described by Gasparovic et al MRM 2006 55(6):1219-26:

p_vols <- c(WM = 100, GM = 0, CSF = 0)
TE = 0.03
TR = 2
fit_res_molal <- scale_amp_molal_pvc(fit_res, mrs_data_wref, p_vols, TE, TR)
fit_res_molal$res_tab$tNAA
#> [1] 12.58177

An alternative method scales the metabolite values into molar (mM) units (mol / Litre of tissue) based on assumptions outlined in the LCModel manual and references therein (section 10.2). This approach may be preferred when comparing results to those obtained LCModel or TARQUIN.

fit_res_molar <- scale_amp_molar(fit_res, mrs_data_wref)
fit_res_molar$res_tab$tNAA
#> [1] 6.817602

Note, while “absolute” units are attractive, a large number of assumptions about metabolite and water relaxation rates are necessary to arrive at these mM estimates. If you’re not confident at being able to justify these assumptions, scaling to a metabolite reference (eg tCr as above) is going to be a better option in most cases. Simple metabolite referenced ratios also have the benefit of being more reproducible due to the simplicity of the approach.