Skip to content

Commit 8480b5f

Browse files
Copilotthewtex
andcommitted
BUG: Fix imread with single-element list and add test
Fixed the issue where imread failed when given a list with a single file path. The problem was in set_inputs() which unpacked lists when calling Set* methods. For SetFileNames, this caused a single-element list ['/path/to/file'] to be unpacked to just '/path/to/file', which SetFileNames then iterated over character-by-character. The fix adds special handling for FileNames parameter to pass the list without unpacking. Added comprehensive tests to verify both single and multi-element lists work correctly. Addresses #5623 Co-authored-by: Matt McCormick <matt@fideus.io>
1 parent 7db3af9 commit 8480b5f

File tree

3 files changed

+184
-37
lines changed

3 files changed

+184
-37
lines changed

Wrapping/Generators/Python/Tests/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ if(ITK_WRAP_unsigned_char AND WRAP_2)
201201
COMMAND
202202
${CMAKE_CURRENT_SOURCE_DIR}/test_xarray.py
203203
DATA{${WrapITK_SOURCE_DIR}/images/cthead1.png})
204+
itk_python_add_test(
205+
NAME
206+
PythonImreadSingleFileListTest
207+
COMMAND
208+
${CMAKE_CURRENT_SOURCE_DIR}/test_imread_single_file_list.py)
204209
endif()
205210
endif()
206211

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# ==========================================================================
2+
#
3+
# Copyright NumFOCUS
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# https://www.apache.org/licenses/LICENSE-2.0.txt
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
# ==========================================================================*/
18+
19+
"""Test for imread with a single-element list.
20+
21+
This tests the fix for the issue where imread fails when provided with a list
22+
containing a single file path. The issue was that SetFileNames was receiving
23+
an unpacked string instead of a list, causing it to iterate over characters.
24+
"""
25+
26+
import sys
27+
import os
28+
import itk
29+
import numpy as np
30+
import tempfile
31+
32+
33+
def test_imread_single_element_list():
34+
"""Test that imread works with a list containing a single file path."""
35+
# Create a temporary image file
36+
temp_dir = tempfile.mkdtemp()
37+
filename = os.path.join(temp_dir, "test_image.png")
38+
39+
try:
40+
# Create and save a test image
41+
image_size = (8, 10)
42+
arr = np.zeros(image_size, dtype=np.uint8)
43+
image = itk.image_from_array(arr)
44+
itk.imwrite(image, filename)
45+
46+
# Test 1: imread with a string (baseline - should always work)
47+
img_from_string = itk.imread(filename)
48+
assert img_from_string is not None
49+
# NumPy shape (8, 10) becomes ITK size [10, 8] due to row/column-major ordering
50+
assert itk.size(img_from_string)[0] == image_size[1]
51+
assert itk.size(img_from_string)[1] == image_size[0]
52+
53+
# Test 2: imread with a single-element list (the bug case)
54+
img_from_list = itk.imread([filename])
55+
assert img_from_list is not None
56+
# When reading as a series, dimension is increased by 1
57+
assert img_from_list.GetImageDimension() == 3
58+
assert itk.size(img_from_list)[0] == image_size[1]
59+
assert itk.size(img_from_list)[1] == image_size[0]
60+
assert itk.size(img_from_list)[2] == 1
61+
62+
finally:
63+
# Cleanup
64+
if os.path.exists(filename):
65+
os.remove(filename)
66+
if os.path.exists(temp_dir):
67+
os.rmdir(temp_dir)
68+
69+
70+
def test_imread_multi_element_list():
71+
"""Test that imread still works with a list containing multiple file paths."""
72+
# Create temporary image files
73+
temp_dir = tempfile.mkdtemp()
74+
filename1 = os.path.join(temp_dir, "test_image1.png")
75+
filename2 = os.path.join(temp_dir, "test_image2.png")
76+
77+
try:
78+
# Create and save test images
79+
image_size = (8, 10)
80+
arr = np.zeros(image_size, dtype=np.uint8)
81+
image = itk.image_from_array(arr)
82+
itk.imwrite(image, filename1)
83+
itk.imwrite(image, filename2)
84+
85+
# Test: imread with a multi-element list (should work as before)
86+
img_from_list = itk.imread([filename1, filename2])
87+
assert img_from_list is not None
88+
# When reading as a series, dimension is increased by 1
89+
assert img_from_list.GetImageDimension() == 3
90+
# NumPy shape (8, 10) becomes ITK size [10, 8] due to row/column-major ordering
91+
assert itk.size(img_from_list)[0] == image_size[1]
92+
assert itk.size(img_from_list)[1] == image_size[0]
93+
assert itk.size(img_from_list)[2] == 2
94+
95+
finally:
96+
# Cleanup
97+
if os.path.exists(filename1):
98+
os.remove(filename1)
99+
if os.path.exists(filename2):
100+
os.remove(filename2)
101+
if os.path.exists(temp_dir):
102+
os.rmdir(temp_dir)
103+
104+
105+
if __name__ == "__main__":
106+
test_imread_single_element_list()
107+
test_imread_multi_element_list()

0 commit comments

Comments
 (0)