Repository: nilearn/nilearn

Issue:
rename / refactor plotting specific fixture in conftest.py
Given the nature of the fixtures that were moved in conftest.py I think that they can be  renamed, refactored to be more reusable in other tests.

This will hopefully become more obvious as we keep refactoring the test suite in general.

_Originally posted by @Remi-Gau in https://github.com/nilearn/nilearn/pull/3648#discussion_r1177709995_
            


Discussion:

Resolving patch:
diff --git a/nilearn/conftest.py b/nilearn/conftest.py
--- a/nilearn/conftest.py
+++ b/nilearn/conftest.py
@@ -181,6 +181,11 @@ def _shape_4d_default():
     return (10, 10, 10, 10)
 
 
+def _shape_4d_long():
+    """Return default shape for a long 4D image."""
+    return (10, 10, 10, 1500)
+
+
 @pytest.fixture()
 def shape_3d_default():
     """Return default shape for a 3D image."""
@@ -193,6 +198,12 @@ def shape_4d_default():
     return _shape_4d_default()
 
 
+@pytest.fixture()
+def shape_4d_long():
+    """Return long shape for a 4D image."""
+    return _shape_4d_long()
+
+
 def _img_zeros(shape, affine):
     return Nifti1Image(np.zeros(shape), affine)
 
@@ -261,6 +272,12 @@ def img_3d_ones_eye():
     return _img_3d_ones()
 
 
+@pytest.fixture
+def img_3d_ones_mni():
+    """Return a ones-filled 3D Nifti1Image (identity affine)."""
+    return _img_3d_ones(shape=_shape_3d_default(), affine=_affine_mni())
+
+
 # ------------------------ 4D IMAGES ------------------------#
 
 
@@ -272,6 +289,10 @@ def _img_4d_zeros(shape=_shape_4d_default(), affine=_affine_eye()):
     return _img_zeros(shape, affine)
 
 
+def _img_4d_mni(shape=_shape_4d_default(), affine=_affine_mni()):
+    return Nifti1Image(_rng().uniform(size=shape), affine=affine)
+
+
 @pytest.fixture
 def img_4d_zeros_eye():
     """Return a default zeros filled 4D Nifti1Image (identity affine)."""
@@ -285,33 +306,35 @@ def img_4d_ones_eye():
 
 
 @pytest.fixture
-def img_4D_rand_eye():
+def img_4d_rand_eye():
     """Return a default random filled 4D Nifti1Image (identity affine)."""
     data = _rng().rand(*_shape_4d_default())
     return Nifti1Image(data, _affine_eye())
 
 
+@pytest.fixture
+def img_4d_mni():
+    """Return a default random filled 4D Nifti1Image."""
+    return _img_4d_mni()
+
+
+@pytest.fixture
+def img_4d_long_mni(rng, shape_4d_long, affine_mni):
+    """Return a default random filled long 4D Nifti1Image."""
+    return Nifti1Image(rng.uniform(size=shape_4d_long), affine=affine_mni)
+
+
 @pytest.fixture()
-def testdata_4d_for_plotting():
-    """Random 4D images for testing figures for multivolume data."""
-    rng = _rng()
-    img_4d = Nifti1Image(rng.uniform(size=(7, 7, 3, 10)), _affine_mni())
-    img_4d_long = Nifti1Image(rng.uniform(size=(7, 7, 3, 1777)), _affine_mni())
-    img_mask = Nifti1Image(np.ones((7, 7, 3), dtype="uint8"), _affine_mni())
-    atlas = np.ones((7, 7, 3), dtype="int32")
+def img_atlas(shape_3d_default, affine_mni):
+    """Return an atlas and its labels."""
+    atlas = np.ones(shape_3d_default, dtype="int32")
     atlas[2:5, :, :] = 2
     atlas[5:8, :, :] = 3
-    img_atlas = Nifti1Image(atlas, _affine_mni())
-    atlas_labels = {
-        "gm": 1,
-        "wm": 2,
-        "csf": 3,
-    }
-    # TODO: split into several fixtures
     return {
-        "img_4d": img_4d,
-        "img_4d_long": img_4d_long,
-        "img_mask": img_mask,
-        "img_atlas": img_atlas,
-        "atlas_labels": atlas_labels,
+        "img": Nifti1Image(atlas, affine_mni),
+        "labels": {
+            "gm": 1,
+            "wm": 2,
+            "csf": 3,
+        },
     }


Test patch:
diff --git a/nilearn/image/tests/test_image.py b/nilearn/image/tests/test_image.py
--- a/nilearn/image/tests/test_image.py
+++ b/nilearn/image/tests/test_image.py
@@ -843,22 +843,20 @@ def test_math_img(
             assert result.shape == expected_result.shape
 
 
-def test_binarize_img(img_4D_rand_eye):
-    img = img_4D_rand_eye
-
+def test_binarize_img(img_4d_rand_eye):
     # Test that all output values are 1.
-    img1 = binarize_img(img)
+    img1 = binarize_img(img_4d_rand_eye)
 
     assert_array_equal(np.unique(img1.dataobj), np.array([1]))
 
     # Test that it works with threshold
-    img2 = binarize_img(img, threshold=0.5)
+    img2 = binarize_img(img_4d_rand_eye, threshold=0.5)
 
     assert_array_equal(np.unique(img2.dataobj), np.array([0, 1]))
     # Test that manual binarization equals binarize_img results.
-    img3 = img_4D_rand_eye
-    img3.dataobj[img.dataobj < 0.5] = 0
-    img3.dataobj[img.dataobj >= 0.5] = 1
+    img3 = img_4d_rand_eye
+    img3.dataobj[img_4d_rand_eye.dataobj < 0.5] = 0
+    img3.dataobj[img_4d_rand_eye.dataobj >= 0.5] = 1
 
     assert_array_equal(img2.dataobj, img3.dataobj)
 
diff --git a/nilearn/plotting/tests/test_img_plotting/test_img_plotting.py b/nilearn/plotting/tests/test_img_plotting/test_img_plotting.py
--- a/nilearn/plotting/tests/test_img_plotting/test_img_plotting.py
+++ b/nilearn/plotting/tests/test_img_plotting/test_img_plotting.py
@@ -78,18 +78,19 @@ def test_cbar_tick_format(plot_func, img_3d_mni, cbar_tick_format, tmp_path):
     plt.close()
 
 
-@pytest.mark.parametrize("plot_func", PLOTTING_FUNCS_4D)
-def test_plot_functions_4d_default_params(
-    plot_func, img_3d_mni, testdata_4d_for_plotting, tmp_path
-):
-    """Smoke-test for 4D plotting functions with default arguments."""
-    filename = tmp_path / "temp.png"
-    kwargs = {"output_file": filename}
-    if plot_func == plot_carpet:
-        kwargs["mask_img"] = testdata_4d_for_plotting["img_mask"]
-    else:
-        kwargs["bg_img"] = img_3d_mni
-    plot_func(testdata_4d_for_plotting["img_4d"], **kwargs)
+def test_plot_carpet_default_params(img_4d_mni, img_3d_ones_mni, tmp_path):
+    """Smoke-test for 4D plot_carpet with default arguments."""
+    plot_carpet(
+        img_4d_mni, mask_img=img_3d_ones_mni, output_file=tmp_path / "temp.png"
+    )
+    plt.close()
+
+
+def test_plot_prob_atlas_default_params(img_3d_mni, img_4d_mni, tmp_path):
+    """Smoke-test for plot_prob_atlas with default arguments."""
+    plot_prob_atlas(
+        img_4d_mni, bg_img=img_3d_mni, output_file=tmp_path / "temp.png"
+    )
     plt.close()
 
 
diff --git a/nilearn/plotting/tests/test_img_plotting/test_plot_carpet.py b/nilearn/plotting/tests/test_img_plotting/test_plot_carpet.py
--- a/nilearn/plotting/tests/test_img_plotting/test_plot_carpet.py
+++ b/nilearn/plotting/tests/test_img_plotting/test_plot_carpet.py
@@ -9,30 +9,29 @@
 from nilearn.plotting import plot_carpet
 
 
-def test_plot_carpet(testdata_4d_for_plotting):
+def test_plot_carpet(img_4d_mni, img_3d_ones_mni, img_4d_long_mni):
     """Check contents of plot_carpet figure against data in image."""
-    img_4d = testdata_4d_for_plotting["img_4d"]
-    img_4d_long = testdata_4d_for_plotting["img_4d_long"]
-    mask_img = testdata_4d_for_plotting["img_mask"]
-    display = plot_carpet(img_4d, mask_img, detrend=False, title="TEST")
+    display = plot_carpet(
+        img_4d_mni, img_3d_ones_mni, detrend=False, title="TEST"
+    )
     # Next two lines retrieve the numpy array from the plot
     ax = display.axes[0]
     plotted_array = ax.images[0].get_array()
     assert plotted_array.shape == (
-        np.prod(img_4d.shape[:-1]),
-        img_4d.shape[-1],
+        np.prod(img_4d_mni.shape[:-1]),
+        img_4d_mni.shape[-1],
     )
     # Make sure that the values in the figure match the values in the image
     np.testing.assert_almost_equal(
-        plotted_array.sum(), img_4d.get_fdata().sum(), decimal=3
+        plotted_array.sum(), img_4d_mni.get_fdata().sum(), decimal=3
     )
     # Save execution time and memory
     plt.close(display)
 
     fig, ax = plt.subplots()
     display = plot_carpet(
-        img_4d_long,
-        mask_img,
+        img_4d_long_mni,
+        img_3d_ones_mni,
         t_r=None,
         detrend=True,
         title="TEST",
@@ -43,22 +42,24 @@ def test_plot_carpet(testdata_4d_for_plotting):
     ax = display.axes[0]
     plotted_array = ax.images[0].get_array()
     # Check size
-    n_items = np.prod(img_4d_long.shape[:-1]) * np.ceil(
-        img_4d_long.shape[-1] / 4
+    n_items = np.prod(img_4d_long_mni.shape[:-1]) * np.ceil(
+        img_4d_long_mni.shape[-1] / 2
     )
     assert plotted_array.size == n_items
     plt.close(display)
 
 
-def test_plot_carpet_with_atlas(testdata_4d_for_plotting):
+def test_plot_carpet_with_atlas(img_4d_mni, img_atlas):
     """Test plot_carpet when using an atlas."""
-    img_4d = testdata_4d_for_plotting["img_4d"]
-    mask_img = testdata_4d_for_plotting["img_atlas"]
-    atlas_labels = testdata_4d_for_plotting["atlas_labels"]
-
     # Test atlas - labels
     # t_r is set explicitly for this test as well
-    display = plot_carpet(img_4d, mask_img, t_r=2, detrend=False, title="TEST")
+    display = plot_carpet(
+        img_4d_mni,
+        mask_img=img_atlas["img"],
+        t_r=2,
+        detrend=False,
+        title="TEST",
+    )
 
     # Check the output
     # Two axes: 1 for colorbar and 1 for imshow
@@ -71,7 +72,7 @@ def test_plot_carpet_with_atlas(testdata_4d_for_plotting):
     # Next two lines retrieve the numpy array from the plot
     ax = display.axes[0]
     colorbar = ax.images[0].get_array()
-    assert len(np.unique(colorbar)) == len(atlas_labels)
+    assert len(np.unique(colorbar)) == len(img_atlas["labels"])
 
     # Save execution time and memory
     plt.close(display)
@@ -79,9 +80,9 @@ def test_plot_carpet_with_atlas(testdata_4d_for_plotting):
     # Test atlas + labels
     fig, ax = plt.subplots()
     display = plot_carpet(
-        img_4d,
-        mask_img,
-        mask_labels=atlas_labels,
+        img_4d_mni,
+        mask_img=img_atlas["img"],
+        mask_labels=img_atlas["labels"],
         detrend=True,
         title="TEST",
         figure=fig,
@@ -95,25 +96,25 @@ def test_plot_carpet_with_atlas(testdata_4d_for_plotting):
     # The ytick labels of the colorbar should match the atlas labels
     yticklabels = ax.get_yticklabels()
     yticklabels = [yt.get_text() for yt in yticklabels]
-    assert set(yticklabels) == set(atlas_labels.keys())
+    assert set(yticklabels) == set(img_atlas["labels"].keys())
 
     # Next two lines retrieve the numpy array from the plot
     ax = display.axes[0]
     colorbar = ax.images[0].get_array()
-    assert len(np.unique(colorbar)) == len(atlas_labels)
+    assert len(np.unique(colorbar)) == len(img_atlas["labels"])
     plt.close(display)
 
 
-def test_plot_carpet_standardize(testdata_4d_for_plotting):
+def test_plot_carpet_standardize(img_4d_mni, img_3d_ones_mni):
     """Check warning is raised and then suppressed with setting standardize."""
-    img_4d = testdata_4d_for_plotting["img_4d"]
-    mask_img = testdata_4d_for_plotting["img_mask"]
     match = "default strategy for standardize"
 
     with pytest.warns(FutureWarning, match=match):
-        plot_carpet(img_4d, mask_img)
+        plot_carpet(img_4d_mni, mask_img=img_3d_ones_mni)
 
     with warnings.catch_warnings(record=True) as record:
-        plot_carpet(img_4d, mask_img, standardize="zscore_sample")
+        plot_carpet(
+            img_4d_mni, mask_img=img_3d_ones_mni, standardize="zscore_sample"
+        )
         for m in record:
             assert match not in m.message