Repository: nilearn/nilearn

Issue:
passing nifti to surface plotting functions fails
> Also, in this case you pass the statistical map as a texture, not as a 3D volume per se, so I'm not sure how it would affect.

I was trying to stay close to the code you provided but this did lead me to try passing the path to a nifti image as stat map as `stat_map` as the doc string says it should be ok but this does not seem to work:

![image](https://github.com/nilearn/nilearn/assets/6961185/2482e5f9-0f5c-407d-8f86-f169a3c17334)


```python
import matplotlib.pyplot as plt
import numpy as np

from nilearn import datasets, plotting, surface

fsaverage = datasets.fetch_surf_fsaverage()
curv_left = surface.load_surf_data(fsaverage.curv_left)
curv_left_sign = np.sign(curv_left)

stat_map = datasets.load_sample_motor_activation_image()

print(stat_map)

# %%
engine = "matplotlib"

plotting.plot_surf_stat_map(
    fsaverage.infl_left,
    stat_map = stat_map,
    hemi="left",
    title="Surface left hemisphere",
    cmap = 'bwr',
    colorbar=True,
    threshold=1.0,
    bg_map=curv_left_sign,
    engine=engine,
    symmetric_cbar=False,
    avg_method="mean",
)
```

gives

```
/home/remi/github/nilearn/nilearn/nilearn/datasets/data/image_10426.nii.gz

Traceback (most recent call last):
  File "/home/remi/github/nilearn/nilearn/tmp.py", line 22, in <module>
    plotting.plot_surf_stat_map(
  File "/home/remi/github/nilearn/nilearn/nilearn/plotting/surf_plotting.py", line 1167, in plot_surf_stat_map
    display = plot_surf(
              ^^^^^^^^^^
  File "/home/remi/github/nilearn/nilearn/nilearn/plotting/surf_plotting.py", line 809, in plot_surf
    fig = _plot_surf_matplotlib(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/remi/github/nilearn/nilearn/nilearn/plotting/surf_plotting.py", line 580, in _plot_surf_matplotlib
    surf_map_faces = _compute_surf_map_faces_matplotlib(
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/remi/github/nilearn/nilearn/nilearn/plotting/surf_plotting.py", line 366, in _compute_surf_map_faces_matplotlib
    surf_map_data = _check_surf_map(surf_map, n_vertices)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/remi/github/nilearn/nilearn/nilearn/plotting/surf_plotting.py", line 345, in _check_surf_map
    raise ValueError("'surf_map' can only have one dimension "
ValueError: 'surf_map' can only have one dimension but has '3' dimensions
```

_Originally posted by @Remi-Gau in https://github.com/nilearn/nilearn/issues/4296#issuecomment-1983479419_
            


Discussion:
@bthirion 
Has it ever been possible to pass directly a nifti to any of the surface plotting functions without using `vol_to_surf` first to project it on a surface?

I cannot see any test that suggest this is the case but I may be missing something.

If not then this "bug" seems like an inconsistency between what the doc says and what the code does and could be resolved but just saying that stat_map cannot be a string pointing to a nifti image.
IIRC we have not supported this. Maybe @jeromedockes can correct me on this.
I'd be in favor of udpating the docstring (+potentially revising the doc to be more explicit).
you pass a nifti to the functions that are explicitly made for converting to surface before plotting, ie `view_img_on_surf` and `plot_img_on_surf` . the others accept only surfaces
OK I will try to clarify the doc.

Would it make sense to also check the extension of the files passed is among the supported ones? To align the doc with the code behavior? 

Because even if we change the doc string the users would still get the error reported above which is not super useful to figure out that nifti are not supported.
Isn't it endless ?
nope

A check of the extensions is already performed here:

https://github.com/nilearn/nilearn/blob/284a6ff1fe76898e3806f964a03780bb5f0283f9/nilearn/surface/surface.py#L757-L767

With those extensions as supported:

https://github.com/nilearn/nilearn/blob/284a6ff1fe76898e3806f964a03780bb5f0283f9/nilearn/surface/surface.py#L693-L710

I would suggest extracting this check into a separate private function that we can call earlier with for the plotting functions that do not support niftis:

```python
def _check_extensions(surf_data, data_extensions, freesurfer_data_extensions):
    if (not any(surf_data.endswith(x)
            for x in data_extensions +
            freesurfer_data_extensions)):
        raise ValueError(
            'The input type is not recognized. '
            f'{surf_data!r} was given '
            'while valid inputs are a Numpy array '
            'or one of the following file formats: '
            f"{_stringify(data_extensions)}, "
            'Freesurfer specific files such as '
            f"{_stringify(freesurfer_data_extensions)}.")
```

It is not ideal because this check would be performed twice in the end for most cases, but I don't think is a costly check.
Maybe in another PR so that we can think more globally where such an extension check is needed.

Resolving patch:
diff --git a/nilearn/conftest.py b/nilearn/conftest.py
--- a/nilearn/conftest.py
+++ b/nilearn/conftest.py
@@ -3,6 +3,7 @@
 import warnings
 
 import nibabel
+import nibabel as nb
 import numpy as np
 import pytest
 from nibabel import Nifti1Image
@@ -243,6 +244,14 @@ def img_3d_mni():
     return _img_3d_mni()
 
 
+@pytest.fixture()
+def img_3d_mni_as_file(tmp_path):
+    """Return path to a random 3D Nifti1Image in MNI space saved to disk."""
+    filename = tmp_path / "img.nii"
+    nb.save(_img_3d_mni(), filename)
+    return filename
+
+
 def _img_3d_zeros(shape=_shape_3d_default(), affine=_affine_eye()):
     """Return a default zeros filled 3D Nifti1Image (identity affine).
 
diff --git a/nilearn/plotting/surf_plotting.py b/nilearn/plotting/surf_plotting.py
--- a/nilearn/plotting/surf_plotting.py
+++ b/nilearn/plotting/surf_plotting.py
@@ -23,11 +23,20 @@
 from nilearn.plotting.img_plotting import get_colorbar_and_data_ranges
 from nilearn.plotting.js_plotting_utils import colorscale
 from nilearn.surface import load_surf_data, load_surf_mesh, vol_to_surf
-from nilearn.surface.surface import check_mesh
+from nilearn.surface.surface import (
+    FREESURFER_DATA_EXTENSIONS,
+    check_extensions,
+    check_mesh,
+)
 
 VALID_VIEWS = "anterior", "posterior", "medial", "lateral", "dorsal", "ventral"
 VALID_HEMISPHERES = "left", "right"
 
+# subset of data format extensions supported
+DATA_EXTENSIONS = ("gii",
+                   "gii.gz",
+                   "mgz",)
+
 
 MATPLOTLIB_VIEWS = {
     "left": {
@@ -813,6 +822,9 @@ def plot_surf(surf_mesh, surf_map=None, bg_map=None,
         "cbar_vmax": cbar_vmax,
         "alpha": alpha
     }
+
+    check_extensions(surf_map, DATA_EXTENSIONS, FREESURFER_DATA_EXTENSIONS)
+
     if engine == 'plotly':
         for parameter, value in parameters_not_implemented_in_plotly.items():
             if value is not None:
@@ -907,10 +919,12 @@ def plot_surf_contours(surf_mesh, roi_map, axes=None, figure=None, levels=None,
         of the :term:`mesh` :term:`faces`.
 
     roi_map : str or numpy.ndarray or list of numpy.ndarray
-        ROI map to be displayed on the surface mesh, can be a file
-        (valid formats are .gii, .mgz, .nii, .nii.gz, or Freesurfer specific
-        files such as .annot or .label), or
-        a Numpy array with a value for each :term:`vertex` of the surf_mesh.
+        ROI map to be displayed on the surface mesh,
+        can be a file
+        (valid formats are .gii, .mgz, or
+        Freesurfer specific files such as
+        .thickness, .area, .curv, .sulc, .annot, .label) or
+        a Numpy array with a value for each :term:`vertex` of the `surf_mesh`.
         The value at each :term:`vertex` one inside the ROI
         and zero inside ROI,
         or an integer giving the label number for atlases.
@@ -971,7 +985,10 @@ def plot_surf_contours(surf_mesh, roi_map, axes=None, figure=None, levels=None,
         _ = plot_surf(surf_mesh, axes=axes, **kwargs)
 
     _, faces = load_surf_mesh(surf_mesh)
+
+    check_extensions(roi_map, DATA_EXTENSIONS, FREESURFER_DATA_EXTENSIONS)
     roi = load_surf_data(roi_map)
+
     if levels is None:
         levels = np.unique(roi_map)
     if colors is None:
@@ -1058,9 +1075,10 @@ def plot_surf_stat_map(surf_mesh, stat_map, bg_map=None,
 
     stat_map : str or numpy.ndarray
         Statistical map to be displayed on the surface :term:`mesh`,
-        can be a file (valid formats are .gii, .mgz, .nii, .nii.gz, or
-        Freesurfer specific files such as .thickness, .area, .curv,
-        .sulc, .annot, .label) or
+        can be a file
+        (valid formats are .gii, .mgz, or
+        Freesurfer specific files such as
+        .thickness, .area, .curv, .sulc, .annot, .label) or
         a Numpy array with a value for each :term:`vertex` of the `surf_mesh`.
 
     bg_map : str or numpy.ndarray, optional
@@ -1183,6 +1201,7 @@ def plot_surf_stat_map(surf_mesh, stat_map, bg_map=None,
     nilearn.surface.vol_to_surf : For info on the generation of surfaces.
 
     """
+    check_extensions(stat_map, DATA_EXTENSIONS, FREESURFER_DATA_EXTENSIONS)
     loaded_stat_map = load_surf_data(stat_map)
 
     # Call get_colorbar_and_data_ranges to derive symmetric vmin, vmax
@@ -1362,7 +1381,7 @@ def plot_img_on_surf(stat_map, surf_mesh='fsaverage5', mask_img=None,
 
     Parameters
     ----------
-    stat_map : str or 3D Niimg-like object
+    stat_map : :obj:`str` or :class:`pathlib.Path` or 3D Niimg-like object
         See :ref:`extracting_data`.
 
     surf_mesh : str, dict, or None, default='fsaverage5'
@@ -1578,8 +1597,9 @@ def plot_surf_roi(surf_mesh,
     roi_map : str or numpy.ndarray or list of numpy.ndarray
         ROI map to be displayed on the surface :term:`mesh`,
         can be a file
-        (valid formats are .gii, .mgz, .nii, .nii.gz, or Freesurfer specific
-        files such as .annot or .label), or
+        (valid formats are .gii, .mgz, or
+        Freesurfer specific files such as
+        .thickness, .area, .curv, .sulc, .annot, .label) or
         a Numpy array with a value for each :term:`vertex` of the `surf_mesh`.
         The value at each vertex one inside the ROI and zero inside ROI, or an
         integer giving the label number for atlases.
@@ -1695,8 +1715,9 @@ def plot_surf_roi(surf_mesh,
 
     # preload roi and mesh to determine vmin, vmax and give more useful error
     # messages in case of wrong inputs
-
+    check_extensions(roi_map, DATA_EXTENSIONS, FREESURFER_DATA_EXTENSIONS)
     roi = load_surf_data(roi_map)
+
     idx_not_na = ~np.isnan(roi)
     if vmin is None:
         vmin = np.nanmin(roi)
diff --git a/nilearn/surface/surface.py b/nilearn/surface/surface.py
--- a/nilearn/surface/surface.py
+++ b/nilearn/surface/surface.py
@@ -5,6 +5,7 @@
 import warnings
 from collections import namedtuple
 from collections.abc import Mapping
+from pathlib import Path
 
 import nibabel
 import numpy as np
@@ -754,17 +755,9 @@ def load_surf_data(surf_data):
         for f in range(len(file_list)):
             surf_data = file_list[f]
 
-            if (not any(surf_data.endswith(x)
-                        for x in DATA_EXTENSIONS +
-                        FREESURFER_DATA_EXTENSIONS)):
-                raise ValueError(
-                    'The input type is not recognized. '
-                    f'{surf_data!r} was given '
-                    'while valid inputs are a Numpy array '
-                    'or one of the following file formats: '
-                    f"{_stringify(DATA_EXTENSIONS)}, "
-                    'Freesurfer specific files such as '
-                    f"{_stringify(FREESURFER_DATA_EXTENSIONS)}.")
+            check_extensions(surf_data,
+                             DATA_EXTENSIONS,
+                             FREESURFER_DATA_EXTENSIONS)
 
             if (surf_data.endswith('nii') or surf_data.endswith('nii.gz') or
                     surf_data.endswith('mgz')):
@@ -805,6 +798,33 @@ def load_surf_data(surf_data):
     return np.squeeze(data)
 
 
+def check_extensions(surf_data, data_extensions, freesurfer_data_extensions):
+    """Check the extension of the input file.
+
+    Should either be one one of the supported data formats
+    or one of freesurfer data formats.
+
+    Raises
+    ------
+    ValueError
+        When the input is a string or a path with an extension
+        that does not match one of the supported ones.
+    """
+    if isinstance(surf_data, Path):
+        surf_data = str(surf_data)
+    if isinstance(surf_data, str) and (not any(surf_data.endswith(x)
+                                       for x in data_extensions +
+                                       freesurfer_data_extensions)):
+        raise ValueError(
+            'The input type is not recognized. '
+            f'{surf_data!r} was given '
+            'while valid inputs are a Numpy array '
+            'or one of the following file formats: '
+            f"{_stringify(data_extensions)}, "
+            'Freesurfer specific files such as '
+            f"{_stringify(freesurfer_data_extensions)}.")
+
+
 def _gifti_img_to_mesh(gifti_img):
     """Load surface image in nibabel.gifti.GiftiImage to data.
 


Test patch:
diff --git a/nilearn/_utils/tests/test_common.py b/nilearn/_utils/tests/test_common.py
--- a/nilearn/_utils/tests/test_common.py
+++ b/nilearn/_utils/tests/test_common.py
@@ -34,7 +34,7 @@ def test_number_public_functions():
     If this is intentional, then the number should be updated in the test.
     Otherwise it means that the public API of nilearn has changed by mistake.
     """
-    assert len({_[0] for _ in all_functions()}) == 240
+    assert len({_[0] for _ in all_functions()}) == 241
 
 
 def test_number_public_classes():
diff --git a/nilearn/plotting/tests/test_html_surface.py b/nilearn/plotting/tests/test_html_surface.py
--- a/nilearn/plotting/tests/test_html_surface.py
+++ b/nilearn/plotting/tests/test_html_surface.py
@@ -8,12 +8,14 @@
 from nilearn.datasets import fetch_surf_fsaverage
 from nilearn.image import get_data
 from nilearn.plotting import html_surface
+from nilearn.plotting.html_surface import view_img_on_surf
 from nilearn.plotting.js_plotting_utils import decode
 
 from .test_js_plotting_utils import check_colors, check_html
 
 
-def _get_img():
+@pytest.fixture(scope="session")
+def mni152_template_res_2():
     return datasets.load_mni152_template(resolution=2)
 
 
@@ -118,10 +120,10 @@ def test_one_mesh_info():
         html_surface.one_mesh_info(surf_map, mesh)
 
 
-def test_full_brain_info():
+def test_full_brain_info(mni152_template_res_2):
     surfaces = datasets.fetch_surf_fsaverage()
-    img = _get_img()
-    info = html_surface._full_brain_info(img, surfaces)
+
+    info = html_surface._full_brain_info(mni152_template_res_2, surfaces)
     check_colors(info['colorscale'])
     assert {'pial_left', 'pial_right',
             'inflated_left', 'inflated_right',
@@ -145,14 +147,13 @@ def test_full_brain_info():
         "_full_brain_info. Using the deprecated name will raise an error "
         "in release 0.13",
     ):
-        html_surface.full_brain_info(img)
+        html_surface.full_brain_info(mni152_template_res_2)
 
 
-def test_fill_html_template():
+def test_fill_html_template(mni152_template_res_2):
     fsaverage = fetch_surf_fsaverage()
     mesh = surface.load_surf_mesh(fsaverage['pial_right'])
     surf_map = mesh[0][:, 0]
-    img = _get_img()
     info = html_surface._one_mesh_info(
         surf_map, fsaverage['pial_right'], '90%', black_bg=True,
         bg_map=fsaverage['sulc_right'])
@@ -160,7 +161,7 @@ def test_fill_html_template():
     html = html_surface._fill_html_template(info, embed_js=False)
     check_html(html)
     assert "jquery.min.js" in html.html
-    info = html_surface._full_brain_info(img)
+    info = html_surface._full_brain_info(mni152_template_res_2)
     info["title"] = None
     html = html_surface._fill_html_template(info)
     check_html(html)
@@ -196,31 +197,52 @@ def test_view_surf(rng):
                                bg_map=mesh[0][::2, 0])
 
 
-def test_view_img_on_surf():
-    img = _get_img()
-    surfaces = datasets.fetch_surf_fsaverage()
-    html = html_surface.view_img_on_surf(img, threshold='92.3%')
+def test_view_img_on_surf(mni152_template_res_2):
+    html = view_img_on_surf(mni152_template_res_2, threshold='92.3%')
     check_html(html)
-    html = html_surface.view_img_on_surf(img, threshold=0, surf_mesh=surfaces)
+
+    surfaces = datasets.fetch_surf_fsaverage()
+    html = view_img_on_surf(mni152_template_res_2,
+                            threshold=0,
+                            surf_mesh=surfaces)
     check_html(html)
-    html = html_surface.view_img_on_surf(img, threshold=.4, title="SOME_TITLE")
+
+    html = view_img_on_surf(mni152_template_res_2,
+                            threshold=.4,
+                            title="SOME_TITLE")
     assert "SOME_TITLE" in html.html
     check_html(html)
-    html = html_surface.view_img_on_surf(
-        img, threshold=.4, cmap='hot', black_bg=True)
+
+    html = view_img_on_surf(
+        mni152_template_res_2, threshold=.4, cmap='hot', black_bg=True)
     check_html(html)
-    with pytest.raises(DimensionError):
-        html_surface.view_img_on_surf([img, img])
-    img_4d = image.new_img_like(img, get_data(img)[:, :, :, np.newaxis])
+
+    img_4d = image.new_img_like(
+        mni152_template_res_2,
+        get_data(mni152_template_res_2)[:, :, :, np.newaxis])
     assert len(img_4d.shape) == 4
-    html = html_surface.view_img_on_surf(img, threshold='92.3%')
-    check_html(html)
-    np.clip(get_data(img), 0, None, out=get_data(img))
-    html = html_surface.view_img_on_surf(img, symmetric_cmap=False)
+
+    np.clip(get_data(mni152_template_res_2),
+            0,
+            None,
+            out=get_data(mni152_template_res_2))
+    html = view_img_on_surf(mni152_template_res_2, symmetric_cmap=False)
     check_html(html)
-    html = html_surface.view_img_on_surf(img, symmetric_cmap=False,
-                                         vol_to_surf_kwargs={
-                                             "n_samples": 1,
-                                             "radius": 0.,
-                                             "interpolation": "nearest"})
+
+    html = view_img_on_surf(mni152_template_res_2,
+                            symmetric_cmap=False,
+                            vol_to_surf_kwargs={
+                                "n_samples": 1,
+                                "radius": 0.,
+                                "interpolation": "nearest"})
     check_html(html)
+
+
+def test_view_img_on_surf_input_as_file(img_3d_mni_as_file):
+    view_img_on_surf(img_3d_mni_as_file)
+    view_img_on_surf(str(img_3d_mni_as_file))
+
+
+def test_view_img_on_surf_errors(img_3d_mni):
+    with pytest.raises(DimensionError):
+        view_img_on_surf([img_3d_mni, img_3d_mni])
diff --git a/nilearn/plotting/tests/test_surf_plotting.py b/nilearn/plotting/tests/test_surf_plotting.py
--- a/nilearn/plotting/tests/test_surf_plotting.py
+++ b/nilearn/plotting/tests/test_surf_plotting.py
@@ -879,79 +879,82 @@ def test_plot_surf_roi_colorbar_vmin_equal_across_engines(kwargs):
 
 
 def test_plot_img_on_surf_hemispheres_and_orientations(img_3d_mni):
-    nii = img_3d_mni
     # Check that all combinations of 1D or 2D hemis and orientations work.
-    plot_img_on_surf(nii, hemispheres=['right'], views=['lateral'])
-    plot_img_on_surf(nii, hemispheres=['left', 'right'], views=['lateral'])
-    plot_img_on_surf(nii,
+    plot_img_on_surf(img_3d_mni,
+                     hemispheres=['right'],
+                     views=['lateral'])
+    plot_img_on_surf(img_3d_mni,
+                     hemispheres=['left', 'right'],
+                     views=['lateral'])
+    plot_img_on_surf(img_3d_mni,
                      hemispheres=['right'],
                      views=['medial', 'lateral'])
-    plot_img_on_surf(nii,
+    plot_img_on_surf(img_3d_mni,
                      hemispheres=['left', 'right'],
                      views=['dorsal', 'medial'])
     # Check that manually set view angles work.
-    plot_img_on_surf(nii,
+    plot_img_on_surf(img_3d_mni,
                      hemispheres=['left', 'right'],
                      views=[(210.0, 90.0), (15.0, -45.0)])
 
 
 def test_plot_img_on_surf_colorbar(img_3d_mni):
-    nii = img_3d_mni
-    plot_img_on_surf(nii, hemispheres=['right'], views=['lateral'],
+    plot_img_on_surf(img_3d_mni, hemispheres=['right'], views=['lateral'],
                      colorbar=True, vmin=-5, vmax=5, threshold=3)
-    plot_img_on_surf(nii, hemispheres=['right'], views=['lateral'],
+    plot_img_on_surf(img_3d_mni, hemispheres=['right'], views=['lateral'],
                      colorbar=True, vmin=-1, vmax=5, symmetric_cbar=False,
                      threshold=3)
-    plot_img_on_surf(nii, hemispheres=['right'], views=['lateral'],
+    plot_img_on_surf(img_3d_mni, hemispheres=['right'], views=['lateral'],
                      colorbar=False)
-    plot_img_on_surf(nii, hemispheres=['right'], views=['lateral'],
+    plot_img_on_surf(img_3d_mni, hemispheres=['right'], views=['lateral'],
                      colorbar=False, cmap='roy_big_bl')
-    plot_img_on_surf(nii, hemispheres=['right'], views=['lateral'],
+    plot_img_on_surf(img_3d_mni, hemispheres=['right'], views=['lateral'],
                      colorbar=True, cmap='roy_big_bl', vmax=2)
 
 
 def test_plot_img_on_surf_inflate(img_3d_mni):
-    nii = img_3d_mni
-    plot_img_on_surf(nii, hemispheres=['right'], views=['lateral'],
+    plot_img_on_surf(img_3d_mni, hemispheres=['right'], views=['lateral'],
                      inflate=True)
 
 
 def test_plot_img_on_surf_surf_mesh(img_3d_mni):
-    nii = img_3d_mni
-    plot_img_on_surf(nii, hemispheres=['right', 'left'], views=['lateral'])
-    plot_img_on_surf(nii, hemispheres=['right', 'left'], views=['lateral'],
+    plot_img_on_surf(img_3d_mni,
+                     hemispheres=['right', 'left'],
+                     views=['lateral'])
+    plot_img_on_surf(img_3d_mni,
+                     hemispheres=['right', 'left'],
+                     views=['lateral'],
                      surf_mesh='fsaverage5')
-    surf_mesh = fetch_surf_fsaverage()
-    plot_img_on_surf(nii, hemispheres=['right', 'left'], views=['lateral'],
-                     surf_mesh=surf_mesh)
+    plot_img_on_surf(img_3d_mni,
+                     hemispheres=['right', 'left'],
+                     views=['lateral'],
+                     surf_mesh=fetch_surf_fsaverage())
 
 
 def test_plot_img_on_surf_with_invalid_orientation(img_3d_mni):
     kwargs = {"hemisphere": ["right"], "inflate": True}
-    nii = img_3d_mni
     with pytest.raises(ValueError):
-        plot_img_on_surf(nii, views=['latral'], **kwargs)
+        plot_img_on_surf(img_3d_mni, views=['latral'], **kwargs)
     with pytest.raises(ValueError):
-        plot_img_on_surf(nii, views=['dorsal', 'post'], **kwargs)
+        plot_img_on_surf(img_3d_mni, views=['dorsal', 'post'], **kwargs)
     with pytest.raises(TypeError):
-        plot_img_on_surf(nii, views=0, **kwargs)
+        plot_img_on_surf(img_3d_mni, views=0, **kwargs)
     with pytest.raises(ValueError):
-        plot_img_on_surf(nii, views=['medial', {'a': 'a'}], **kwargs)
+        plot_img_on_surf(img_3d_mni, views=['medial', {'a': 'a'}], **kwargs)
 
 
 def test_plot_img_on_surf_with_invalid_hemisphere(img_3d_mni):
-    nii = img_3d_mni
     with pytest.raises(ValueError):
         plot_img_on_surf(
-            nii, views=['lateral'], inflate=True, hemispheres=["lft]"]
+            img_3d_mni, views=['lateral'], inflate=True, hemispheres=["lft]"]
         )
     with pytest.raises(ValueError):
         plot_img_on_surf(
-            nii, views=['medial'], inflate=True, hemispheres=['lef']
+            img_3d_mni, views=['medial'], inflate=True, hemispheres=['lef']
         )
     with pytest.raises(ValueError):
         plot_img_on_surf(
-            nii,
+            img_3d_mni,
             views=['anterior', 'posterior'],
             inflate=True,
             hemispheres=['left', 'right', 'middle']
@@ -959,10 +962,9 @@ def test_plot_img_on_surf_with_invalid_hemisphere(img_3d_mni):
 
 
 def test_plot_img_on_surf_with_figure_kwarg(img_3d_mni):
-    nii = img_3d_mni
     with pytest.raises(ValueError):
         plot_img_on_surf(
-            nii,
+            img_3d_mni,
             views=["anterior"],
             hemispheres=["right"],
             figure=True,
@@ -970,10 +972,9 @@ def test_plot_img_on_surf_with_figure_kwarg(img_3d_mni):
 
 
 def test_plot_img_on_surf_with_axes_kwarg(img_3d_mni):
-    nii = img_3d_mni
     with pytest.raises(ValueError):
         plot_img_on_surf(
-            nii,
+            img_3d_mni,
             views=["anterior"],
             hemispheres=["right"],
             inflat=True,
@@ -1006,9 +1007,8 @@ def test_plot_img_on_surf_title(img_3d_mni):
 
 
 def test_plot_img_on_surf_output_file(tmp_path, img_3d_mni):
-    nii = img_3d_mni
     fname = tmp_path / 'tmp.png'
-    return_value = plot_img_on_surf(nii,
+    return_value = plot_img_on_surf(img_3d_mni,
                                     hemispheres=['right'],
                                     views=['lateral'],
                                     output_file=str(fname))
@@ -1016,6 +1016,12 @@ def test_plot_img_on_surf_output_file(tmp_path, img_3d_mni):
     assert fname.is_file(), "Saved image file could not be found."
 
 
+def test_plot_img_on_surf_input_as_file(img_3d_mni_as_file):
+    """Test nifti is supported when passed as string or path to a file."""
+    plot_img_on_surf(stat_map=img_3d_mni_as_file)
+    plot_img_on_surf(stat_map=str(img_3d_mni_as_file))
+
+
 def test_plot_surf_contours():
     mesh = generate_surf()
     # we need a valid parcellation for testing
@@ -1204,3 +1210,16 @@ def test_plot_surf_roi_default_arguments(engine, symmetric_cmap, avg_method):
                   darkness=None,  # to avoid deprecation warning
                   cmap="RdYlBu_r",
                   avg_method=avg_method)
+
+
+@pytest.mark.parametrize("function", [plot_surf_roi,
+                                      plot_surf_stat_map,
+                                      plot_surf_contours,
+                                      plot_surf])
+def test_error_nifti_not_supported(function, img_3d_mni_as_file):
+    """Test nifti file not supported by several surface plotting functions."""
+    mesh = generate_surf()
+    with pytest.raises(ValueError, match='The input type is not recognized'):
+        function(mesh, img_3d_mni_as_file)
+    with pytest.raises(ValueError, match='The input type is not recognized'):
+        function(mesh, str(img_3d_mni_as_file))