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

Add tests for niftimrs proc and start of processing provenance.

parent 28974ee1
......@@ -76,12 +76,20 @@ class NIFTI_MRS(Image):
if isinstance(args[0], np.ndarray):
args = list(args)
args[0] = args[0].conj()
filename = None
elif isinstance(args[0], Path):
args = list(args)
filename = args[0].name
args[0] = str(args[0])
elif isinstance(args[0], str):
args = list(args)
filename = Path(args[0]).name
super().__init__(*args, **kwargs)
# Store original filename for reports etc
self._filename = filename
# Check that file meets minimum requirements
try:
nmrs_version = self.mrs_nifti_version
......@@ -173,6 +181,15 @@ class NIFTI_MRS(Image):
self.header.extensions.append(extension)
self._set_dim_tags()
@property
def filename(self):
'''Name of file object was generated from.
Returns empty string if N/A.'''
if self._filename:
return self._filename
else:
return ''
def dim_position(self, dim_tag):
'''Return position of dim if it exists.'''
if dim_tag in self.dim_tags:
......@@ -273,6 +290,7 @@ class NIFTI_MRS(Image):
dim = self._dim_tag_to_index(remove_dim)
reduced_data = self.data.take(0, axis=dim)
new_obj = NIFTI_MRS(reduced_data, header=self.header)
new_obj._filename = self.filename
# Modify the dim information in
hdr_ext = new_obj.hdr_ext
......
......@@ -43,6 +43,14 @@ def test_nifti_mrs():
assert obj.copy(remove_dim='DIM_DYN').shape == (1, 1, 1, 4096, 32)
def test_nifti_mrs_filename():
obj = NIFTI_MRS(data['unprocessed'])
assert obj.filename == 'metab_raw.nii.gz'
obj = gen_new_nifti_mrs(np.zeros((1, 1, 1, 2), dtype=complex), 0.0005, 120.0)
assert obj.filename == ''
def test_nifti_mrs_save(tmp_path):
obj = NIFTI_MRS(data['metab'])
obj.save(tmp_path / 'out')
......
'''FSL-MRS test script
Test NIfTI-MRS processing
Copyright Will Clarke, University of Oxford, 2021
'''
from pathlib import Path
from fsl_mrs.utils.preproc import nifti_mrs_proc as nproc
from fsl_mrs.utils.mrs_io import read_FID
from fsl_mrs import __version__
testsPath = Path(__file__).parent
data = testsPath / 'testdata' / 'fsl_mrs_preproc'
metab = data / 'metab_raw.nii.gz'
wrefc = data / 'wref_raw.nii.gz'
wrefq = data / 'quant_raw.nii.gz'
ecc = data / 'ecc.nii.gz'
def test_update_processing_prov():
nmrs_obj = read_FID(metab)
assert 'ProcessingApplied' not in nmrs_obj.hdr_ext
nproc.update_processing_prov(nmrs_obj, 'test', 'test_str')
assert 'ProcessingApplied' in nmrs_obj.hdr_ext
assert isinstance(nmrs_obj.hdr_ext['ProcessingApplied'], list)
assert 'Time' in nmrs_obj.hdr_ext['ProcessingApplied'][0]
assert nmrs_obj.hdr_ext['ProcessingApplied'][0]['Program'] == 'FSL-MRS'
assert nmrs_obj.hdr_ext['ProcessingApplied'][0]['Version'] == __version__
assert nmrs_obj.hdr_ext['ProcessingApplied'][0]['Method'] == 'test'
assert nmrs_obj.hdr_ext['ProcessingApplied'][0]['Details'] == 'test_str'
def test_coilcombine():
nmrs_obj = read_FID(metab)
nmrs_ref_obj = read_FID(wrefc)
nmrs_ref_obj = nproc.average(nmrs_ref_obj, 'DIM_DYN')
combined = nproc.coilcombine(nmrs_obj, reference=nmrs_ref_obj)
assert combined.hdr_ext['ProcessingApplied'][0]['Method'] == 'RF coil combination'
assert combined.hdr_ext['ProcessingApplied'][0]['Details']\
== 'Coil combination, reference data used (wref_raw.nii.gz), prewhitening applied.'
......@@ -6,9 +6,13 @@ Author: Saad Jbabdi <saad@fmrib.ox.ac.uk>
Copyright (C) 2021 University of Oxford
SHBASECOPYRIGHT'''
from fsl_mrs.utils import preproc
from datetime import datetime
import numpy as np
from fsl_mrs.utils import preproc
from fsl_mrs.core import NIFTI_MRS
from fsl_mrs import __version__
class DimensionsDoNotMatch(Exception):
......@@ -19,6 +23,35 @@ class OnlySVS(Exception):
pass
def update_processing_prov(nmrs_obj: NIFTI_MRS, method, details):
"""Insert appropriate processing provenance information into the
NIfTI-MRS header extension.
:param nmrs_obj: NIFTI-MRS object which has been modified
:type nmrs_obj: fsl_mrs.core.NIFTI_MRS
:param method: [description]
:type method: str
:param details: [description]
:type details: str
"""
# 1. Check for ProcessingApplied key and create if not present
if 'ProcessingApplied' not in nmrs_obj.hdr_ext:
nmrs_obj.add_hdr_field('ProcessingApplied', [])
# 2. Form object to append.
prov_dict = {
'Time': datetime.now().isoformat(sep='T', timespec='milliseconds'),
'Program': 'FSL-MRS',
'Version': __version__,
'Method': method,
'Details': details}
# 3. Append
current_processing = nmrs_obj.hdr_ext['ProcessingApplied']
current_processing.append(prov_dict)
nmrs_obj.add_hdr_field('ProcessingApplied', current_processing)
def first_index(idx):
return all([ii == slice(None, None, None) or ii == 0 for ii in idx])
......@@ -71,6 +104,20 @@ def coilcombine(data, reference=None, no_prewhiten=False, figure=False, report=N
html=report)
if figure:
fig.show()
# Update processing prov
processing_info = 'Coil combination, '
if reference is None:
processing_info += 'no reference data, '
else:
processing_info += f'reference data used ({reference.filename}), '
if no_prewhiten:
processing_info += 'no prewhitening.'
else:
processing_info += 'prewhitening applied.'
update_processing_prov(combinedc_obj, 'RF coil combination', processing_info)
return combinedc_obj
......@@ -183,7 +230,7 @@ def aligndiff(data,
:param report: Provide output location as path to generate report
:param report_all: True to output all indicies
:return: Combined data in NIFTI_MRS format.
:return: Aligned data in NIFTI_MRS format.
'''
if data.shape[data.dim_position(dim_diff)] != 2:
raise DimensionsDoNotMatch('Diff dimension must be of length 2')
......
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