Skip to content

Commit 31f8d7f

Browse files
committed
RF+BF - check whether image and header are same file when saving
1 parent 715e04c commit 31f8d7f

File tree

4 files changed

+85
-9
lines changed

4 files changed

+85
-9
lines changed

nibabel/analyze.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,14 +1377,21 @@ def to_file_map(self, file_map=None):
13771377
hdr = self.get_header()
13781378
slope, inter, mn, mx = hdr.scaling_from_data(data)
13791379
hdr_fh, img_fh = self._get_fileholders(file_map)
1380+
# Check if hdr and img refer to same file; this can happen with odd
1381+
# analyze images but most often this is because it's a single nifti file
1382+
hdr_img_same = hdr_fh.same_file_as(img_fh)
13801383
hdrf = hdr_fh.get_prepare_fileobj(mode='wb')
1381-
imgf = img_fh.get_prepare_fileobj(mode='wb')
1384+
if hdr_img_same:
1385+
imgf = hdrf
1386+
else:
1387+
imgf = img_fh.get_prepare_fileobj(mode='wb')
13821388
self._write_header(hdrf, hdr, slope, inter)
13831389
self._write_image(imgf, data, hdr, slope, inter, mn, mx)
13841390
if hdr_fh.fileobj is None: # was filename
13851391
hdrf.close()
1386-
if img_fh.fileobj is None: # was filename
1387-
imgf.close()
1392+
if not hdr_img_same:
1393+
if img_fh.fileobj is None: # was filename
1394+
imgf.close()
13881395
self._header = hdr
13891396
self.file_map = file_map
13901397

nibabel/fileholders.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,23 @@ def get_prepare_fileobj(self, *args, **kwargs):
7373
raise FileHolderError('No filename or fileobj present')
7474
return obj
7575

76+
def same_file_as(self, other):
77+
""" Test if `self` refers to same files / fileobj as `other`
78+
79+
Parameters
80+
----------
81+
other : object
82+
object with `filename` and `fileobj` attributes
83+
84+
Returns
85+
-------
86+
tf : bool
87+
True if `other` has the same filename (or both have None) and the
88+
same fileobj (or both have None
89+
"""
90+
return ((self.filename == other.filename) and
91+
(self.fileobj == other.fileobj))
92+
7693

7794
def copy_file_map(file_map):
7895
''' Copy mapping of fileholders given by `file_map`

nibabel/tests/test_fileholders.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
""" Testing fileholders
2+
"""
3+
4+
from StringIO import StringIO
5+
6+
import numpy as np
7+
8+
from ..fileholders import FileHolder, FileHolderError, copy_file_map
9+
from ..tmpdirs import InTemporaryDirectory
10+
11+
from numpy.testing import (assert_array_almost_equal,
12+
assert_array_equal)
13+
14+
from nose.tools import assert_true, assert_false, assert_equal, assert_raises
15+
16+
17+
def test_init():
18+
fh = FileHolder('a_fname')
19+
assert_equal(fh.filename, 'a_fname')
20+
assert_true(fh.fileobj is None)
21+
assert_equal(fh.pos, 0)
22+
sio0 = StringIO()
23+
fh = FileHolder('a_test', sio0)
24+
assert_equal(fh.filename, 'a_test')
25+
assert_true(fh.fileobj is sio0)
26+
assert_equal(fh.pos, 0)
27+
fh = FileHolder('a_test_2', sio0, 3)
28+
assert_equal(fh.filename, 'a_test_2')
29+
assert_true(fh.fileobj is sio0)
30+
assert_equal(fh.pos, 3)
31+
32+
33+
def test_same_file_as():
34+
fh = FileHolder('a_fname')
35+
assert_true(fh.same_file_as(fh))
36+
fh2 = FileHolder('a_test')
37+
assert_false(fh.same_file_as(fh2))
38+
sio0 = StringIO()
39+
fh3 = FileHolder('a_fname', sio0)
40+
fh4 = FileHolder('a_fname', sio0)
41+
assert_true(fh3.same_file_as(fh4))
42+
assert_false(fh3.same_file_as(fh))
43+
fh5 = FileHolder(fileobj=sio0)
44+
fh6 = FileHolder(fileobj=sio0)
45+
assert_true(fh5.same_file_as(fh6))
46+
# Not if the filename is the same
47+
assert_false(fh5.same_file_as(fh3))
48+
# pos doesn't matter
49+
fh4_again = FileHolder('a_fname', sio0, pos=4)
50+
assert_true(fh3.same_file_as(fh4_again))
51+
52+
53+

nibabel/tests/test_nifti1.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,28 +368,27 @@ def test_set_slice_times():
368368
yield assert_equal(hdr['slice_code'], 6)
369369

370370

371-
@parametric
372371
def test_nifti1_images():
373372
shape = (2, 4, 6)
374373
npt = np.float32
375374
data = np.arange(np.prod(shape), dtype=npt).reshape(shape)
376375
affine = np.diag([1, 2, 3, 1])
377376
img = Nifti1Image(data, affine)
378-
yield assert_equal(img.get_shape(), shape)
377+
assert_equal(img.get_shape(), shape)
379378
img.set_data_dtype(npt)
380379
stio = StringIO()
381380
img.file_map['image'].fileobj = stio
382381
img.to_file_map()
383382
img2 = Nifti1Image.from_file_map(img.file_map)
384-
yield assert_array_equal(img2.get_data(), data)
383+
assert_array_equal(img2.get_data(), data)
385384
with InTemporaryDirectory() as tmpdir:
386385
for ext in ('.gz', '.bz2'):
387386
fname = os.path.join(tmpdir, 'test.nii' + ext)
388387
img.to_filename(fname)
389388
img3 = Nifti1Image.load(fname)
390-
yield assert_true(isinstance(img3, img.__class__))
391-
yield assert_array_equal(img3.get_data(), data)
392-
yield assert_equal(img3.get_header(), img.get_header())
389+
assert_true(isinstance(img3, img.__class__))
390+
assert_array_equal(img3.get_data(), data)
391+
assert_equal(img3.get_header(), img.get_header())
393392
# del to avoid windows errors of form 'The process cannot
394393
# access the file because it is being used'
395394
del img3

0 commit comments

Comments
 (0)