Skip to content

Commit 188c7ea

Browse files
committed
RF: try doing image 1 concat stuff outside loop
Try doing the checks on the first image etc outside the body of the loop.
1 parent 84d990d commit 188c7ea

File tree

2 files changed

+38
-47
lines changed

2 files changed

+38
-47
lines changed

nibabel/funcs.py

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,6 @@ def squeeze_image(img):
8888
img.extra)
8989

9090

91-
def _shape_equal_excluding(shape1, shape2, exclude_axes):
92-
""" Helper function to compare two array shapes, excluding any
93-
axis specified."""
94-
95-
if len(shape1) != len(shape2):
96-
return False
97-
98-
idx_mask = np.ones((len(shape1),), dtype=bool)
99-
idx_mask[exclude_axes] = False
100-
return np.array_equal(np.asarray(shape1)[idx_mask],
101-
np.asarray(shape2)[idx_mask])
102-
103-
10491
def concat_images(images, check_affines=True, axis=None):
10592
''' Concatenate images in list to single image, along specified dimension
10693
@@ -112,50 +99,53 @@ def concat_images(images, check_affines=True, axis=None):
11299
If True, then check that all the affines for `images` are nearly
113100
the same, raising a ``ValueError`` otherwise. Default is True
114101
axis : None or int, optional
115-
If None, concatenates on a new dimension. This requires all images
116-
to be the same shape).
117-
If not None, concatenates on the specified dimension. This requires
118-
all images to be the same shape, except on the specified dimension.
102+
If None, concatenates on a new dimension. This requires all images to
103+
be the same shape. If not None, concatenates on the specified
104+
dimension. This requires all images to be the same shape, except on
105+
the specified dimension.
119106
Returns
120107
-------
121108
concat_img : ``SpatialImage``
122109
New image resulting from concatenating `images` across last
123110
dimension
124111
'''
125-
112+
images = [load(img) if not hasattr(img, 'get_data')
113+
else img for img in images]
126114
n_imgs = len(images)
127115
if n_imgs == 0:
128116
raise ValueError("Cannot concatenate an empty list of images.")
129-
117+
img0 = images[0]
118+
affine = img0.affine
119+
header = img0.header
120+
klass = img0.__class__
121+
shape0 = img0.shape
122+
n_dim = len(shape0)
123+
if axis is None:
124+
# collect images in output array for efficiency
125+
out_shape = (n_imgs, ) + shape0
126+
out_data = np.empty(out_shape)
127+
else:
128+
# collect images in list for use with np.concatenate
129+
out_data = [None] * n_imgs
130+
# Get part of shape we need to check inside loop
131+
idx_mask = np.ones((n_dim,), dtype=bool)
132+
if axis is not None:
133+
idx_mask[axis] = False
134+
masked_shape = np.array(shape0)[idx_mask]
130135
for i, img in enumerate(images):
131-
if not hasattr(img, 'get_data'):
132-
img = load(img)
133-
134-
if i == 0: # first image, initialize data from loaded image
135-
affine = img.affine
136-
header = img.header
137-
shape = img.shape
138-
klass = img.__class__
139-
140-
if axis is None: # collect images in output array for efficiency
141-
out_shape = (n_imgs, ) + shape
142-
out_data = np.empty(out_shape)
143-
else: # collect images in list for use with np.concatenate
144-
out_data = [None] * n_imgs
145-
146-
elif check_affines and not np.all(img.affine == affine):
147-
raise ValueError('Affines do not match')
148-
149-
elif ((axis is None and not np.array_equal(shape, img.shape)) or
150-
(axis is not None and not _shape_equal_excluding(shape, img.shape,
151-
exclude_axes=[axis]))):
152-
# shape mismatch; numpy broadcast / concatenate can hide these.
153-
raise ValueError("Image #%d (shape=%s) does not match the first "
154-
"image shape (%s)." % (i, shape, img.shape))
155-
156-
out_data[i] = img.get_data()
157-
158-
del img
136+
if len(img.shape) != n_dim:
137+
raise ValueError(
138+
'Image {0} has {1} dimensions, image 0 has {2}'.format(
139+
i, len(img.shape), n_dim))
140+
if not np.all(np.array(img.shape)[idx_mask] == masked_shape):
141+
raise ValueError('shape {0} for image {1} not compatible with '
142+
'first image shape {2} with axis == {0}'.format(
143+
img.shape, i, shape0, axis))
144+
if check_affines and not np.all(img.affine == affine):
145+
raise ValueError('Affine for image {0} does not match affine '
146+
'for first image'.format(i))
147+
# Do not fill cache in image if it is empty
148+
out_data[i] = img.get_data(caching='unchanged')
159149

160150
if axis is None:
161151
out_data = np.rollaxis(out_data, 0, out_data.ndim)

nibabel/tests/test_funcs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def test_concat():
8686
else: # both 3D, appending on final axis
8787
all_data = np.concatenate([data0, data1],
8888
**np_concat_kwargs)
89+
expect_error = False
8990
except ValueError:
9091
# Shapes are not combinable
9192
expect_error = True

0 commit comments

Comments
 (0)