Skip to content

Commit

Permalink
Add validation of SpectralWidth
Browse files Browse the repository at this point in the history
  • Loading branch information
wtclarke committed Dec 6, 2023
1 parent f862649 commit 62e0bab
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
This document contains the nifti_mrs_tools release history in reverse chronological order.

1.1.1 (Wednesday 6th December 2023)
-----------------------------------
- Validator checks consistency of any `SpectraWidth` header extension value with the dwell time in `pixdim[4]`.

1.1.0 (Wednesday 6th December 2023)
-----------------------------------
- Update definitions to NIfTI-MRS V0.8
Expand Down
8 changes: 8 additions & 0 deletions src/nifti_mrs/nifti_mrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,18 @@ def __init__(self, *args, validate_on_creation=True, **kwargs):
self._hdr_ext.to_json(),
self.image.shape,
np.max((self._hdr_ext.ndim, self.image.ndim)))
validator.validate_spectralwidth(
self._hdr_ext.to_json(),
self.dwelltime)
else:
try:
validator.validate_hdr_ext(
self._hdr_ext.to_json(),
self.image.shape,
np.max((self._hdr_ext.ndim, self.image.ndim)))
validator.validate_spectralwidth(
self._hdr_ext.to_json(),
self.dwelltime)
except validator.headerExtensionError as exc:
print(f"This file's header extension is currently invalid. Reason: {str(exc)}")

Expand Down Expand Up @@ -278,9 +284,11 @@ def hdr_ext(self, new_hdr):
'''Update MRS JSON header extension from python dict or Hdr_Ext object'''
if isinstance(new_hdr, dict):
validator.validate_hdr_ext(json.dumps(new_hdr), self.shape)
validator.validate_spectralwidth(json.dumps(new_hdr), self.dwelltime)
self._hdr_ext = Hdr_Ext.from_header_ext(new_hdr)
elif isinstance(new_hdr, Hdr_Ext):
validator.validate_hdr_ext(new_hdr.to_json(), self.shape)
validator.validate_spectralwidth(new_hdr.to_json(), self.dwelltime)
self._hdr_ext = new_hdr
else:
raise TypeError('Passed header extension must be a dict or Hdr_Ext object')
Expand Down
25 changes: 25 additions & 0 deletions src/nifti_mrs/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ def validate_nifti_mrs(nifti_mrs):
nifti_mrs.header.extensions[0].get_content(),
nifti_mrs.shape)

# Validate that any SpectralWidth definition matches pixdim[4]
validate_spectralwidth(
nifti_mrs.header.extensions[0].get_content(),
nifti_mrs.header['pixdim'][4])


def validate_nifti_data(nifti_img_data):
"""Validate the data inside a nibabel nifti image
Expand Down Expand Up @@ -230,3 +235,23 @@ def check_type(value, json_type):
if isinstance(value, json_type):
return True
return False


def validate_spectralwidth(header_ex, dwelltime):
"""If a SpectralWidth field is present, check that it matches the dwell time
Dwell time is stored in pixdim[4].
:param header_ex: NIfTI-MRS header extensions as a json deserialisable string
:type header_ex: str
:param dwelltime: Dwell time as stored in pixdim[4] to check against any SpectralWidth definition. In seconds.
:type dwelltime: float
"""

json_dict = json.loads(header_ex)
# check that (if present) SpectralWidth is consistent with pixdim[4]
if 'SpectralWidth' in json_dict:
if not np.isclose(json_dict['SpectralWidth'], 1 / dwelltime, atol=1E-2):
raise headerExtensionError(
f'SpectralWidth ({json_dict["SpectralWidth"]:0.2f} Hz) does not match'
f' 1 / dwelltime ({1 / dwelltime:0.2f} Hz).')
38 changes: 38 additions & 0 deletions tests/test_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,41 @@ def test_dynamic_header_size():
dim_5_header={'test': {'Value': [0, 1, 3, 4], 'Description': 'test'}}
)
validator.validate_hdr_ext(json.dumps(test_dict), (1, 1, 1, 512, 4), data_dimensions=5)


def test_spectralwidth():
# Wrong value
test_dict = dict(
SpectrometerFrequency=[123.2, ],
ResonantNucleus=["1H", ],
SpectralWidth=500
)

with raises(
validator.headerExtensionError,
match=r'SpectralWidth \(500\.00 Hz\) does not match 1 / dwelltime \(1000\.00 Hz\).'):
validator.validate_spectralwidth(
json.dumps(test_dict),
0.001)

# Right value
test_dict = dict(
SpectrometerFrequency=[123.2, ],
ResonantNucleus=["1H", ],
SpectralWidth=1000
)

validator.validate_spectralwidth(
json.dumps(test_dict),
0.001)

# No value
test_dict = dict(
SpectrometerFrequency=[123.2, ],
ResonantNucleus=["1H", ],
)

validator.validate_spectralwidth(
json.dumps(test_dict),
0.001)

0 comments on commit 62e0bab

Please sign in to comment.