nibabel icon indicating copy to clipboard operation
nibabel copied to clipboard

test_resample fails with scipy 1.16

Open drew-parsons opened this issue 4 months ago • 3 comments

nibabel is failing tests using scipy 1.16 on debian CI infrastructure, https://ci.debian.net/packages/n/nibabel/ (tests with scipy 1.16 are reported under the unstable links). The bug was reported to Debian at https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1109953

The failing tests are

176s FAILED nibabel/tests/test_processing.py::test_resample_from_to - Failed: DID ...
176s FAILED nibabel/tests/test_processing.py::test_resample_to_output - Failed: DI...
176s = 2 failed, 5362 passed, 108 skipped, 11 xfailed, 1 xpassed, 26950 warnings in 137.68s (0:02:17) =

It looks like it might be a problem with API changes. The error is

176s ___________________________ test_resample_to_output ____________________________
176s 
176s caplog = <_pytest.logging.LogCaptureFixture object at 0x7fb89afd3110>
176s 
176s     @needs_scipy
176s     def test_resample_to_output(caplog):
176s         # Test routine to sample images to output space
176s         # Image aligned to output axes - no-op
176s         data = np.arange(24, dtype='int32').reshape((2, 3, 4))
176s         img = Nifti1Image(data, np.eye(4))
176s         # Check default resampling
176s         img2 = resample_to_output(img)
176s         assert_array_equal(img2.shape, (2, 3, 4))
176s         assert_array_equal(img2.affine, np.eye(4))
176s         assert_array_equal(img2.dataobj, data)
176s         # Check resampling with different voxel size specifications
176s         for vox_sizes in (None, 1, [1, 1, 1]):
176s             img2 = resample_to_output(img, vox_sizes)
176s             assert_array_equal(img2.shape, (2, 3, 4))
176s             assert_array_equal(img2.affine, np.eye(4))
176s             assert_array_equal(img2.dataobj, data)
176s         img2 = resample_to_output(img, vox_sizes)
176s         # Check 2D works
176s         img_2d = Nifti1Image(data[0], np.eye(4))
176s         for vox_sizes in (None, 1, (1, 1), (1, 1, 1)):
176s             img3 = resample_to_output(img_2d, vox_sizes)
176s             assert_array_equal(img3.shape, (3, 4, 1))
176s             assert_array_equal(img3.affine, np.eye(4))
176s             assert_array_equal(img3.dataobj, data[0][..., None])
176s         # Even 1D
176s         img_1d = Nifti1Image(data[0, 0], np.eye(4))
176s         img3 = resample_to_output(img_1d)
176s         assert_array_equal(img3.shape, (4, 1, 1))
176s         assert_array_equal(img3.affine, np.eye(4))
176s         assert_array_equal(img3.dataobj, data[0, 0][..., None, None])
176s         # But 4D does not
176s         img_4d = Nifti1Image(data.reshape(2, 3, 2, 2), np.eye(4))
176s         with pytest.raises(ValueError):
176s             resample_to_output(img_4d)
176s         # Run vox2vox_out tests, checking output shape, coordinate transform
176s         for in_shape, in_aff, vox, out_shape, out_aff in get_outspace_params():
176s             # Allow for expansion of image shape from < 3D
176s             in_n_dim = len(in_shape)
176s             if in_n_dim < 3:
176s                 in_shape = in_shape + (1,) * (3 - in_n_dim)
176s                 if not vox is None:
176s                     vox = vox + (1,) * (3 - in_n_dim)
176s                 assert len(out_shape) == in_n_dim
176s                 out_shape = out_shape + (1,) * (3 - in_n_dim)
176s             img = Nifti1Image(np.ones(in_shape), in_aff)
176s             out_img = resample_to_output(img, vox)
176s             assert_all_in(in_shape, in_aff, out_img.shape, out_img.affine)
176s             assert out_img.shape == out_shape
176s             assert_almost_equal(out_img.affine, out_aff)
176s         # Check data is as expected with some transforms
176s         # Flip first axis
176s         out_img = resample_to_output(Nifti1Image(data, np.diag([-1, 1, 1, 1])))
176s         assert_array_equal(out_img.dataobj, np.flipud(data))
176s         # Subsample voxels
176s         out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1])))
176s >       with pytest.warns(UserWarning):  # Suppress scipy warning
176s E       Failed: DID NOT WARN. No warnings of type (<class 'UserWarning'>,) were emitted.
176s E        Emitted warnings: [].
176s 
176s nibabel/tests/test_processing.py:278: Failed

Full test log at https://ci.debian.net/data/autopkgtest/unstable/amd64/n/nibabel/63127756/log.gz

These tests were run with scipy 1.16.0, not the more recent 1.16.1.

drew-parsons avatar Aug 16 '25 13:08 drew-parsons

Greetings,

I'm having a look and, for Debian, I consider applying the below patch:

--- nibabel.orig/nibabel/tests/test_processing.py
+++ nibabel/nibabel/tests/test_processing.py
@@ -169,8 +169,7 @@
     exp_out[1:, :, :] = data[1, :, :]
     assert_almost_equal(out.dataobj, exp_out)
     out = resample_from_to(img, trans_p_25_img)
-    with pytest.warns(UserWarning):  # Suppress scipy warning
-        exp_out = spnd.affine_transform(data, [1, 1, 1], [-0.25, 0, 0], order=3)
+    exp_out = spnd.affine_transform(data, [1, 1, 1], [-0.25, 0, 0], order=3)
     assert_almost_equal(out.dataobj, exp_out)
     # Test cval
     out = resample_from_to(img, trans_img, cval=99)
@@ -275,8 +274,7 @@
     assert_array_equal(out_img.dataobj, np.flipud(data))
     # Subsample voxels
     out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1])))
-    with pytest.warns(UserWarning):  # Suppress scipy warning
-        exp_out = spnd.affine_transform(data, [1 / 4, 1 / 5, 1 / 6], output_shape=(5, 11, 19))
+    exp_out = spnd.affine_transform(data, [1 / 4, 1 / 5, 1 / 6], output_shape=(5, 11, 19))
     assert_array_equal(out_img.dataobj, exp_out)
     # Unsubsample with voxel sizes
     out_img = resample_to_output(Nifti1Image(data, np.diag([4, 5, 6, 1])), [4, 5, 6])

Just dropping the check seems appropriate, as it looked like a workaround for scipy behavioral issues in the first place. Such a change might be appropriate on Debian as we know scipy is unlikely to rollback to older version than 1.16, but a scipy version check may be in order upstream.

Anyways, I confirm my patch resolved the issue on Debian unstable with scipy 1.16.2.

Have a nice day, :) Étienne.

emollier avatar Oct 24 '25 19:10 emollier

I think this is fixed in master. I'll queue up a release in the next week.

effigies avatar Dec 05 '25 21:12 effigies

I see the same thing in Fedora, and I confirm that ac0b38851ad9505c863b56e64c2c4131cf97847c is a fix.

musicinmybrain avatar Dec 05 '25 23:12 musicinmybrain