Commit c79ceb9c authored by William Clarke's avatar William Clarke
Browse files

Merge branch 'master' into 'master'

Master

See merge request fsl/fsl_mrs!17
parents c6dc31cc c71d9d85
This document contains the FSL-MRS release history in reverse chronological order.
1.1.1 (Monday 15th March 2021)
------------------------------
- SNR measurements should cope with negative peak amplitudes correctly
- New metabolites added to list of default water referencing metabolites (Cr, PCr and NAA)
- Quantification now takes into account T1 relaxation
- Quantification module now fits the water reference FID to deal with corruption of first FID points.
- Added plot in report to clarify referencing signals.
- Restructure of internal quantification code.
1.1.0 (Thursday 18th February 2021)
-----------------------------------
- Support for NIfTI-MRS format.
......
......@@ -20,8 +20,7 @@ Tissue water density [0]_::
TISSUE_WATER_DENSITY = {'GM':0.78,'WM':0.65,'CSF':0.97}
Mollecular mass of water::
Molecular mass of water::
H2O_MOLECULAR_MASS = 18.01528 # g/mol
......@@ -33,6 +32,15 @@ Number of protons in water::
H2O_PROTONS = 2
The integrated water signal is referenced to a single reference basis.
There are three defaults defined in FSL-MRS, and each are tried in the order listed here.
Each possible reference is equivalent to a predetermined number of protons and has associated integration limits.
There are::
WATER_SCALING_METAB = ['Cr', 'PCr', 'NAA']
WATER_SCALING_METAB_PROTONS = [5, 5, 3]
WATER_SCALING_DEFAULT_LIMITS = [(2, 5), (2, 5), (1.8, 2.2)]
Relaxation parameters
*********************
Values are derived from a survey of the literature. References listed below. Values for metabolites are derived from an average of NAA, Cr and Cho peaks.
......
......@@ -168,6 +168,14 @@ Below are detailed explanations of some of the optional arguments in the wrapper
Allow independent scaling of specified basis spectra before fitting. For example this can be used to independently scale empirically measured macromolecules combined with simulated metabolite spectra.
:code:`--disable_MH_priors`
Disable the priors on the MH fitting. The priors are tuned for *in vivo* human brain spectroscopy. Use this option if your spectra has significantly different line widths, phases or large shifts. E.g. in liquid phase phantom or (potentially) pre-clinical systems. Priors can be fine tuned by altering the values in :code:`fsl_mrs.utils.constants`.
:code:`--internal_ref`
Set alternative metabolites for internal reference scaling (default is tCr = Cr + PCr). Multiple arguments can be specified for a combined internal reference.
:code:`--wref_metabolite`
Set alternative water scaling reference (default is Cr). Must be used if none of Cr, PCr and NAA are present in the basis set.
:code:`--ref_protons`
Number of protons that the water scaling reference is equivalent to (between defined integration limits). E.g. Cr is equivalent to 5 between 2 and 5 ppm. Only active when --wref_metabolite is used.
:code:`--ref_int_limits`
Integration limits for water scaling reference. Only active when --wref_metabolite is used.
The wrapper scripts can also take a configuration file as an input. For example, say we have a text file called :code:`config.txt` which contains the below:
......
......@@ -11,4 +11,18 @@ For this FSL-MRS provides the :code:`svs_segment` and :code:`mrsi_segment` comma
mrsi_segment -t T1.nii.gz -f tissue_frac mrsi_data.nii.gz
:code:`svs_segment` creates a small JSON file which can be passed to the fitting routines. :code:`mrsi_segment` creates NIfTI files of the fractional tissue volumes registered to the MRSI volume.
:code:`svs_segment` and :code:`mrsi_segment` both rely on fsl_anat to run FSL FAST tissue segmentation. If fsl_anat has already been run then the :code:`-t T1.nii.gz` can be substituted with :code:`-a T1.anat`.
\ No newline at end of file
:code:`svs_segment` and :code:`mrsi_segment` both rely on fsl_anat to run FSL FAST tissue segmentation. If fsl_anat has already been run then the :code:`-t T1.nii.gz` can be substituted with :code:`-a T1.anat`.
Water Reference Scaling Model
-----------------------------
If provided with an unsuppressed water reference FSL-MRS can generate metabolite concentrations in units of molarity (moles of substance per unit-volume, mol/L), or molality (moles of substance per unit-weight, mol/kg). Scaling is performed alongside relaxation correction as described by equations 4 & 6 of [NEAR20]_.
Referencing to water is carried out by comparing the integrated water resonance in the unsuppressed water (between 1.65 and 7.65 ppm) to the integrated area of a reference metabolite. The raw unsuppressed signal is first fitted using to a simple model (a single peak with Voigt lineshape), and integration is carried out on the fitted data after residual phase has been removed. This is to ensure the corruption of the first few FID points doesn't result in integration of broad, negative-valued wings of the water peak. Similarly the integration of the reference metabolite is carried out on the scaled, broadened basis with the influence of phase and baseline removed.
The integrated areas are shown in the final plot of the html report if a reference dataset is provided.
References
----------
.. [NEAR20] `Near J et al. Preprocessing, analysis and quantification in single‐voxel magnetic resonance spectroscopy: experts' consensus recommendations. NMR in Biomed 2020. <https://pubmed.ncbi.nlm.nih.gov/32084297>`_
\ No newline at end of file
......@@ -22,17 +22,6 @@ class MRSI(object):
mask=None, basis=None, names=None,
basis_hdr=None, H2O=None):
# process mask
if mask is None:
mask = np.full(FID.shape, True)
elif mask.shape[0:3] == FID.shape[0:3]:
mask = mask != 0.0
else:
raise ValueError(f'Mask must be None or numpy'
f' array of the same shape'
f' as FID. Mask {mask.shape[0:3]},'
f' FID {FID.shape[0:3]}.')
# process H2O
if H2O is None:
H2O = np.full(FID.shape, None)
......@@ -43,7 +32,9 @@ class MRSI(object):
# Load into properties
self.data = FID
self.H2O = H2O
self.mask = mask
# process mask
self.set_mask(mask)
if header is not None:
self.header = header
......@@ -244,7 +235,7 @@ class MRSI(object):
def set_mask(self, mask):
""" Load mask as numpy array."""
if mask is None:
mask = np.full(self.data.shape, True)
mask = np.full(self.data.shape[0:3], True)
elif mask.shape[0:3] == self.data.shape[0:3]:
mask = mask != 0.0
else:
......
......@@ -67,7 +67,7 @@ def main():
fitting_args.add_argument('--baseline_order', default=2, type=int,
metavar=('ORDER'),
help='order of baseline polynomial'
' (default=2,-1 disables)')
' (default=2, -1 disables)')
fitting_args.add_argument('--metab_groups', default=0, nargs='+',
type=str_or_int_arg,
help='metabolite groups: list of groups'
......@@ -89,6 +89,8 @@ def main():
help='structural image (for report)')
optional.add_argument('--TE', type=float, default=None, metavar='TE',
help='Echo time for relaxation correction (ms)')
optional.add_argument('--TR', type=float, default=None, metavar='TR',
help='Repetition time for relaxation correction (s)')
optional.add_argument('--tissue_frac', type=tissue_frac_arg,
action=TissueFracAction, nargs='+',
default=None, metavar='WM GM CSF OR json',
......@@ -99,14 +101,21 @@ def main():
nargs='+',
help='Metabolite(s) used as an internal reference.'
' Defaults to tCr (Cr+PCr).')
optional.add_argument('--wref_metabolite', type=str, default=None,
help='Metabolite(s) used as an the reference for water scaling.'
' Uses internal defaults otherwise.')
optional.add_argument('--ref_protons', type=int, default=None,
help='Number of protons that reference metabolite is equivalent to.'
' No effect without setting --wref_metabolite.')
optional.add_argument('--ref_int_limits', type=float, default=None, nargs=2,
help='Reference spectrum integration limits (low, high).'
' No effect without setting --wref_metabolite.')
optional.add_argument('--h2o_scale', type=float, default=1.0,
help='Additional scaling modifier for external water referencing.')
optional.add_argument('--report', action="store_true",
help='output html report')
optional.add_argument('--verbose', action="store_true",
help='spit out verbose info')
optional.add_argument('--phase_correct', action="store_true",
help='do phase correction')
optional.add_argument('--overwrite', action="store_true",
help='overwrite existing output folder')
optional.add_argument('--conj_fid', dest='conjfid', action="store_true",
......@@ -147,6 +156,7 @@ def main():
from fsl_mrs.utils import fitting
from fsl_mrs.utils import plotting
from fsl_mrs.utils import misc
from fsl_mrs.utils import quantify
import datetime
# ######################################################
if not args.verbose:
......@@ -226,12 +236,6 @@ def main():
if not args.no_rescale:
mrs.rescaleForFitting(ind_scaling=args.ind_scale)
# Do phase correction
if args.phase_correct:
if args.verbose:
print('--->> Phase correction\n')
mrs.FID = misc.phase_correct(mrs, mrs.FID)
# Keep/Ignore metabolites
mrs.keep(args.keep)
mrs.ignore(args.ignore)
......@@ -284,40 +288,48 @@ def main():
# Echo time
if args.TE is not None:
echotime = args.TE * 1E-3
elif 'meta' in basisheader and 'TE' in basisheader['meta']:
echotime = basisheader['meta']['TE']
if echotime > 1.0: # Assume in ms.
echotime *= 1E-3
else:
echotime = None
elif 'EchoTime' in FID.hdr_ext:
echotime = FID.hdr_ext['EchoTime']
else:
echotime = None
# Repetition time
if args.TR is not None:
repetition_time = args.TR
elif 'RepetitionTime' in FID.hdr_ext:
repetition_time = FID.hdr_ext['RepetitionTime']
else:
repetition_time = None
# Internal and Water quantification if requested
if (mrs.H2O is None) or (echotime is None):
if (mrs.H2O is None) or (echotime is None) or (repetition_time is None):
if echotime is None:
warnings.warn('H2O file provided but could not determine TE:'
' no absolute quantification will be performed.',
UserWarning)
res.calculateConcScaling(mrs, referenceMetab=args.internal_ref)
elif args.tissue_frac is not None:
res.calculateConcScaling(mrs,
referenceMetab=args.internal_ref,
waterRefFID=mrs.H2O,
tissueFractions=args.tissue_frac,
TE=echotime,
verbose=args.verbose,
add_scale=args.h2o_scale)
if repetition_time is None:
warnings.warn('H2O file provided but could not determine TR:'
' no absolute quantification will be performed.',
UserWarning)
res.calculateConcScaling(mrs, internal_reference=args.internal_ref, verbose=args.verbose)
else:
# Form quantification information
q_info = quantify.QuantificationInfo(echotime,
repetition_time,
mrs.names,
mrs.centralFrequency / 1E6,
water_ref_metab=args.wref_metabolite,
water_ref_metab_protons=args.ref_protons,
water_ref_metab_limits=args.ref_int_limits)
if args.tissue_frac:
q_info.set_fractions(args.tissue_frac)
if args.h2o_scale:
q_info.add_corr = args.h2o_scale
res.calculateConcScaling(mrs,
referenceMetab=args.internal_ref,
waterRefFID=mrs.H2O,
tissueFractions=None,
TE=echotime,
verbose=args.verbose,
add_scale=args.h2o_scale)
quant_info=q_info,
internal_reference=args.internal_ref,
verbose=args.verbose)
# Combine metabolites.
if args.combine is not None:
......@@ -349,13 +361,12 @@ def main():
# Save image of MRS voxel
location_fig = None
if args.t1 is not None:
datatype = mrs_io.check_datatype(args.data)
if datatype == 'NIFTI':
fig = plotting.plot_world_orient(args.t1, args.data)
fig.tight_layout()
location_fig = os.path.join(args.output, 'voxel_location.png')
fig.savefig(location_fig, bbox_inches='tight', facecolor='k')
if args.t1 is not None \
and FID.getXFormCode() > 0:
fig = plotting.plot_world_orient(args.t1, args.data)
fig.tight_layout()
location_fig = os.path.join(args.output, 'voxel_location.png')
fig.savefig(location_fig, bbox_inches='tight', facecolor='k')
# Save quick summary figure
report.fitting_summary_fig(mrs, res,
......
......@@ -7,12 +7,14 @@
#
# Copyright (C) 2019 University of Oxford
from fsl_mrs.auxiliary import configargparse
import time
import warnings
from fsl_mrs.auxiliary import configargparse
from fsl_mrs import __version__
from fsl_mrs.utils.splash import splash
from fsl_mrs.utils import fitting, misc, mrs_io
import time
from fsl_mrs.utils import fitting, misc, mrs_io, quantify
# NOTE!!!! THERE ARE MORE IMPORTS IN THE CODE BELOW (AFTER ARGPARSING)
......@@ -83,6 +85,8 @@ def main():
# ADDITONAL OPTIONAL ARGUMENTS
optional.add_argument('--TE', type=float, default=None, metavar='TE',
help='Echo time for relaxation correction (ms)')
optional.add_argument('--TR', type=float, default=None, metavar='TR',
help='Repetition time for relaxation correction (s)')
optional.add_argument('--tissue_frac', type=str, nargs=3, default=None,
help='Tissue fraction nifti files registered to'
' MRSI volume. Supplied in order: WM, GM, CSF.')
......@@ -90,6 +94,15 @@ def main():
nargs='+',
help='Metabolite(s) used as an internal reference.'
' Defaults to tCr (Cr+PCr).')
optional.add_argument('--wref_metabolite', type=str, default=None,
help='Metabolite(s) used as an the reference for water scaling.'
' Uses internal defaults otherwise.')
optional.add_argument('--ref_protons', type=int, default=None,
help='Number of protons that reference metabolite is equivalent to.'
' No effect without setting --wref_metabolite.')
optional.add_argument('--ref_int_limits', type=float, default=None, nargs=2,
help='Reference spectrum integration limits (low, high).'
' No effect without setting --wref_metabolite.')
optional.add_argument('--report', action="store_true",
help='output html report')
optional.add_argument('--verbose', action="store_true",
......@@ -122,7 +135,6 @@ def main():
# DO THE IMPORTS AFTER PARSING TO SPEED UP HELP DISPLAY
import os
import shutil
import warnings
import numpy as np
from fsl_mrs.utils import report
from fsl_mrs.core import NIFTI_MRS
......@@ -212,16 +224,17 @@ def main():
# Echo time
if args.TE is not None:
echotime = args.TE * 1E-3
elif 'meta' in mrsi.basis_hdr and 'TE' in mrsi.basis_hdr['meta']:
echotime = mrsi.basis_hdr['meta']['TE']
if echotime > 1.0: # Assume in ms.
echotime *= 1E-3
else:
echotime = None
elif 'TE' in mrsi.header:
echotime = mrsi.header['TE']
else:
echotime = None
# Repetition time
if args.TR is not None:
repetition_time = args.TR
elif 'RepetitionTime' in mrsi_data.hdr_ext:
repetition_time = mrsi_data.hdr_ext['RepetitionTime']
else:
repetition_time = None
# Fitting
if args.verbose:
......@@ -234,7 +247,7 @@ def main():
mrs = mrsi.mrs_from_average()
Fitargs_init = Fitargs.copy()
Fitargs_init['method'] = 'Newton'
res_init, _ = runvoxel([mrs, 0, None], args, Fitargs_init, echotime)
res_init, _ = runvoxel([mrs, 0, None], args, Fitargs_init, echotime, repetition_time)
Fitargs['x0'] = res_init.params
# quick summary figure
......@@ -260,7 +273,7 @@ def main():
print(' Running sequentially (are you sure about that?) ')
results = []
for idx, mrs in enumerate(mrsi):
res = runvoxel(mrs, args, Fitargs, echotime)
res = runvoxel(mrs, args, Fitargs, echotime, repetition_time)
results.append(res)
if args.verbose:
print(f'{idx+1}/{mrsi.num_masked_voxels} voxels completed')
......@@ -268,7 +281,7 @@ def main():
if args.verbose:
print(f' Parallelising over {mp.cpu_count()} workers ')
func = partial(runvoxel, args=args, Fitargs=Fitargs, echotime=echotime)
func = partial(runvoxel, args=args, Fitargs=Fitargs, echotime=echotime, repetition_time=repetition_time)
with mp.Pool(processes=mp.cpu_count()) as p:
results = p.map_async(func, mrsi)
if args.verbose:
......@@ -406,7 +419,7 @@ def main():
print('\n\n\nDone.')
def runvoxel(mrs_in, args, Fitargs, echotime):
def runvoxel(mrs_in, args, Fitargs, echotime, repetition_time):
mrs, index, tissue_seg = mrs_in
# Parse metabolite groups
......@@ -420,22 +433,36 @@ def runvoxel(mrs_in, args, Fitargs, echotime):
new_metab_groups = metab_groups.copy()
res = fitting.fit_FSLModel(mrs, **Fitargs, metab_groups=new_metab_groups)
# Quantification
# Internal and Water quantification if requested
if (mrs.H2O is None) or (echotime is None):
res.calculateConcScaling(mrs, referenceMetab=args.internal_ref)
elif tissue_seg is None:
res.calculateConcScaling(mrs,
referenceMetab=args.internal_ref,
waterRefFID=mrs.H2O,
tissueFractions=None,
TE=echotime)
if (mrs.H2O is None) or (echotime is None) or (repetition_time is None):
if echotime is None:
warnings.warn('H2O file provided but could not determine TE:'
' no absolute quantification will be performed.',
UserWarning)
if repetition_time is None:
warnings.warn('H2O file provided but could not determine TR:'
' no absolute quantification will be performed.',
UserWarning)
res.calculateConcScaling(mrs, internal_reference=args.internal_ref, verbose=args.verbose)
else:
# Form quantification information
q_info = quantify.QuantificationInfo(echotime,
repetition_time,
mrs.names,
mrs.centralFrequency / 1E6,
water_ref_metab=args.wref_metabolite,
water_ref_metab_protons=args.ref_protons,
water_ref_metab_limits=args.ref_int_limits)
if tissue_seg:
q_info.set_fractions(tissue_seg)
if args.h2o_scale:
q_info.add_corr = args.h2o_scale
res.calculateConcScaling(mrs,
referenceMetab=args.internal_ref,
waterRefFID=mrs.H2O,
tissueFractions=tissue_seg,
TE=echotime)
quant_info=q_info,
internal_reference=args.internal_ref,
verbose=args.verbose)
# Combine metabolites.
if args.combine is not None:
res.combine(args.combine)
......
......@@ -7,6 +7,7 @@ Copyright Will Clarke, University of Oxford, 2021'''
import fsl_mrs.utils.mrs_io as mrsio
import fsl_mrs.utils.mrs_io.fsl_io as fslio
from fsl_mrs.utils.mrs_io.main import _check_datatype
from fsl_mrs.utils import plotting
import numpy as np
import os.path as op
......@@ -150,3 +151,17 @@ def test_fslBasisRegen():
assert names_fsl2 == names_fsl
for r in headerReqFields:
assert headers_fsl[0][r] == headers_fsl2[0][r]
def test_check_datatype():
'''Check various paths through _check_datatype'''
assert _check_datatype('fake/path/test.RAW') == 'RAW'
assert _check_datatype('fake/path/test.H2O') == 'RAW'
assert _check_datatype('fake/path/test.txt') == 'TXT'
assert _check_datatype('fake/path/test.nii') == 'NIFTI'
assert _check_datatype('fake/path/test.nii.gz') == 'NIFTI'
assert _check_datatype('fake/path/test.blah.nii.gz') == 'NIFTI'
assert _check_datatype('fake/path/test.blah.nii') == 'NIFTI'
......@@ -47,3 +47,30 @@ def test_fsl_mrs(tmp_path):
assert op.exists(op.join(tmp_path, 'qc.csv'))
assert op.exists(op.join(tmp_path, 'all_parameters.csv'))
assert op.exists(op.join(tmp_path, 'options.txt'))
def test_alt_ref(tmp_path):
subprocess.check_call(['fsl_mrs',
'--data', data['metab'],
'--basis', data['basis'],
'--output', tmp_path,
'--h2o', data['water'],
'--TE', '11',
'--metab_groups', 'Mac',
'--tissue_frac', '0.45', '0.45', '0.1',
'--overwrite',
'--combine', 'Cr', 'PCr',
'--combine', 'NAA', 'NAAG',
'--internal_ref', 'NAA', 'NAAG',
'--wref_metabolite', 'PCh',
'--ref_protons', '3',
'--ref_int_limits', '3.0', '3.4',
'--report'])
assert op.exists(op.join(tmp_path, 'report.html'))
assert op.exists(op.join(tmp_path, 'summary.csv'))
assert op.exists(op.join(tmp_path, 'concentrations.csv'))
assert op.exists(op.join(tmp_path, 'qc.csv'))
assert op.exists(op.join(tmp_path, 'all_parameters.csv'))
assert op.exists(op.join(tmp_path, 'options.txt'))
......@@ -7,15 +7,59 @@ Copyright Will Clarke, University of Oxford, 2021'''
import os.path as op
import numpy as np
import fsl_mrs.utils.mrs_io as mrsio
from fsl_mrs.utils.fitting import fit_FSLModel
import numpy as np
import fsl_mrs.utils.quantify as quant
from fsl_mrs.utils.constants import STANDARD_T1, STANDARD_T2
metabfile = op.join(op.dirname(__file__), 'testdata/quantify/Cr_10mM_test_water_scaling_WS.txt')
h2ofile = op.join(op.dirname(__file__), 'testdata/quantify/Cr_10mM_test_water_scaling_nWS.txt')
basisfile = op.join(op.dirname(__file__), 'testdata/quantify/basisset_JMRUI')
def test_QuantificationInfo():
qci = quant.QuantificationInfo(0.000, 40, ['Cr', 'NAA'], 298)
assert qci.relax_corr_water_molal > 55500
assert qci.relax_corr_water_molar > 55500
qci = quant.QuantificationInfo(0.000, 40, ['Cr', 'NAA'], 127)
assert qci.relax_corr_water_molal > 55500
assert qci.relax_corr_water_molar > 55500
qci = quant.QuantificationInfo(0.010, 3, ['Cr', 'NAA'], 127)
t2s = STANDARD_T2['3T']
t1s = STANDARD_T1['3T']
assert np.isclose(qci.R_H2O_WM, np.exp(-0.010 / t2s['H2O_WM']) * (1 - np.exp(-3 / t1s['H2O_WM'])))
assert np.isclose(qci.R_H2O_GM, np.exp(-0.010 / t2s['H2O_GM']) * (1 - np.exp(-3 / t1s['H2O_GM'])))
assert np.isclose(qci.R_H2O_CSF, np.exp(-0.010 / t2s['H2O_CSF']) * (1 - np.exp(-3 / t1s['H2O_CSF'])))
qci = quant.QuantificationInfo(0.010, 3, ['Cr', 'NAA'], 298)
t2s = STANDARD_T2['7T']
t1s = STANDARD_T1['7T']
assert np.isclose(qci.R_H2O_WM, np.exp(-0.010 / t2s['H2O_WM']) * (1 - np.exp(-3 / t1s['H2O_WM'])))
assert np.isclose(qci.R_H2O_GM, np.exp(-0.010 / t2s['H2O_GM']) * (1 - np.exp(-3 / t1s['H2O_GM'])))
assert np.isclose(qci.R_H2O_CSF, np.exp(-0.010 / t2s['H2O_CSF']) * (1 - np.exp(-3 / t1s['H2O_CSF'])))
assert qci.ref_metab == 'Cr'
assert qci.ref_protons == 5
assert qci.ref_limits == (2, 5)
qci = quant.QuantificationInfo(0.010, 3, ['NAA'], 298)
assert qci.ref_metab == 'NAA'
assert qci.ref_protons == 3
assert qci.ref_limits == (1.8, 2.2)
qci.set_fractions({'GM': 0.45, 'WM': 0.45, 'CSF': 0.1})
assert qci._fractions is not None
assert np.isclose(qci.csf_corr, 1 / 0.9)
qci.add_corr = 5.0
assert qci.add_corr == 5.0
def test_quantifyWater():
basis, names, headerb = mrsio.read_basis(basisfile)
crIndex = names.index('Cr')
......@@ -31,28 +75,32 @@ def test_quantifyWater():
Fitargs = {'ppmlim': [0.2, 5.2],
'method': 'MH',
'baseline_order': -1,
'baseline_order': 0,
'metab_groups': [0]}
res = fit_FSLModel(mrs, **Fitargs)
tissueFractions = {'GM': 0.6, 'WM': 0.4, 'CSF': 0.0}
TE = 0.03
TR = 20
T2dict = {'H2O_GM': 0.110,
'H2O_WM': 0.080,
'H2O_CSF': 2.55,
'METAB': 0.160}
q_info = quant.QuantificationInfo(
TE,
TR,
mrs.names,
mrs.centralFrequency / 1E6,
t2=T2dict)
q_info.set_fractions(tissueFractions)
res.calculateConcScaling(mrs,
referenceMetab=['Cr'],
waterRefFID=mrs.H2O,
tissueFractions=tissueFractions,
TE=TE,
T2=T2dict,
waterReferenceMetab='Cr',
wRefMetabProtons=5,
reflimits=(2, 5),
verbose=False)
q_info,
internal_reference=['Cr'],
verbose=True)
print(res.getConc(scaling='raw'))
print(res.getConc(scaling='internal'))
......@@ -60,4 +108,4 @@ def test_quantifyWater():
print(res.getConc(scaling='molarity'))
assert np.allclose(res.getConc(scaling='internal'), 1.0)
assert np.allclose(res.getConc(scaling='molarity'), 10.59, atol=1E-1)
assert np.allclose(res.getConc(scaling='molarity'), 10.78, atol=1E-1)
......@@ -37,6 +37,13 @@ H2O_MOLECULAR_MASS = 18.01528 # g/mol
H2O_MOLALITY = 55.51E3 # mmol/kg
H2O_PROTONS = 2
# Water referencing metabolites
# Define a list of sensible metabolites to use and
# the number of protons between the default limits of 2 and 5
WATER_SCALING_METAB = ['Cr', 'PCr', 'NAA']
WATER_SCALING_METAB_PROTONS = [5, 5, 3]
WATER_SCALING_DEFAULT_LIMITS = [(2, 5), (2, 5), (1.8, 2.2)]