Repository: nilearn/nilearn

Issue:
[DOC] Add cross-reference links to type definitions in public surface functions
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe your proposed suggestion in detail.

Use sphinx cross-referencing where possible in surface module public functions so that rendered docstrings will link the types to their source documentation.

See functions https://nilearn.github.io/stable/modules/surface.html

Example: 
```python 
"""
  radius : float
    The size (in mm) of the neighbourhood... 
"""
```

becomes

```python
"""
    radius : :obj:`float`
        The size (in mm) of the neighbourhood... 
"""
```

For more examples check out docstrings in other modules where this was done like: 

https://github.com/nilearn/nilearn/blob/321494420/nilearn/interfaces/bids/query.py#L146

And the corresponding rendered version:

https://nilearn.github.io/stable/modules/generated/nilearn.interfaces.bids.get_bids_files.html#nilearn.interfaces.bids.get_bids_files

### List any pages that would be impacted.

_No response_


Discussion:
Sounds like another issue that could generate "siblings" for other modules if we need to create other issues during the hackathon.

Resolving patch:
diff --git a/nilearn/surface/surface.py b/nilearn/surface/surface.py
--- a/nilearn/surface/surface.py
+++ b/nilearn/surface/surface.py
@@ -129,30 +129,31 @@ def _ball_sample_locations(
 
     Parameters
     ----------
-    mesh : pair of np arrays.
+    mesh : pair of :obj:`numpy.ndarray`s.
         `mesh[0]` contains the 3d coordinates of the vertices
         (shape n_vertices, 3)
         `mesh[1]` contains, for each triangle,
         the indices into `mesh[0]` of its vertices (shape n_triangles, 3)
 
-    affine : array of shape (4, 4)
+    affine : :obj:`numpy.ndarray` of shape (4, 4)
         Affine transformation from image voxels to the vertices' coordinate
         space.
 
-    ball_radius : float, optional
+    ball_radius : :obj:`float`, optional
         Size in mm of the neighbourhood around each vertex in which to draw
         samples. Default=3.0.
 
-    n_points : int, optional
+    n_points : :obj:`int`, optional
         Number of samples to draw for each vertex. Default=20.
 
-    depth : None
-        Raises a ValueError if not None because incompatible with this sampling
-        strategy.
+    depth : `None`
+        Raises a `ValueError` if not `None` because incompatible with this
+        sampling strategy.
 
     Returns
     -------
-    sample_location_voxel_space : numpy array, shape (n_vertices, n_points, 3)
+    sample_location_voxel_space : :obj:`numpy.ndarray`, \
+        shape (n_vertices, n_points, 3)
         The locations, in voxel space, from which to draw samples.
         First dimension iterates over mesh vertices, second dimension iterates
         over the sample points associated to a vertex, third dimension is x, y,
@@ -188,30 +189,31 @@ def _line_sample_locations(
 
     Parameters
     ----------
-    mesh : pair of numpy.ndarray
+    mesh : pair of :obj:`numpy.ndarray`
         `mesh[0]` contains the 3d coordinates of the vertices
         (shape n_vertices, 3)
         `mesh[1]` contains, for each triangle,
         the indices into `mesh[0]` of its vertices (shape n_triangles, 3)
 
-    affine : numpy.ndarray of shape (4, 4)
+    affine : :obj:`numpy.ndarray` of shape (4, 4)
         Affine transformation from image voxels to the vertices' coordinate
         space.
 
-    segment_half_width : float, optional
+    segment_half_width : :obj:`float`, optional
         Size in mm of the neighbourhood around each vertex in which to draw
         samples. Default=3.0.
 
-    n_points : int, optional
+    n_points : :obj:`int`, optional
         Number of samples to draw for each vertex. Default=10.
 
-    depth : sequence of floats or None, optional
+    depth : sequence of :obj:`float` or None, optional
         Cortical depth, expressed as a fraction of segment_half_width.
         Overrides n_points.
 
     Returns
     -------
-    sample_location_voxel_space : numpy array, shape (n_vertices, n_points, 3)
+    sample_location_voxel_space : :obj:`numpy.ndarray`, \
+            shape (n_vertices, n_points, 3)
         The locations, in voxel space, from which to draw samples.
         First dimension iterates over mesh vertices, second dimension iterates
         over the sample points associated to a vertex, third dimension is x, y,
@@ -272,14 +274,14 @@ def _masked_indices(sample_locations, img_shape, mask=None):
 
     Parameters
     ----------
-    sample_locations : array, shape(n_sample_locations, 3)
+    sample_locations : :obj:`numpy.ndarray`, shape(n_sample_locations, 3)
         The coordinates of candidate interpolation points.
 
-    img_shape : tuple
+    img_shape : :obj:`tuple`
         The dimensions of the image to be sampled.
 
-    mask : array of shape img_shape or None, optional
-        Part of the image to be masked. If None, don't apply any mask.
+    mask : :obj:`numpy.ndarray` of shape img_shape or `None`, optional
+        Part of the image to be masked. If `None`, don't apply any mask.
 
     Returns
     -------
@@ -304,7 +306,7 @@ def _projection_matrix(mesh, affine, img_shape, kind='auto', radius=3.,
 
     Parameters
     ----------
-    mesh : str or numpy.ndarray
+    mesh : :obj:`str` or :obj:`numpy.ndarray`
         Either a file containing surface mesh geometry (valid formats
         are .gii or Freesurfer specific files such as .orig, .pial,
         .sphere, .white, .inflated) or a list of two Numpy arrays,
@@ -312,11 +314,11 @@ def _projection_matrix(mesh, affine, img_shape, kind='auto', radius=3.,
         vertices, the second containing the indices (into coords)
         of the mesh faces.
 
-    affine : array of shape (4, 4)
+    affine : :obj:`numpy.ndarray` of shape (4, 4)
         Affine transformation from image voxels to the vertices' coordinate
         space.
 
-    img_shape : 3-tuple of integers
+    img_shape : 3-tuple of :obj:`int`
         The shape of the image to be projected.
 
     kind : {'auto', 'depth', 'line', 'ball'}, optional
@@ -334,23 +336,23 @@ def _projection_matrix(mesh, affine, img_shape, kind='auto', radius=3.,
             Samples are regularly spaced inside a ball centered at the mesh
             vertex.
 
-    radius : float, optional
+    radius : :obj:`float`, optional
         The size (in mm) of the neighbourhood from which samples are drawn
-        around each node. Ignored if `inner_mesh` is not None.
+        around each node. Ignored if `inner_mesh` is not `None`.
         Default=3.0.
 
-    n_points : int or None, optional
-        How many samples are drawn around each vertex and averaged. If None,
+    n_points : :obj:`int` or None, optional
+        How many samples are drawn around each vertex and averaged. If `None`,
         use a reasonable default for the chosen sampling strategy (20 for
         'ball' or 10 for lines ie using `line` or an `inner_mesh`).
         For performance reasons, if using kind="ball", choose `n_points` in
         [10, 20, 40, 80, 160] (default is 20), because cached positions are
         available.
 
-    mask : array of shape img_shape or None, optional
-        Part of the image to be masked. If None, don't apply any mask.
+    mask : :obj:`numpy.ndarray` of shape img_shape or `None`, optional
+        Part of the image to be masked. If `None`, don't apply any mask.
 
-    inner_mesh : str or numpy.ndarray, optional
+    inner_mesh : :obj:`str` or :obj:`numpy.ndarray`, optional
         Either a file containing surface mesh or a pair of ndarrays
         (coordinates, triangles). If provided this is an inner surface that is
         nested inside the one represented by `mesh` -- e.g. `mesh` is a pial
@@ -360,13 +362,13 @@ def _projection_matrix(mesh, affine, img_shape, kind='auto', radius=3.,
         are then sampled along the line joining these two points (if `kind` is
         'auto' or 'depth').
 
-    depth : sequence of floats or None, optional
+    depth : sequence of :obj:`float` or `None`, optional
         Cortical depth, expressed as a fraction of segment_half_width.
         overrides n_points. Should be None if kind is 'ball'
 
     Returns
     -------
-    proj : scipy.sparse.csr_matrix
+    proj : :obj:`scipy.sparse.csr_matrix`
        Shape (n_voxels, n_mesh_vertices). The dot product of this matrix with
        an image (represented as a column vector) gives the projection onto mesh
        vertices.
@@ -474,14 +476,14 @@ def vol_to_surf(img, surf_mesh,
     img : Niimg-like object, 3d or 4d.
         See :ref:`extracting_data`.
 
-    surf_mesh : str, pathlib.Path, numpy.ndarray, or Mesh
+    surf_mesh : :obj:`str`, :obj:`pathlib.Path`, :obj:`numpy.ndarray`, or Mesh
         Either a file containing surface mesh geometry (valid formats
         are .gii or Freesurfer specific files such as .orig, .pial,
         .sphere, .white, .inflated) or two Numpy arrays organized in a list,
         tuple or a namedtuple with the fields "coordinates" and "faces", or
         a Mesh object with "coordinates" and "faces" attributes.
 
-    radius : float, optional
+    radius : :obj:`float`, optional
         The size (in mm) of the neighbourhood from which samples are drawn
         around each node. Ignored if `inner_mesh` is provided.
         Default=3.0.
@@ -520,19 +522,19 @@ def vol_to_surf(img, surf_mesh,
             Samples are regularly spaced inside a ball centered at the mesh
             vertex.
 
-    n_samples : int or None, optional
+    n_samples : :obj:`int` or `None`, optional
         How many samples are drawn around each vertex and averaged. If
-        ``None``, use a reasonable default for the chosen sampling strategy
+        `None`, use a reasonable default for the chosen sampling strategy
         (20 for 'ball' or 10 for 'line').
         For performance reasons, if using `kind` ="ball", choose `n_samples` in
         [10, 20, 40, 80, 160] (default is 20), because cached positions are
         available.
 
-    mask_img : Niimg-like object or None, optional
+    mask_img : Niimg-like object or `None`, optional
         Samples falling out of this mask or out of the image are ignored.
-        If ``None``, don't apply any mask.
+        If `None`, don't apply any mask.
 
-    inner_mesh : str or numpy.ndarray, optional
+    inner_mesh : :obj:`str` or :obj:`numpy.ndarray`, optional
         Either a file containing a surface mesh or a pair of ndarrays
         (coordinates, triangles). If provided this is an inner surface that is
         nested inside the one represented by `surf_mesh` -- e.g. `surf_mesh` is
@@ -542,7 +544,7 @@ def vol_to_surf(img, surf_mesh,
         values for index i are then sampled along the line joining these two
         points (if `kind` is 'auto' or 'depth').
 
-    depth : sequence of floats or None, optional
+    depth : sequence of :obj:`float` or `None`, optional
         The cortical depth of samples. If provided, n_samples is ignored.
         When `inner_mesh` is provided, each element of `depth` is a fraction of
         the distance from `mesh` to `inner_mesh`: 0 is exactly on the outer
@@ -558,7 +560,7 @@ def vol_to_surf(img, surf_mesh,
 
     Returns
     -------
-    texture : numpy.ndarray, 1d or 2d.
+    texture : :obj:`numpy.ndarray`, 1d or 2d.
         If 3D image is provided, a 1d vector is returned, containing one value
         for each mesh node.
         If 4D image is provided, a 2d array is returned, where each row
@@ -669,7 +671,7 @@ def _load_surf_files_gifti_gzip(surf_file):
 
 def _gifti_img_to_data(gifti_img):
     """Load surface image e.g. sulcal depth or statistical map \
-    in nibabel.gifti.GiftiImage to data.
+        in nibabel.gifti.GiftiImage to data.
 
     Used by load_surf_data function in common to surface sulcal data
     acceptable to .gii or .gii.gz
@@ -711,7 +713,7 @@ def load_surf_data(surf_data):
 
     Parameters
     ----------
-    surf_data : str, pathlib.Path, or numpy.ndarray
+    surf_data : :obj:`str`, :obj:`pathlib.Path`, or :obj:`numpy.ndarray`
         Either a file containing surface data (valid format are .gii,
         .gii.gz, .mgz, .nii, .nii.gz, or Freesurfer specific files such as
         .thickness, .curv, .sulc, .annot, .label), lists of 1D data files are
@@ -719,7 +721,7 @@ def load_surf_data(surf_data):
 
     Returns
     -------
-    data : numpy.ndarray
+    data : :obj:`numpy.ndarray`
         An array containing surface data
 
     """
@@ -830,7 +832,8 @@ def load_surf_mesh(surf_mesh):
 
     Parameters
     ----------
-    surf_mesh : str, pathlib.Path, or numpy.ndarray or Mesh
+    surf_mesh : :obj:`str`, :obj:`pathlib.Path`, or \
+        :obj:`numpy.ndarray` or Mesh
         Either a file containing surface mesh geometry (valid formats
         are .gii .gii.gz or Freesurfer specific files such as .orig, .pial,
         .sphere, .white, .inflated) or two Numpy arrays organized in a list,
@@ -841,7 +844,7 @@ def load_surf_mesh(surf_mesh):
     -------
     mesh : Mesh
         With the fields "coordinates" and "faces", each containing a
-        numpy.ndarray
+        :obj:`numpy.ndarray`
 
     """
     # if input is a filename, try to load it
@@ -934,7 +937,7 @@ def load_surface(surface):
     Returns
     -------
     surface : Surface
-        With the fields "mesh" (Mesh object) and "data" (numpy.ndarray).
+        With the fields "mesh" (Mesh object) and "data" (:obj:`numpy.ndarray`).
 
     """
     # Handle the case where we received a Surface
@@ -960,11 +963,11 @@ def load_surface(surface):
 
 
 def _check_mesh(mesh):
-    """Check that mesh data is either a str, \
-    or a dict with sufficient entries.
+    """Check that mesh data is either a :obj:`str`, \
+        or a :obj:`dict` with sufficient entries.
 
-    Used by plotting.surf_plotting.plot_img_on_surf and
-    plotting.html_surface.full_brain_info
+    Used by :func:`plotting.surf_plotting.plot_img_on_surf` and
+    :func:`plotting.html_surface.full_brain_info`
 
     """
     if isinstance(mesh, str):
@@ -986,14 +989,14 @@ def check_mesh_and_data(mesh, data):
 
     Parameters
     ----------
-    mesh : str or numpy.ndarray or Mesh
+    mesh : :obj:`str` or :obj:`numpy.ndarray` or Mesh
         Either a file containing surface mesh geometry (valid formats
         are .gii .gii.gz or Freesurfer specific files such as .orig, .pial,
         .sphere, .white, .inflated) or two Numpy arrays organized in a list,
         tuple or a namedtuple with the fields "coordinates" and "faces", or a
         Mesh object with "coordinates" and "faces" attributes.
 
-    data : str or numpy.ndarray
+    data : :obj:`str` or :obj:`numpy.ndarray`
         Either a file containing surface data (valid format are .gii,
         .gii.gz, .mgz, .nii, .nii.gz, or Freesurfer specific files such as
         .thickness, .area, .curv, .sulc, .annot, .label),
@@ -1005,7 +1008,7 @@ def check_mesh_and_data(mesh, data):
     mesh : Mesh
         Checked mesh.
 
-    data : numpy.ndarray
+    data : :obj:`numpy.ndarray`
         Checked data.
 
     """


Test patch: