From 2b90b292d2431e4bc8357071529b42d7d5107478 Mon Sep 17 00:00:00 2001 From: William T Clarke Date: Thu, 7 Dec 2023 08:35:36 +0000 Subject: [PATCH] Enh: Automatically add spectralwidth to header extension (#120) * Automatically add spectralwidth * Better handling of existing spectralWidth field --- CHANGELOG.md | 5 +++++ requirements.yml | 2 +- spec2nii/spec2nii.py | 16 ++++++++++++++++ tests/test_spectralwidth.py | 29 +++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/test_spectralwidth.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 62e8984..b6442ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ This document contains the Spec2nii release history in reverse chronological order. +0.7.2 (WIP) +--------------------------------- +- SpectralWidth now added to header extension automatically to match bids specification. +- NIfTI-MRS V0.8 now generated. + 0.7.1 (Tuesday 7th November 2023) --------------------------------- - The --anon flag can be passed with any call to anonymise after writing files. diff --git a/requirements.yml b/requirements.yml index 09d716f..4e0f419 100644 --- a/requirements.yml +++ b/requirements.yml @@ -6,4 +6,4 @@ dependencies: - scipy - brukerapi>=0.1.8 - pandas - - nifti-mrs>=1.0.2 + - nifti-mrs>=1.1.1 diff --git a/spec2nii/spec2nii.py b/spec2nii/spec2nii.py index 56742e0..9ea7897 100644 --- a/spec2nii/spec2nii.py +++ b/spec2nii/spec2nii.py @@ -13,6 +13,7 @@ import json from nibabel.nifti2 import Nifti2Image from spec2nii import __version__ as spec2nii_ver +from numpy import isclose # There are case specific imports below @@ -291,6 +292,8 @@ def add_common_parameters(subparser): if self.imageOut: self.implement_overrides(args) + self.insert_spectralwidth() + if args.anon: from spec2nii.anonymise import anon_nifti_mrs for idx, nifti_mrs_img in enumerate(self.imageOut): @@ -325,6 +328,19 @@ def implement_overrides(self, args): nifti_mrs_img.header.extensions.clear() nifti_mrs_img.header.extensions.append(new_ext) + def insert_spectralwidth(self): + """Ensure that the correct spectral width is inserted into the header extension""" + for nifti_mrs_img in self.imageOut: + if 'SpectralWidth' in nifti_mrs_img.hdr_ext\ + and not isclose( + nifti_mrs_img.hdr_ext['SpectralWidth'], + 1 / nifti_mrs_img.dwelltime, + atol=1E-2): + nifti_mrs_img.remove_hdr_field('SpectralWidth') + nifti_mrs_img.add_hdr_field('SpectralWidth', 1 / nifti_mrs_img.dwelltime) + else: + nifti_mrs_img.add_hdr_field('SpectralWidth', 1 / nifti_mrs_img.dwelltime) + def validate_output(self): """Run NIfTI MRS validation on output.""" import nifti_mrs.validator as validate diff --git a/tests/test_spectralwidth.py b/tests/test_spectralwidth.py new file mode 100644 index 0000000..4e548d7 --- /dev/null +++ b/tests/test_spectralwidth.py @@ -0,0 +1,29 @@ +'''Simple test for SpectralWidth compliance''' + +import subprocess +from pathlib import Path +import json + +import numpy as np + +from .io_for_tests import read_nifti_mrs + +# Data paths +siemens_path = Path(__file__).parent / 'spec2nii_test_data' / 'Siemens' +vb_path = siemens_path / 'VBData' / 'Twix/meas_MID151_svs_se_C_T15_S10_10_FID108741.dat' + + +def test_insertion_spectralwidth(tmp_path): + subprocess.check_call(['spec2nii', 'twix', + '-e', 'image', + '-f', 'vb', + '-o', tmp_path, + '-j', str(vb_path)]) + + img_t = read_nifti_mrs(tmp_path / 'vb.nii.gz') + + hdr_ext_codes = img_t.header.extensions.get_codes() + hdr_ext = json.loads(img_t.header.extensions[hdr_ext_codes.index(44)].get_content()) + + assert 'SpectralWidth' in hdr_ext + assert np.isclose(hdr_ext['SpectralWidth'], 1 / img_t.header['pixdim'][4])