From cc9cdf2ba20290b7ecb9a7a7dc3259c6f9703dbb Mon Sep 17 00:00:00 2001 From: Yujing Huang Date: Mon, 1 Apr 2024 12:52:54 -0400 Subject: [PATCH] handle Freesurfer Nifti1 header extension write TAG_END_NIIHDREXTENSION at the end of extension data to avoid the data to be truncated: TAG_END_NIIHDREXTENSION (-1) data-length (1) '*' note: If the extension data has trailing null characters or zeros at the end, nibabel.nifti1.Nifti1Extension.get_content() will truncate the data. See https://github.com/nipy/nibabel/blob/master/nibabel/nifti1.py#L629C1-L630C1, line 629: 'evalue = evalue.rstrip(b'\x00')' --- surfa/io/fsnifti1extension.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/surfa/io/fsnifti1extension.py b/surfa/io/fsnifti1extension.py index 1bfb9d5..e217feb 100644 --- a/surfa/io/fsnifti1extension.py +++ b/surfa/io/fsnifti1extension.py @@ -199,6 +199,18 @@ def write(self, fileobj, content, countbytesonly=False): iou.write_bytes(fileobj, content.warpmeta['format'], dtype='>i4') iou.write_bytes(fileobj, content.warpmeta.get('spacing', 1), dtype='>i4') iou.write_bytes(fileobj, content.warpmeta.get('exp_k', 0.0), dtype='>f4') + + # write TAG_END_NIIHDREXTENSION at the end of extension data to avoid the data to be truncated: + # TAG_END_NIIHDREXTENSION (-1) data-length (1) '*' + # this needs to be the last tag. + tag = FSNifti1Extension.Tags.end_data + length = 1 # extra char '*' + num_bytes += length + addtaglength + print(f'[DEBUG] FSNifti1Extension.write(): +{length:5d}, +{addtaglength:d}, dlen = {num_bytes:6d}, TAG = {tag:2d}') + if (not countbytesonly): + FSNifti1Extension.write_tag(fileobj, tag, length) + extrachar = '*' + fileobj.write(extrachar.encode('utf-8')) return num_bytes @@ -258,6 +270,26 @@ def write(self, fileobj, content, countbytesonly=False): iou.write_bytes(fileobj, content.scan_parameters['field_strength'], '>f4') fileobj.write(content.scan_parameters['pedir'].encode('utf-8')) + # end_data (TAG_END_NIIHDREXTENSION = -1) + """ + write TAG_END_NIIHDREXTENSION at the end of extension data to avoid the data to be truncated: + TAG_END_NIIHDREXTENSION (-1) data-length (1) '*' + this needs to be the last tag. + + If the extension data has trailing null characters or zeros at the end, + nibabel.nifti1.Nifti1Extension.get_content() will truncate the data. + See https://github.com/nipy/nibabel/blob/master/nibabel/nifti1.py#L629C1-L630C1, + line 629: 'evalue = evalue.rstrip(b'\x00')' + """ + tag = FSNifti1Extension.Tags.end_data + length = 1 # extra char '*' + num_bytes += length + addtaglength + print(f'[DEBUG] FSNifti1Extension.write(): +{length:5d}, +{addtaglength:d}, dlen = {num_bytes:6d}, TAG = {tag:2d}') + if (not countbytesonly): + FSNifti1Extension.write_tag(fileobj, tag, length) + extrachar = '*' + fileobj.write(extrachar.encode('utf-8')) + return num_bytes @@ -384,6 +416,7 @@ class Tags: gcamorph_geom = 10 # TAG_GCAMORPH_GEOM gcamorph_meta = 13 # TAG_GCAMORPH_META scan_parameters = 45 # TAG_SCAN_PARAMETERS + end_data = -1 # TAG_END_NIIHDREXTENSION class Content: