From b021b2dffa5b65b013f94c103c5ff5f671830614 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Tue, 10 Sep 2019 21:55:38 -0400 Subject: [PATCH 1/2] TEST: Check for failing GIFTI encodings --- nibabel/gifti/tests/test_gifti.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/nibabel/gifti/tests/test_gifti.py b/nibabel/gifti/tests/test_gifti.py index f1285d441d..60f7a539ec 100644 --- a/nibabel/gifti/tests/test_gifti.py +++ b/nibabel/gifti/tests/test_gifti.py @@ -21,6 +21,7 @@ from nibabel.testing import clear_and_catch_warnings from .test_parse_gifti_fast import (DATA_FILE1, DATA_FILE2, DATA_FILE3, DATA_FILE4, DATA_FILE5, DATA_FILE6) +import itertools def test_gifti_image(): @@ -400,3 +401,20 @@ def test_data_array_round_trip(): gio = GiftiImage.from_file_map(fmap) vertices = gio.darrays[0].data assert_array_equal(vertices, verts) + + +def test_type_coercion(): + dtypes = (np.uint8, np.int32, np.int64, np.float32, np.float64) + encodings = ('ASCII', 'B64BIN', 'B64GZ') + for data_dtype, darray_dtype, encoding in itertools.product(dtypes, + dtypes, + encodings): + da = GiftiDataArray(np.arange(10).astype(data_dtype), + encoding=encoding, + intent='NIFTI_INTENT_NODE_INDEX', + datatype=darray_dtype) + gii = GiftiImage(darrays=[da]) + gii_copy = GiftiImage.from_bytes(gii.to_bytes()) + da_copy = gii_copy.darrays[0] + assert_equal(np.dtype(da_copy.data.dtype), np.dtype(darray_dtype)) + assert_array_equal(da_copy.data, da.data) From 2838c49ddf84981fa1b2a43646ac423340c03861 Mon Sep 17 00:00:00 2001 From: "Christopher J. Markiewicz" Date: Tue, 10 Sep 2019 22:47:01 -0400 Subject: [PATCH 2/2] FIX: Coerce data types on writing GIFTI DataArrays Includes a hack to keep the old data_tag API functional --- nibabel/gifti/gifti.py | 16 ++++++++++------ nibabel/gifti/tests/test_gifti.py | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/nibabel/gifti/gifti.py b/nibabel/gifti/gifti.py index 22d6449e9a..5a69644f8e 100644 --- a/nibabel/gifti/gifti.py +++ b/nibabel/gifti/gifti.py @@ -270,16 +270,21 @@ def _to_xml_element(self): return DataTag(dataarray, encoding, datatype, ordering).to_xml() -def _data_tag_element(dataarray, encoding, datatype, ordering): +def _data_tag_element(dataarray, encoding, dtype, ordering): """ Creates data tag with given `encoding`, returns as XML element """ import zlib - ord = array_index_order_codes.npcode[ordering] + order = array_index_order_codes.npcode[ordering] enclabel = gifti_encoding_codes.label[encoding] if enclabel == 'ASCII': - da = _arr2txt(dataarray, datatype) + # XXX Accommodating data_tag API + # On removal (nibabel 4.0) drop str case + da = _arr2txt(dataarray, dtype if isinstance(dtype, str) else KIND2FMT[dtype.kind]) elif enclabel in ('B64BIN', 'B64GZ'): - out = dataarray.tostring(ord) + # XXX Accommodating data_tag API - don't try to fix dtype + if isinstance(dtype, str): + dtype = dataarray.dtype + out = np.asanyarray(dataarray, dtype).tostring(order) if enclabel == 'B64GZ': out = zlib.compress(out) da = base64.b64encode(out).decode() @@ -462,11 +467,10 @@ def _to_xml_element(self): if self.coordsys is not None: data_array.append(self.coordsys._to_xml_element()) # write data array depending on the encoding - dt_kind = data_type_codes.dtype[self.datatype].kind data_array.append( _data_tag_element(self.data, gifti_encoding_codes.specs[self.encoding], - KIND2FMT[dt_kind], + data_type_codes.dtype[self.datatype], self.ind_ord)) return data_array diff --git a/nibabel/gifti/tests/test_gifti.py b/nibabel/gifti/tests/test_gifti.py index 60f7a539ec..8ef7846f51 100644 --- a/nibabel/gifti/tests/test_gifti.py +++ b/nibabel/gifti/tests/test_gifti.py @@ -403,7 +403,7 @@ def test_data_array_round_trip(): assert_array_equal(vertices, verts) -def test_type_coercion(): +def test_darray_dtype_coercion_failures(): dtypes = (np.uint8, np.int32, np.int64, np.float32, np.float64) encodings = ('ASCII', 'B64BIN', 'B64GZ') for data_dtype, darray_dtype, encoding in itertools.product(dtypes,