Commit 6892a023 authored by William Clarke's avatar William Clarke
Browse files

Add facility to align acorss all FIDs in higher dimensions of nifti-mrs.

parent 6ffd9c76
......@@ -428,6 +428,21 @@ class NIFTI_MRS(Image):
raise TypeError('dim should be int or a string matching one of the dim tags.')
def iterate_over_spatial(self):
"""Iterate over spatial voxels yeilding a data array the shape of the FID and any higher dimensions + index.
:yield: Complex FID data with any higher dimensions. Index to data.
:rtype: tuple
data =
def calc_slice_idx(idx):
slice_obj = list(idx[:3]) + [slice(None), ] * ( - 3)
return tuple(slice_obj)
for idx in np.ndindex(data.shape[:3]):
yield[idx], calc_slice_idx(idx)
def generate_mrs(self, dim=None, basis_file=None, basis=None, ref_data=None):
"""Generator for MRS or MRSI objects from the data, optionally returning a whole dimension as a list.
......@@ -91,6 +91,18 @@ def test_nifti_mrs_generator():
def test_nifti_mrs_spatial_generator():
obj = NIFTI_MRS(data['unprocessed'])
for gen_data, slice_idx in obj.iterate_over_spatial():
assert gen_data.shape == (4096, 32, 64)
assert slice_idx == (0, 0, 0,
slice(None, None, None),
slice(None, None, None),
slice(None, None, None))
def test_nifti_mrs_gen_mrs():
obj = NIFTI_MRS(data['unprocessed'])
......@@ -75,6 +75,14 @@ def test_align():
== 'fsl_mrs.utils.preproc.nifti_mrs_proc.align, dim=DIM_DYN, '\
'target=None, ppmlim=(1.0, 4.0), niter=1, apodize=5.'
# Align across all spectra
aligned3 = nproc.align(with_coils, 'all', ppmlim=(1.0, 4.0), niter=1, apodize=5)
assert aligned3.hdr_ext['ProcessingApplied'][0]['Method'] == 'Frequency and phase correction'
assert aligned3.hdr_ext['ProcessingApplied'][0]['Details']\
== 'fsl_mrs.utils.preproc.nifti_mrs_proc.align, dim=all, '\
'target=None, ppmlim=(1.0, 4.0), niter=1, apodize=5.'
def test_aligndiff():
# For want of data this is a bizzare way of using this function.
......@@ -161,11 +161,11 @@ def average(data, dim, figure=False, report=None, report_all=False):
def align(data, dim, target=None, ppmlim=None, niter=2, apodize=10, figure=False, report=None, report_all=False):
'''Align frequencies of spectra across a dimension
specified by a tag.
'''Align frequency and phase of spectra. Can be run across a dimension (specified by a tag), or all spectra
stored in higher dimensions.
:param NIFTI_MRS data: Data to align
:param str dim: NIFTI-MRS dimension tag
:param str dim: NIFTI-MRS dimension tag, or 'all'
:param target: Optional target FID
:param ppmlim: ppm search limits.
:param int niter: Number of total iterations
......@@ -178,9 +178,19 @@ def align(data, dim, target=None, ppmlim=None, niter=2, apodize=10, figure=False
aligned_obj = data.copy()
for dd, idx in data.iterate_over_dims(dim=dim,
if dim == 'all':
generator = data.iterate_over_spatial()
generator = data.iterate_over_dims(dim=dim,
for dd, idx in generator:
if dim == 'all':
# flatten
original_shape = dd.shape
dd = dd.reshape(original_shape[0], -1)
out = preproc.phase_freq_align(
......@@ -193,12 +203,15 @@ def align(data, dim, target=None, ppmlim=None, niter=2, apodize=10, figure=False
if dim == 'all':
aligned_obj[idx], phi, eps = out[0].T.reshape(original_shape), out[1], out[2]
aligned_obj[idx], phi, eps = out[0].T, out[1], out[2]
if (figure or report) and (report_all or first_index(idx)):
from fsl_mrs.utils.preproc.align import phase_freq_align_report
fig = phase_freq_align_report(dd.T,
......@@ -333,8 +346,10 @@ def ecc(data, reference, figure=False, report=None, report_all=False):
for dd, idx in data.iterate_over_dims(iterate_over_space=True):
if data.shape == reference.shape:
# Reference is the same shape as data, voxel-wise and spectrum-wise iteration
ref = reference[idx]
# Only one reference FID, only iterate over spatial voxels.
ref = reference[idx[0], idx[1], idx[2], :]
corrected_obj[idx] = preproc.eddy_correct(dd, ref)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment