Coverage for nilearn/_utils/tests/test_niimg_conversions.py: 0%

248 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-20 10:58 +0200

1"""Test the niimg_conversions. 

2 

3This test file is in nilearn/tests because Nosetest, 

4which we historically used, 

5ignores modules whose name starts with an underscore. 

6""" 

7 

8import os 

9import re 

10from pathlib import Path 

11from tempfile import mkstemp 

12 

13import numpy as np 

14import pytest 

15from nibabel import Nifti1Image, spatialimages 

16from numpy.testing import assert_array_equal 

17 

18import nilearn as ni 

19from nilearn._utils import ( 

20 check_niimg, 

21 check_niimg_3d, 

22 check_niimg_4d, 

23 repr_niimgs, 

24) 

25from nilearn._utils.exceptions import DimensionError 

26from nilearn._utils.niimg_conversions import check_same_fov, iter_check_niimg 

27from nilearn._utils.testing import ( 

28 assert_memory_less_than, 

29 with_memory_profiler, 

30 write_imgs_to_path, 

31) 

32from nilearn.image import get_data 

33 

34 

35class PhonyNiimage(spatialimages.SpatialImage): 

36 def __init__(self): 

37 self.data = np.ones((9, 9, 9, 9)) 

38 self.my_affine = np.ones((4, 4)) 

39 

40 def get_data(self): 

41 return self.data 

42 

43 def get_affine(self): 

44 return self.my_affine 

45 

46 @property 

47 def shape(self): 

48 return self.data.shape 

49 

50 @property 

51 def _data_cache(self): 

52 return self.data 

53 

54 @property 

55 def _dataobj(self): 

56 return self.data 

57 

58 

59def test_check_same_fov(affine_eye): 

60 affine_b = affine_eye * 2 

61 

62 shape_a = (2, 2, 2) 

63 shape_b = (3, 3, 3) 

64 

65 shape_a_affine_a = Nifti1Image(np.empty(shape_a), affine_eye) 

66 shape_a_affine_a_2 = Nifti1Image(np.empty(shape_a), affine_eye) 

67 shape_a_affine_b = Nifti1Image(np.empty(shape_a), affine_b) 

68 shape_b_affine_a = Nifti1Image(np.empty(shape_b), affine_eye) 

69 shape_b_affine_b = Nifti1Image(np.empty(shape_b), affine_b) 

70 

71 check_same_fov(a=shape_a_affine_a, b=shape_a_affine_a_2, raise_error=True) 

72 

73 with pytest.raises( 

74 ValueError, match="[ac] and [ac] do not have the same affine" 

75 ): 

76 check_same_fov( 

77 a=shape_a_affine_a, 

78 b=shape_a_affine_a_2, 

79 c=shape_a_affine_b, 

80 raise_error=True, 

81 ) 

82 with pytest.raises( 

83 ValueError, match="[ab] and [ab] do not have the same shape" 

84 ): 

85 check_same_fov( 

86 a=shape_a_affine_a, b=shape_b_affine_a, raise_error=True 

87 ) 

88 with pytest.raises( 

89 ValueError, match="[ab] and [ab] do not have the same affine" 

90 ): 

91 check_same_fov( 

92 a=shape_b_affine_b, b=shape_a_affine_a, raise_error=True 

93 ) 

94 

95 with pytest.raises( 

96 ValueError, match="[ab] and [ab] do not have the same shape" 

97 ): 

98 check_same_fov( 

99 a=shape_b_affine_b, b=shape_a_affine_a, raise_error=True 

100 ) 

101 

102 

103def test_check_niimg_3d(affine_eye, img_3d_zeros_eye, tmp_path): 

104 # check error for non-forced but necessary resampling 

105 with pytest.raises(TypeError, match="input should be a NiftiLike object"): 

106 check_niimg(0) 

107 

108 # check error for non-forced but necessary resampling 

109 with pytest.raises(TypeError, match="empty object"): 

110 check_niimg([]) 

111 

112 # Test dimensionality error 

113 with pytest.raises( 

114 TypeError, 

115 match="Input data has incompatible dimensionality: " 

116 "Expected dimension is 3D and you provided a list " 

117 "of 3D images \\(4D\\).", 

118 ): 

119 check_niimg_3d([img_3d_zeros_eye, img_3d_zeros_eye]) 

120 

121 # Check that a filename does not raise an error 

122 data = np.zeros((40, 40, 40, 1)) 

123 data[20, 20, 20] = 1 

124 data_img = Nifti1Image(data, affine_eye) 

125 

126 filename = write_imgs_to_path( 

127 data_img, file_path=tmp_path, create_files=True 

128 ) 

129 check_niimg_3d(filename) 

130 

131 # check data dtype equal with dtype='auto' 

132 img_check = check_niimg_3d(img_3d_zeros_eye, dtype="auto") 

133 assert ( 

134 get_data(img_3d_zeros_eye).dtype.kind == get_data(img_check).dtype.kind 

135 ) 

136 

137 

138def test_check_niimg_4d_errors(affine_eye, img_3d_zeros_eye, shape_3d_default): 

139 with pytest.raises(TypeError, match="input should be a NiftiLike object"): 

140 check_niimg_4d(0) 

141 

142 with pytest.raises(TypeError, match="empty object"): 

143 check_niimg_4d([]) 

144 

145 # This should raise an error: a 3D img is given and we want a 4D 

146 with pytest.raises( 

147 DimensionError, 

148 match="Input data has incompatible dimensionality: " 

149 "Expected dimension is 4D and you provided a 3D image.", 

150 ): 

151 check_niimg_4d(img_3d_zeros_eye) 

152 

153 a = img_3d_zeros_eye 

154 b = np.zeros(shape_3d_default) 

155 c = check_niimg_4d([a, b], return_iterator=True) 

156 with pytest.raises( 

157 TypeError, match="Error encountered while loading image #1" 

158 ): 

159 list(c) 

160 

161 b = Nifti1Image(np.zeros((10, 20, 10)), affine_eye) 

162 c = check_niimg_4d([a, b], return_iterator=True) 

163 with pytest.raises( 

164 ValueError, 

165 match="Field of view of image #1 is different from reference FOV", 

166 ): 

167 list(c) 

168 

169 

170def test_check_niimg_4d(affine_eye, img_3d_zeros_eye, shape_3d_default): 

171 # Tests with return_iterator=False 

172 img_4d_1 = check_niimg_4d([img_3d_zeros_eye, img_3d_zeros_eye]) 

173 assert get_data(img_4d_1).shape == (*shape_3d_default, 2) 

174 assert_array_equal(img_4d_1.affine, affine_eye) 

175 

176 img_4d_2 = check_niimg_4d(img_4d_1) 

177 assert_array_equal(get_data(img_4d_2), get_data(img_4d_2)) 

178 assert_array_equal(img_4d_2.affine, img_4d_2.affine) 

179 

180 # Tests with return_iterator=True 

181 img_3d_iterator = check_niimg_4d( 

182 [img_3d_zeros_eye, img_3d_zeros_eye], return_iterator=True 

183 ) 

184 img_3d_iterator_length = sum(1 for _ in img_3d_iterator) 

185 assert img_3d_iterator_length == 2 

186 

187 img_3d_iterator_1 = check_niimg_4d( 

188 [img_3d_zeros_eye, img_3d_zeros_eye], return_iterator=True 

189 ) 

190 img_3d_iterator_2 = check_niimg_4d(img_3d_iterator_1, return_iterator=True) 

191 for img_1, img_2 in zip(img_3d_iterator_1, img_3d_iterator_2): 

192 assert get_data(img_1).shape == shape_3d_default 

193 assert_array_equal(get_data(img_1), get_data(img_2)) 

194 assert_array_equal(img_1.affine, img_2.affine) 

195 

196 img_3d_iterator_1 = check_niimg_4d( 

197 [img_3d_zeros_eye, img_3d_zeros_eye], return_iterator=True 

198 ) 

199 img_3d_iterator_2 = check_niimg_4d(img_4d_1, return_iterator=True) 

200 for img_1, img_2 in zip(img_3d_iterator_1, img_3d_iterator_2): 

201 assert get_data(img_1).shape == shape_3d_default 

202 assert_array_equal(get_data(img_1), get_data(img_2)) 

203 assert_array_equal(img_1.affine, img_2.affine) 

204 

205 # Test a Niimg-like object that does not hold a shape attribute 

206 phony_img = PhonyNiimage() 

207 check_niimg_4d(phony_img) 

208 

209 

210def test_check_niimg(img_3d_zeros_eye, img_4d_zeros_eye): 

211 img_3_3d = [[[img_3d_zeros_eye, img_3d_zeros_eye]]] 

212 img_2_4d = [[img_4d_zeros_eye, img_4d_zeros_eye]] 

213 

214 with pytest.raises( 

215 DimensionError, 

216 match="Input data has incompatible dimensionality: " 

217 "Expected dimension is 2D and you provided " 

218 "a list of list of list of 3D images \\(6D\\)", 

219 ): 

220 check_niimg(img_3_3d, ensure_ndim=2) 

221 

222 with pytest.raises( 

223 DimensionError, 

224 match="Input data has incompatible dimensionality: " 

225 "Expected dimension is 4D and you provided " 

226 "a list of list of 4D images \\(6D\\)", 

227 ): 

228 check_niimg(img_2_4d, ensure_ndim=4) 

229 

230 # check data dtype equal with dtype='auto' 

231 img_3d_check = check_niimg(img_3d_zeros_eye, dtype="auto") 

232 assert ( 

233 get_data(img_3d_zeros_eye).dtype.kind 

234 == get_data(img_3d_check).dtype.kind 

235 ) 

236 

237 img_4d_check = check_niimg(img_4d_zeros_eye, dtype="auto") 

238 assert ( 

239 get_data(img_4d_zeros_eye).dtype.kind 

240 == get_data(img_4d_check).dtype.kind 

241 ) 

242 

243 

244def test_check_niimg_pathlike(img_3d_zeros_eye, tmp_path): 

245 filename = write_imgs_to_path( 

246 img_3d_zeros_eye, file_path=tmp_path, create_files=True 

247 ) 

248 filename = Path(filename) 

249 check_niimg_3d(filename) 

250 

251 

252def test_check_niimg_wildcards_errors(): 

253 # Check bad filename 

254 # Non existing file (with no magic) raise a ValueError exception 

255 nofile_path = "/tmp/nofile" 

256 file_not_found_msg = "File not found: '%s'" 

257 with pytest.raises(ValueError, match=file_not_found_msg % nofile_path): 

258 check_niimg(nofile_path) 

259 

260 # Non matching wildcard raises a ValueError exception 

261 nofile_path_wildcards = "/tmp/no*file" 

262 with pytest.raises( 

263 ValueError, match="You may have left wildcards usage activated" 

264 ): 

265 check_niimg(nofile_path_wildcards) 

266 

267 

268@pytest.mark.parametrize("shape", [(10, 10, 10), (10, 10, 10, 3)]) 

269@pytest.mark.parametrize( 

270 "wildcards", [True, False] 

271) # (With globbing behavior or not) 

272def test_check_niimg_wildcards(affine_eye, shape, wildcards, tmp_path): 

273 # First create some testing data 

274 img = Nifti1Image(np.zeros(shape), affine_eye) 

275 

276 filename = write_imgs_to_path(img, file_path=tmp_path, create_files=True) 

277 assert_array_equal( 

278 get_data(check_niimg(filename, wildcards=wildcards)), 

279 get_data(img), 

280 ) 

281 

282 

283@pytest.fixture 

284def img_in_home_folder(img_3d_mni): 

285 """Create a test file in the home folder. 

286 

287 Teardown: use yield instead of return to make sure the file 

288 is deleted after the test, 

289 even if the test fails. 

290 https://docs.pytest.org/en/stable/how-to/fixtures.html#teardown-cleanup-aka-fixture-finalization 

291 """ 

292 created_file = Path("~/test.nii") 

293 img_3d_mni.to_filename(created_file.expanduser()) 

294 assert created_file.expanduser().exists() 

295 

296 yield img_3d_mni 

297 

298 created_file.expanduser().unlink() 

299 

300 

301@pytest.mark.parametrize( 

302 "filename", ["~/test.nii", r"~/test.nii", Path("~/test.nii")] 

303) 

304def test_check_niimg_user_expand(img_in_home_folder, filename): 

305 """Check that user path are expanded.""" 

306 found_file = check_niimg(filename) 

307 

308 assert_array_equal( 

309 get_data(found_file), 

310 get_data(img_in_home_folder), 

311 ) 

312 

313 

314@pytest.mark.parametrize( 

315 "filename", 

316 [ 

317 "~/*.nii", 

318 r"~/*.nii", 

319 ["~/test.nii"], 

320 [r"~/test.nii"], 

321 [Path("~/test.nii")], 

322 ], 

323) 

324def test_check_niimg_user_expand_4d(img_in_home_folder, filename): 

325 """Check that user path are expanded. 

326 

327 Wildcards and lists should expected 4D data to be returned. 

328 """ 

329 found_file = check_niimg(filename) 

330 

331 assert_array_equal( 

332 get_data(found_file), 

333 get_data(check_niimg(img_in_home_folder, atleast_4d=True)), 

334 ) 

335 

336 

337def test_check_niimg_wildcards_one_file_name(img_3d_zeros_eye, tmp_path): 

338 file_not_found_msg = "File not found: '%s'" 

339 

340 # Testing with a glob matching exactly one filename 

341 # Using a glob matching one file containing a 3d image returns a 4d image 

342 # with 1 as last dimension. 

343 globs = write_imgs_to_path( 

344 img_3d_zeros_eye, 

345 file_path=tmp_path, 

346 create_files=True, 

347 use_wildcards=True, 

348 ) 

349 assert_array_equal( 

350 get_data(check_niimg(globs))[..., 0], 

351 get_data(img_3d_zeros_eye), 

352 ) 

353 # Disabled globbing behavior should raise an ValueError exception 

354 with pytest.raises( 

355 ValueError, match=file_not_found_msg % re.escape(globs) 

356 ): 

357 check_niimg(globs, wildcards=False) 

358 

359 # Testing with a glob matching multiple filenames 

360 img_4d = check_niimg_4d((img_3d_zeros_eye, img_3d_zeros_eye)) 

361 globs = write_imgs_to_path( 

362 img_3d_zeros_eye, 

363 img_3d_zeros_eye, 

364 file_path=tmp_path, 

365 create_files=True, 

366 use_wildcards=True, 

367 ) 

368 assert_array_equal(get_data(check_niimg(globs)), get_data(img_4d)) 

369 

370 

371def test_check_niimg_wildcards_no_expand_wildcards( 

372 img_3d_zeros_eye, img_4d_zeros_eye, tmp_path 

373): 

374 nofile_path = "/tmp/nofile" 

375 

376 file_not_found_msg = "File not found: '%s'" 

377 

378 ####### 

379 # Test when global variable is set to False => no globbing allowed 

380 ni.EXPAND_PATH_WILDCARDS = False 

381 

382 # Non existing filename (/tmp/nofile) could match an existing one through 

383 # globbing but global wildcards variable overrides this feature => raises 

384 # a ValueError 

385 with pytest.raises(ValueError, match=file_not_found_msg % nofile_path): 

386 check_niimg(nofile_path) 

387 

388 # Verify wildcards function parameter has no effect 

389 with pytest.raises(ValueError, match=file_not_found_msg % nofile_path): 

390 check_niimg(nofile_path, wildcards=False) 

391 

392 # Testing with an exact filename matching (3d case) 

393 filename = write_imgs_to_path( 

394 img_3d_zeros_eye, file_path=tmp_path, create_files=True 

395 ) 

396 assert_array_equal( 

397 get_data(check_niimg(filename)), get_data(img_3d_zeros_eye) 

398 ) 

399 

400 # Testing with an exact filename matching (4d case) 

401 filename = write_imgs_to_path( 

402 img_4d_zeros_eye, file_path=tmp_path, create_files=True 

403 ) 

404 assert_array_equal( 

405 get_data(check_niimg(filename)), get_data(img_4d_zeros_eye) 

406 ) 

407 

408 # Reverting to default behavior 

409 ni.EXPAND_PATH_WILDCARDS = True 

410 

411 

412def test_iter_check_niimgs_error(): 

413 no_file_matching = "No files matching path: %s" 

414 

415 for empty in ((), [], iter(())): 

416 with pytest.raises(ValueError, match="Input niimgs list is empty."): 

417 list(iter_check_niimg(empty)) 

418 

419 nofile_path = "/tmp/nofile" 

420 with pytest.raises(ValueError, match=no_file_matching % nofile_path): 

421 list(iter_check_niimg(nofile_path)) 

422 

423 

424def test_iter_check_niimgs(tmp_path, img_4d_zeros_eye): 

425 img_2_4d = [[img_4d_zeros_eye, img_4d_zeros_eye]] 

426 

427 # Create a test file 

428 filename = tmp_path / "nilearn_test.nii" 

429 img_4d_zeros_eye.to_filename(filename) 

430 niimgs = list(iter_check_niimg([filename])) 

431 assert_array_equal( 

432 get_data(niimgs[0]), get_data(check_niimg(img_4d_zeros_eye)) 

433 ) 

434 del niimgs 

435 

436 # Regular case 

437 niimgs = list(iter_check_niimg(img_2_4d)) 

438 assert_array_equal(get_data(niimgs[0]), get_data(check_niimg(img_2_4d))) 

439 

440 

441def _check_memory(list_img_3d): 

442 # We intentionally add an offset of memory usage to avoid non trustable 

443 # measures with memory_profiler. 

444 mem_offset = b"a" * 100 * 1024**2 

445 list(iter_check_niimg(list_img_3d)) 

446 return mem_offset 

447 

448 

449@with_memory_profiler 

450def test_iter_check_niimgs_memory(affine_eye): 

451 # Verify that iterating over a list of images doesn't consume extra 

452 # memory. 

453 assert_memory_less_than( 

454 100, 

455 0.1, 

456 _check_memory, 

457 [Nifti1Image(np.ones((100, 100, 200)), affine_eye) for _ in range(10)], 

458 ) 

459 

460 

461def test_repr_niimgs(): 

462 # Tests with file path 

463 assert repr_niimgs("test") == "test" 

464 assert repr_niimgs("test", shorten=False) == "test" 

465 

466 # Shortening long names by default 

467 long_name = "this-is-a-very-long-name-for-a-nifti-file.nii" 

468 short_name = "this-is-a-very-lon..." 

469 assert repr_niimgs(long_name) == short_name 

470 # Explicit shortening of long names 

471 assert repr_niimgs(long_name, shorten=True) == short_name 

472 

473 # Lists of long names up to length 3 

474 list_of_size_3 = [ 

475 "this-is-a-very-long-name-for-a-nifti-file.nii", 

476 "this-is-another-very-long-name-for-a-nifti-file.nii", 

477 "this-is-again-another-very-long-name-for-a-nifti-file.nii", 

478 ] 

479 # Explicit shortening, all 3 names are displayed, but shortened 

480 shortened_rep_list_of_size_3 = ( 

481 "[this-is-a-very-lon..., this-is-another-ve..., this-is-again-anot...]" 

482 ) 

483 

484 assert ( 

485 repr_niimgs(list_of_size_3, shorten=True) 

486 == shortened_rep_list_of_size_3 

487 ) 

488 

489 # Lists longer than 3 

490 # Small names - Explicit shortening 

491 long_list_small_names = ["test", "retest", "reretest", "rereretest"] 

492 shortened_rep_long_list_small_names = "[test,\n ...\n rereretest]" 

493 

494 assert ( 

495 repr_niimgs(long_list_small_names, shorten=True) 

496 == shortened_rep_long_list_small_names 

497 ) 

498 

499 # Long names - Explicit shortening 

500 list_of_size_4 = [ 

501 *list_of_size_3, 

502 "this-is-again-another-super-very-long-name-for-a-nifti-file.nii", 

503 ] 

504 shortened_rep_long_list_long_names = ( 

505 "[this-is-a-very-lon...,\n ...\n this-is-again-anot...]" 

506 ) 

507 

508 assert ( 

509 repr_niimgs(list_of_size_4, shorten=True) 

510 == shortened_rep_long_list_long_names 

511 ) 

512 

513 

514def test_repr_niimgs_force_long_names(): 

515 long_name = "this-is-a-very-long-name-for-a-nifti-file.nii" 

516 # Force long display of long names 

517 assert repr_niimgs(long_name, shorten=False) == long_name 

518 

519 # Tests with list of file paths 

520 assert repr_niimgs(["test", "retest"]) == "[test, retest]" 

521 assert repr_niimgs(["test", "retest"], shorten=False) == "[test, retest]" 

522 

523 # Force display, all 3 names are displayed 

524 list_of_size_3 = [ 

525 "this-is-a-very-long-name-for-a-nifti-file.nii", 

526 "this-is-another-very-long-name-for-a-nifti-file.nii", 

527 "this-is-again-another-very-long-name-for-a-nifti-file.nii", 

528 ] 

529 long_rep_list_of_size_3 = ( 

530 "[this-is-a-very-long-name-for-a-nifti-file.nii," 

531 " this-is-another-very-long-name-for-a-nifti-file.nii," 

532 " this-is-again-another-very-long-name-for-a-nifti-file.nii]" 

533 ) 

534 assert ( 

535 repr_niimgs(list_of_size_3, shorten=False) == long_rep_list_of_size_3 

536 ) 

537 

538 long_list_small_names = ["test", "retest", "reretest", "rereretest"] 

539 long_rep_long_list_small_names = ( 

540 "[test,\n retest,\n reretest,\n rereretest]" 

541 ) 

542 

543 assert ( 

544 repr_niimgs(long_list_small_names, shorten=False) 

545 == long_rep_long_list_small_names 

546 ) 

547 

548 # Long names - Force full display in pretty print style for readability 

549 list_of_size_4 = [ 

550 *list_of_size_3, 

551 "this-is-again-another-super-very-long-name-for-a-nifti-file.nii", 

552 ] 

553 long_rep_long_list_long_names = ( 

554 long_rep_list_of_size_3[:-1].replace(",", ",\n") 

555 + ",\n " 

556 + "this-is-again-another-super-very-long-name-for-a-nifti-file.nii]" 

557 ) 

558 

559 assert ( 

560 repr_niimgs(list_of_size_4, shorten=False) 

561 == long_rep_long_list_long_names 

562 ) 

563 

564 

565def test_repr_niimgs_with_niimg_pathlib(): 

566 # Tests with pathlib 

567 # Case with very long path and small filename 

568 long_path = Path("/this/is/a/fake/long/path/to/file.nii") 

569 short_path = Path(".../path/to/file.nii") 

570 assert repr_niimgs(long_path, shorten=True) == str(short_path) 

571 assert repr_niimgs(long_path, shorten=False) == str(long_path) 

572 

573 # Case with very long path but very long filename 

574 long_path_long_name = Path( 

575 "/this/is/a/fake/long/path/to/my_file_with_a_very_long_name.nii" 

576 ) 

577 short_name = "my_file_with_a_ver..." 

578 assert repr_niimgs(long_path_long_name, shorten=True) == short_name 

579 assert repr_niimgs(long_path_long_name, shorten=False) == str( 

580 long_path_long_name 

581 ) 

582 

583 # Case with lists 

584 list_of_paths = [ 

585 Path("/this/is/a/fake/long/path/to/file.nii"), 

586 Path("/this/is/a/fake/long/path/to/another/file2.nii"), 

587 Path("/again/another/fake/long/path/to/file3.nii"), 

588 Path("/this/is/a/fake/long/path/to/a-very-long-file-name.nii"), 

589 ] 

590 

591 shortened_list_of_paths = ( 

592 f"[...{Path('/path/to/file.nii')!s},\n" 

593 f" ...\n" 

594 f" a-very-long-file-n...]" 

595 ) 

596 

597 assert repr_niimgs(list_of_paths, shorten=True) == shortened_list_of_paths 

598 long_list_of_paths = ",\n ".join([str(_) for _ in list_of_paths]) 

599 long_list_of_paths = f"[{long_list_of_paths}]" 

600 assert repr_niimgs(list_of_paths, shorten=False) == long_list_of_paths 

601 

602 

603@pytest.mark.parametrize("shorten", [True, False]) 

604def test_repr_niimgs_with_niimg( 

605 shorten, tmp_path, affine_eye, img_3d_ones_eye, shape_3d_default 

606): 

607 # Shorten has no effect in this case 

608 assert repr_niimgs(img_3d_ones_eye, shorten=shorten).replace( 

609 "10L", "10" 

610 ) == ( 

611 f"{img_3d_ones_eye.__class__.__name__}(\nshape={shape_3d_default!r},\naffine={affine_eye!r}\n)" 

612 ) 

613 

614 # Add filename long enough to qualify for shortening 

615 fd, tmpimg1 = mkstemp(suffix="_very_long.nii", dir=str(tmp_path)) 

616 os.close(fd) 

617 img_3d_ones_eye.to_filename(tmpimg1) 

618 class_name = img_3d_ones_eye.__class__.__name__ 

619 filename = Path(img_3d_ones_eye.get_filename()) 

620 assert ( 

621 repr_niimgs(img_3d_ones_eye, shorten=False) 

622 == f"{class_name}('{filename}')" 

623 ) 

624 assert ( 

625 repr_niimgs(img_3d_ones_eye, shorten=True) 

626 == f"{class_name}('{Path(filename).name[:18]}...')" 

627 )