From 9e88e793a6fd6da0e4cdbe181609c06a96b2d0fd Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauldmccarthy@gmail.com> Date: Tue, 23 Jul 2024 15:19:23 +0100 Subject: [PATCH] TEST: Test ensuring that imcp does not modify data --- fsl/tests/__init__.py | 8 ++++ fsl/tests/test_dicom.py | 2 +- fsl/tests/test_immv_imcp.py | 83 ++++++++++++++++++++++++++++++++----- 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/fsl/tests/__init__.py b/fsl/tests/__init__.py index a758db12..2846ee5c 100644 --- a/fsl/tests/__init__.py +++ b/fsl/tests/__init__.py @@ -10,6 +10,7 @@ import os import sys import glob +import hashlib import shutil import fnmatch import logging @@ -439,3 +440,10 @@ def make_random_mask(filename, shape, xform, premask=None, minones=1): img.save(filename) return img + + +def sha256(filename): + hashobj = hashlib.sha256() + with open(filename, 'rb') as f: + hashobj.update(f.read()) + return hashobj.hexdigest() diff --git a/fsl/tests/test_dicom.py b/fsl/tests/test_dicom.py index dfda97f2..ca68ebd8 100644 --- a/fsl/tests/test_dicom.py +++ b/fsl/tests/test_dicom.py @@ -151,7 +151,7 @@ def test_scanDir(): datafile = op.join(datadir, 'example_dicom.tbz2') with tarfile.open(datafile) as f: - f.extractall() + f.extractall(filter='data') series = fsldcm.scanDir('.') assert len(series) == 2 diff --git a/fsl/tests/test_immv_imcp.py b/fsl/tests/test_immv_imcp.py index 7b3e3fcb..b4b80ffc 100644 --- a/fsl/tests/test_immv_imcp.py +++ b/fsl/tests/test_immv_imcp.py @@ -7,22 +7,26 @@ from __future__ import print_function +import gzip +import itertools as it +import os.path as op +import os +import shutil +import tempfile +from unittest import mock -import os.path as op -import os -import shutil -import tempfile - -import numpy as np +import numpy as np import nibabel as nib -import fsl.utils.imcp as imcp -import fsl.data.image as fslimage +import fsl.utils.imcp as imcp +import fsl.utils.tempdir as tempdir +import fsl.data.image as fslimage -from fsl.tests import make_random_image -from fsl.tests import make_dummy_file -from fsl.tests import looks_like_image +from fsl.tests import (make_random_image, + make_dummy_file, + looks_like_image, + sha256) real_print = print @@ -315,3 +319,60 @@ def test_imcp_shouldPass(move=False): def test_immv_shouldPass(): test_imcp_shouldPass(move=True) + + +def test_imcp_data_unmodified(): + """Test that the data in an imcp'd image file is not modified. """ + + dtypes = [ + np.int16, + np.int32, + np.float32, + np.float64] + + slints = [(None, None), (1, 0), (3, 1.5)] + + for dtype, (slope, inter) in it.product(dtypes, slints): + with tempdir.tempdir(): + data = np.random.randint(1, 100, (10, 10, 10)).astype(dtype) + hdr = nib.Nifti1Header() + hdr.set_data_dtype(dtype) + hdr.set_data_shape((10, 10, 10)) + hdr.set_slope_inter(slope, inter) + hdr.set_sform(np.eye(4)) + + # write header/data separately, as otherwise + # nibabel will automatically rescale the data + with open('image.nii', 'wb') as f: + hdr.write_to(f) + f.write(data.tobytes()) + + # Input/output formats the same, + # should induce a straight file copy + imcp.imcp('image.nii', 'copied.nii', useDefaultExt=False) + + # uncompresed->compressed will cause imcp + # to load in the image, rather than doing a + # file copy + with mock.patch.dict(os.environ, FSLOUTPUTTYPE='NIFTI_GZ'): + imcp.imcp('image.nii', 'converted.nii.gz', useDefaultExt=True) + + # copied files should be identical + assert sha256('image.nii') == sha256('copied.nii') + + # Converted files should have the same + # data, slope, and intercept. Read result + # header/data separately to avoid nibabel + # auto-rescaling. + with gzip.open('converted.nii.gz', 'rb') as f: + gothdr = nib.Nifti1Header.from_fileobj(f) + databytes = f.read() + + gotdata = np.frombuffer(databytes, dtype=dtype).reshape((10, 10, 10)) + + # Data should be binary identical + assert np.all(gotdata == data) + + if slope is None: slope = 1 + if inter is None: inter = 0 + assert np.all(np.isclose(gothdr.get_slope_inter(), (slope, inter))) -- GitLab