From 718aa770ebdf7e730564c0c315f1dd9350b7fda3 Mon Sep 17 00:00:00 2001 From: wtclarke Date: Tue, 5 Mar 2024 20:53:46 +0000 Subject: [PATCH 1/2] Fix issues in un tested lines of the universal editing special case --- spec2nii/Siemens/twix_special_case.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/spec2nii/Siemens/twix_special_case.py b/spec2nii/Siemens/twix_special_case.py index 276bacf..90a1e42 100644 --- a/spec2nii/Siemens/twix_special_case.py +++ b/spec2nii/Siemens/twix_special_case.py @@ -142,24 +142,24 @@ def mgs_svs_ed_twix(twixObj, reord_data, meta_obj, dim_tags): "OFF": {"PulseOffset": edit_pulse_off, "PulseDuration": pulse_length}} elif seq_mode == 1.0: # HERMES GABA GSH (3 edit, 1 ctrl condition) - edit_cases = 3 + edit_cases = 4 dim_info = "HERMES j-difference editing, GABA GSH, four conditions" dim_header = {"EditCondition": ["A", "B", "C", "D"]} edit_pulse_val = { "A": {"PulseOffset": edit_pulse_1, "PulseDuration": 0.02}, - "B": {"PulseOffset": None, "PulseDuration": None}, - "C": {"PulseOffset": edit_pulse_off, "PulseDuration": 0.02}, - "D": {"PulseOffset": [edit_pulse_1, edit_pulse_off], "PulseDuration": 0.02}} + "B": {"PulseOffset": edit_pulse_off, "PulseDuration": 0.02}, + "C": {"PulseOffset": edit_pulse_2, "PulseDuration": 0.02}, + "D": {"PulseOffset": [edit_pulse_1, edit_pulse_2], "PulseDuration": 0.02}} elif seq_mode == 2.0: # HERMES GABA GSH EtOH (3 edit, 1 ctrl condition) edit_cases = 4 dim_info = "HERMES j-difference editing, GABA GSH EtOH, four conditions" dim_header = {"EditCondition": ["A", "B", "C", "D"]} edit_pulse_val = { - "A": {"PulseOffset": [edit_pulse_1, edit_pulse_2], "PulseDuration": 0.02}, - "B": {"PulseOffset": [edit_pulse_3, edit_pulse_2], "PulseDuration": None}, - "C": {"PulseOffset": [edit_pulse_1, edit_pulse_3], "PulseDuration": 0.02}, - "D": {"PulseOffset": None, "PulseDuration": None}} + "A": {"PulseOffset": [edit_pulse_1, edit_pulse_3], "PulseDuration": 0.02}, + "B": {"PulseOffset": edit_pulse_off, "PulseDuration": 0.02}, + "C": {"PulseOffset": [edit_pulse_2, edit_pulse_3], "PulseDuration": 0.02}, + "D": {"PulseOffset": [edit_pulse_1, edit_pulse_2], "PulseDuration": 0.02}} elif seq_mode == 3.0: # HERCULES (4 edit conditions) edit_cases = 4 @@ -170,16 +170,17 @@ def mgs_svs_ed_twix(twixObj, reord_data, meta_obj, dim_tags): "B": {"PulseOffset": [edit_pulse_off, edit_pulse_2], "PulseDuration": 0.02}, "C": {"PulseOffset": edit_pulse_1, "PulseDuration": 0.02}, "D": {"PulseOffset": edit_pulse_off, "PulseDuration": 0.02}} - elif seq_mode == 3.0: + elif seq_mode == 4.0: + # This is possibly only a condition for smm_svs_herc as not present in VE11c version. # HERMES GABA LAC (3 edit 1 ctrl conditions) edit_cases = 4 dim_info = "HERMES j-difference editing, GABA LAC, four conditions" dim_header = {"EditCondition": ["A", "B", "C", "D"]} edit_pulse_val = { "A": {"PulseOffset": edit_pulse_1, "PulseDuration": 0.02}, - "B": {"PulseOffset": None, "PulseDuration": None}, - "C": {"PulseOffset": edit_pulse_off, "PulseDuration": 0.02}, - "D": {"PulseOffset": [edit_pulse_1, edit_pulse_off], "PulseDuration": 0.02}} + "B": {"PulseOffset": edit_pulse_off, "PulseDuration": 0.02}, + "C": {"PulseOffset": edit_pulse_2, "PulseDuration": 0.02}, + "D": {"PulseOffset": [edit_pulse_1, edit_pulse_2], "PulseDuration": 0.02}} else: raise ValueError('Unknown sequence mode in mgs_svs_ed sequence.') From c1b66c9d3cca836698e5b44b662c4f6a075c6279 Mon Sep 17 00:00:00 2001 From: wtclarke Date: Wed, 6 Mar 2024 09:56:18 +0000 Subject: [PATCH 2/2] Fix issue in mgs_svs_ed special casing. Add xa50 test data. --- CHANGELOG.md | 2 ++ tests/spec2nii_test_data | 2 +- tests/test_siemens_rda.py | 20 ++++++++++++++++++ tests/{test_twix.py => test_siemens_twix.py} | 22 ++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) rename tests/{test_twix.py => test_siemens_twix.py} (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e9ca60..a25cc4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ This document contains the Spec2nii release history in reverse chronological ord ----------- - Siemens .rda format now had corrected and validated orientations (tested on VE11 baseline). - Siemens .rda format now handles MRSI/CSI data and matches DICOM output. Validated on VE11 baseline data. +- Fixes in Siemens Twix special case for universal editing sequence (HERMES conditions). +- Added handling of custom Bruker sequences `mt_sLASER`, `mt_MEGA_sLASER_V35` and `cl_STELASER_PA360_b`. 0.7.2 (Thursday 7th December 2023) ---------------------------------- diff --git a/tests/spec2nii_test_data b/tests/spec2nii_test_data index 9322e3d..d300d59 160000 --- a/tests/spec2nii_test_data +++ b/tests/spec2nii_test_data @@ -1 +1 @@ -Subproject commit 9322e3de8b109016af010ce6051c02ee578cfb5d +Subproject commit d300d59ce34eac29d6c24499f87f640f9848864d diff --git a/tests/test_siemens_rda.py b/tests/test_siemens_rda.py index e336a5f..e214417 100644 --- a/tests/test_siemens_rda.py +++ b/tests/test_siemens_rda.py @@ -17,6 +17,7 @@ xa20_svs_path = siemens_path / 'XAData' / 'XA20/rda/spct_002.MR.MRI-LAB Test_Dir.5.1.114540.rda' xa31_locale_svs_path = siemens_path / 'XAData' / 'XA31/rda/locale_XA31.rda' +xa50_path = siemens_path / 'XAData' / 'XA50' / 'Phantom_20240129.MR.10.1.155227.rda' latin1_encoding = siemens_path / 'rda' / 'latin1.rda' @@ -147,6 +148,25 @@ def test_xa31_locale_svs(tmp_path): assert np.iscomplexobj(img_t.dataobj) +def test_xa50_svs(tmp_path): + + subprocess.run([ + 'spec2nii', 'rda', + '-f', 'xa50_svs', + '-o', tmp_path, + '-j', xa50_path]) + + img_t = read_nifti_mrs(tmp_path / 'xa50_svs.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()) + + hdr_ext['ResonantNucleus'] = ['1H', ] + + assert img_t.shape == (1, 1, 1, 2048) + assert np.iscomplexobj(img_t.dataobj) + + def test_latin_encoding(tmp_path): subprocess.check_call(['spec2nii', 'rda', diff --git a/tests/test_twix.py b/tests/test_siemens_twix.py similarity index 92% rename from tests/test_twix.py rename to tests/test_siemens_twix.py index 57b7743..27b7741 100644 --- a/tests/test_twix.py +++ b/tests/test_siemens_twix.py @@ -23,6 +23,7 @@ # Special cased data hercules_ve = siemens_path / 'HERCULES' / 'Siemens_TIEMO_HERC.dat' hercules_xa30 = siemens_path / 'HERCULES' / 'meas_MID02595_FID60346_HERC.dat' +hermes_xa50 = siemens_path / 'XAData' / 'XA50' / 'smm_svs_herc_v2_hermes.dat' def test_VB(tmp_path): @@ -202,6 +203,27 @@ def test_XA_HERCULES(tmp_path): assert hdr_ext['dim_7'] == 'DIM_DYN' +def test_XA_HERMES(tmp_path): + + subprocess.check_call(['spec2nii', 'twix', + '-e', 'image', + '-f', 'hermes_xa', + '-o', tmp_path, + '-j', str(hermes_xa50)]) + + img_t = read_nifti_mrs(tmp_path / 'hermes_xa.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 img_t.shape == (1, 1, 1, 4096, 42, 4, 80) + assert np.iscomplexobj(img_t.dataobj) + + assert hdr_ext['dim_5'] == 'DIM_COIL' + assert hdr_ext['dim_6'] == 'DIM_EDIT' + assert hdr_ext['dim_7'] == 'DIM_DYN' + + def test_twix_mrsi_orientation(tmp_path): '''Test that the (empty) mrsi has information matching the twix equivalent.'''