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
#> 1 1 1 1       1    1       0 9.343253e-06 3.333379e-05 4.021046e-05
#>           GABA          Glc          Gln          GSH          Glu          GPC
#> 1 1.686012e-05 4.012206e-06 4.723745e-06 2.167324e-05 6.733958e-05 1.611385e-05
#>            Ins          Lac        Lip09       Lip13a Lip13b Lip20         MM09
#> 1 6.024419e-05 5.934275e-06 2.344323e-05 2.830141e-06      0     0 1.005429e-05
#>           MM12         MM14         MM17         MM20          NAA         NAAG
#> 1 6.845373e-06 2.711244e-05 2.581297e-05 9.468594e-05 5.951333e-05 1.582301e-05
#>   PCh          PCr         sIns Tau         tNAA          tCr         tCho
#> 1   0 2.050539e-05 6.622802e-06   0 7.533634e-05 6.071585e-05 1.611385e-05
#>            Glx        tLM09        tLM13        tLM20   X.CrCH2.sd       Ala.sd
#> 1 7.206333e-05 3.349752e-05 3.678795e-05 9.468594e-05 2.365865e-06 4.358581e-06
#>        Asp.sd        Cr.sd     GABA.sd       Glc.sd      Gln.sd      GSH.sd
#> 1 8.96596e-06 3.745157e-06 4.44331e-06 4.324162e-06 4.89224e-06 2.01775e-06
#>         Glu.sd      GPC.sd      Ins.sd       Lac.sd    Lip09.sd    Lip13a.sd
#> 1 4.904507e-06 2.48574e-06 2.02138e-06 5.353012e-06 4.06968e-06 1.340822e-05
#>      Lip13b.sd     Lip20.sd     MM09.sd      MM12.sd      MM14.sd      MM17.sd
#> 1 6.514833e-06 7.381737e-06 3.76942e-06 4.490833e-06 7.118535e-06 3.582286e-06
#>        MM20.sd       NAA.sd      NAAG.sd       PCh.sd       PCr.sd      sIns.sd
#> 1 8.255783e-06 1.018032e-06 1.239152e-06 2.126375e-06 3.164547e-06 7.094294e-07
#>         Tau.sd      tNAA.sd       tCr.sd      tCho.sd       Glx.sd     tLM09.sd
#> 1 3.714836e-06 7.075161e-07 5.852302e-07 2.122003e-07 2.894733e-06 9.740525e-07
#>       tLM13.sd     tLM20.sd    phase       lw        shift      asym
#> 1 1.527124e-06 2.881584e-06 10.68786 5.024705 -0.003553105 0.1745251
#>   res.deviance res.niter res.info
#> 1  7.46863e-05        27        2
#>                                                        res.message bl_ed_pppm
#> 1 Relative error between `par' and the solution is at most `ptol'.   1.969325
#>   max_bl_flex_used     full_res fit_pts ppm_range      SNR      SRR     FQN
#> 1            FALSE 8.218365e-05     497       3.8 63.11155 51.11144 1.52469
#>      tNAA_lw     tCr_lw    tCho_lw auto_bl_crit_7 auto_bl_crit_5.901
#> 1 0.04573571 0.05174081 0.05459448      -8.897184          -8.940906
#>   auto_bl_crit_4.942 auto_bl_crit_4.12 auto_bl_crit_3.425 auto_bl_crit_2.844
#> 1            -8.9744         -8.997882          -9.012253          -9.020869
#>   auto_bl_crit_2.364 auto_bl_crit_1.969 auto_bl_crit_1.647 auto_bl_crit_1.384
#> 1           -9.02583          -9.026292          -9.013371          -8.962017
#>   auto_bl_crit_1.17 auto_bl_crit_0.997 auto_bl_crit_0.856 auto_bl_crit_0.743
#> 1         -8.846432          -8.691285          -8.562192          -8.484754
#>   auto_bl_crit_0.654 auto_bl_crit_0.593 auto_bl_crit_0.558 auto_bl_crit_0.54
#> 1          -8.446474          -8.429614           -8.42256         -8.419626
#>   auto_bl_crit_0.532 auto_bl_crit_0.529
#> 1          -8.418395          -8.417874

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

Spectral SNR:

fit_res$res_tab$SNR
#> [1] 63.11155

Linewidth of the tNAA resonance in PPM:

fit_res$res_tab$tNAA_lw
#> [1] 0.04573571

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.15388490
#> Asp     0.54901294
#> Cr      0.66227284
#> GABA    0.27768887
#> Glc     0.06608169
#> Gln     0.07780085
#> GSH     0.35696173
#> Glu     1.10909391
#> GPC     0.26539770
#> Ins     0.99223153
#> Lac     0.09773848
#> Lip09   0.38611380
#> Lip13a  0.04661289
#> Lip13b  0.00000000
#> Lip20   0.00000000
#> MM09    0.16559584
#> MM12    0.11274441
#> MM14    0.44654624
#> MM17    0.42514379
#> MM20    1.55949284
#> NAA     0.98019417
#> NAAG    0.26060757
#> PCh     0.00000000
#> PCr     0.33772716
#> sIns    0.10907862
#> Tau     0.00000000
#> tNAA    1.24080174
#> tCr     1.00000000
#> tCho    0.26539770
#> Glx     1.18689475
#> tLM09   0.55170964
#> tLM13   0.60590354
#> tLM20   1.55949284

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

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

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.