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
#> Reference freq. (ppm)   : 4.65
#> Nucleus                 : 1H
#> Spectral domain         : FALSE

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.228839e-06 3.548328e-05 4.02031e-05 1.706753e-05
#>            Glc          Gln          GSH          Glu         GPC          Ins
#> 1 2.442237e-06 3.029821e-06 2.227789e-05 6.499659e-05 1.60329e-05 5.902975e-05
#>            Lac        Lip09       Lip13a Lip13b Lip20         MM09         MM12
#> 1 5.818672e-06 2.362969e-05 2.635476e-06      0     0 9.887584e-06 6.546982e-06
#>           MM14         MM17         MM20          NAA         NAAG PCh
#> 1 2.599935e-05 2.245509e-05 9.207427e-05 5.981783e-05 1.556184e-05   0
#>            PCr         sIns Tau         tNAA          tCr        tCho
#> 1 2.101288e-05 6.508659e-06   0 7.537967e-05 6.121598e-05 1.60329e-05
#>            Glx        tLM09        tLM13        tLM20   X.CrCH2.sd       Ala.sd
#> 1 6.802641e-05 3.351728e-05 3.518181e-05 9.207427e-05 2.383753e-06 4.353324e-06
#>         Asp.sd        Cr.sd      GABA.sd       Glc.sd       Gln.sd       GSH.sd
#> 1 9.243635e-06 3.715163e-06 4.580095e-06 4.427051e-06 5.089149e-06 2.022838e-06
#>         Glu.sd       GPC.sd       Ins.sd       Lac.sd    Lip09.sd    Lip13a.sd
#> 1 5.086893e-06 2.525935e-06 2.091043e-06 5.311861e-06 4.11879e-06 1.328562e-05
#>      Lip13b.sd     Lip20.sd      MM09.sd      MM12.sd      MM14.sd      MM17.sd
#> 1 6.477216e-06 7.510921e-06 3.827224e-06 4.597895e-06 7.234493e-06 3.810271e-06
#>       MM20.sd       NAA.sd     NAAG.sd       PCh.sd       PCr.sd      sIns.sd
#> 1 8.60247e-06 1.015226e-06 1.21567e-06 2.174695e-06 3.108027e-06 7.233862e-07
#>         Tau.sd      tNAA.sd       tCr.sd      tCho.sd       Glx.sd     tLM09.sd
#> 1 3.777989e-06 7.031061e-07 5.881707e-07 2.113502e-07 3.165048e-06 1.006533e-06
#>       tLM13.sd     tLM20.sd    phase       lw       shift      asym
#> 1 1.572004e-06 3.018191e-06 11.15082 5.038937 -0.00342761 0.1764491
#>   res.deviance res.niter res.info
#> 1 7.300331e-05        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.745313e-05     497       3.8 62.79191 51.44063 1.490029
#>     tNAA_lw    tCr_lw    tCho_lw auto_bl_crit_7 auto_bl_crit_5.901
#> 1 0.0456527 0.0519959 0.05438811      -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.980941         -9.003463          -9.016574          -9.023968
#>   auto_bl_crit_2.364 auto_bl_crit_1.969 auto_bl_crit_1.647 auto_bl_crit_1.384
#> 1          -9.027875          -9.027565          -9.014311          -8.963288
#>   auto_bl_crit_1.17 auto_bl_crit_0.997 auto_bl_crit_0.856 auto_bl_crit_0.743
#> 1         -8.848749          -8.694788          -8.565996          -8.488421
#>   auto_bl_crit_0.654 auto_bl_crit_0.593 auto_bl_crit_0.558 auto_bl_crit_0.54
#> 1          -8.449879          -8.432819          -8.425653         -8.422666
#>   auto_bl_crit_0.532 auto_bl_crit_0.529
#> 1          -8.421411           -8.42088

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.9327529

Spectral SNR:

fit_res$res_tab$SNR
#> [1] 62.79191

Linewidth of the tNAA resonance in PPM:

fit_res$res_tab$tNAA_lw
#> [1] 0.0456527

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.13442304
#> Asp     0.57964080
#> Cr      0.65674194
#> GABA    0.27880838
#> Glc     0.03989541
#> Gln     0.04949395
#> GSH     0.36392281
#> Glu     1.06175847
#> GPC     0.26190706
#> Ins     0.96428663
#> Lac     0.09505152
#> Lip09   0.38600525
#> Lip13a  0.04305210
#> Lip13b  0.00000000
#> Lip20   0.00000000
#> MM09    0.16151965
#> MM12    0.10694890
#> MM14    0.42471509
#> MM17    0.36681750
#> MM20    1.50408874
#> NAA     0.97716039
#> NAAG    0.25421197
#> PCh     0.00000000
#> PCr     0.34325806
#> sIns    0.10632288
#> Tau     0.00000000
#> tNAA    1.23137236
#> tCr     1.00000000
#> tCho    0.26190706
#> Glx     1.11125242
#> tLM09   0.54752490
#> tLM13   0.57471608
#> tLM20   1.50408874

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.58174

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.817587

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.