Coverage for nilearn/plotting/surface/surf_plotting.py: 0%
93 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-16 12:32 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-16 12:32 +0200
1"""Functions for surface visualization."""
3from warnings import warn
5import numpy as np
6import pandas as pd
8from nilearn import DEFAULT_DIVERGING_CMAP
9from nilearn._utils import fill_doc
10from nilearn._utils.logger import find_stack_level
11from nilearn._utils.niimg_conversions import check_niimg_3d
12from nilearn._utils.param_validation import check_params
13from nilearn.image import get_data
14from nilearn.plotting._utils import (
15 DEFAULT_ENGINE,
16 check_threshold_not_negative,
17 create_colormap_from_lut,
18)
19from nilearn.plotting.surface._utils import (
20 DEFAULT_HEMI,
21 check_hemispheres,
22 check_surface_plotting_inputs,
23 check_views,
24 get_surface_backend,
25)
26from nilearn.surface import load_surf_data, load_surf_mesh, vol_to_surf
27from nilearn.surface.surface import (
28 FREESURFER_DATA_EXTENSIONS,
29 check_extensions,
30 check_mesh_is_fsaverage,
31)
33# subset of data format extensions supported
34DATA_EXTENSIONS = (
35 "gii",
36 "gii.gz",
37 "mgz",
38)
41@fill_doc
42def plot_surf(
43 surf_mesh=None,
44 surf_map=None,
45 bg_map=None,
46 hemi=DEFAULT_HEMI,
47 view=None,
48 engine=DEFAULT_ENGINE,
49 cmap=None,
50 symmetric_cmap=None,
51 colorbar=True,
52 avg_method=None,
53 threshold=None,
54 alpha=None,
55 bg_on_data=False,
56 darkness=0.7,
57 vmin=None,
58 vmax=None,
59 cbar_vmin=None,
60 cbar_vmax=None,
61 cbar_tick_format="auto",
62 title=None,
63 title_font_size=None,
64 output_file=None,
65 axes=None,
66 figure=None,
67):
68 """Plot surfaces with optional background and data.
70 .. versionadded:: 0.3
72 Parameters
73 ----------
74 %(surf_mesh)s
75 If `None` is passed, then ``surf_map`` must be a
76 :obj:`~nilearn.surface.SurfaceImage` instance and the mesh from that
77 :obj:`~nilearn.surface.SurfaceImage` instance will be used.
79 surf_map : :obj:`str` or :class:`numpy.ndarray` or \
80 :obj:`~nilearn.surface.SurfaceImage` or None, default=None
81 Data to be displayed on the surface :term:`mesh`.
82 Can be a file (valid formats are .gii, .mgz, .nii, .nii.gz, or
83 Freesurfer specific files such as .thickness, .area, .curv, .sulc,
84 .annot, .label) or a Numpy array with a value for each :term:`vertex`
85 of the `surf_mesh`, or a :obj:`~nilearn.surface.SurfaceImage`
86 instance.
87 If `None` is passed for ``surf_mesh``, then ``surf_map`` must be a
88 :obj:`~nilearn.surface.SurfaceImage` instance and its mesh will be
89 used for plotting.
91 When specified `surf_map` is of type :class:`numpy.ndarray`, to have a
92 correct view, `hemi` should have a value corresponding to `surf_map`
93 data.
95 %(bg_map)s
97 %(hemi)s
99 %(view)s
101 engine : {'matplotlib', 'plotly'}, default='matplotlib'
103 .. versionadded:: 0.9.0
105 Selects which plotting engine will be used by ``plot_surf``.
106 Currently, only ``matplotlib`` and ``plotly`` are supported.
108 .. note::
109 To use the ``plotly`` engine, you need to have ``plotly``
110 installed.
112 .. note::
113 To be able to save figures to disk with the ``plotly`` engine, you
114 need to have ``kaleido`` installed.
116 .. warning::
117 The ``plotly`` engine is new and experimental. Please report bugs
118 that you may encounter.
120 %(cmap)s
121 If `None`, ``matplotlib`` default will be chosen.
123 symmetric_cmap : :obj:`bool`, default=None
124 Whether to use a symmetric colormap or not.
126 .. note::
127 This option is currently only implemented for the ``plotly``
128 engine.
130 When using ``plotly`` as engine, ``symmetric_cmap`` will default to
131 `False` if `None` is passed.
133 .. versionadded:: 0.9.0
135 %(colorbar)s
136 Default=True.
138 %(avg_method)s
140 .. note::
141 This option is currently only implemented for the ``matplotlib``
142 engine.
144 When using ``matplotlib`` as engine, ``avg_method`` will default to
145 ``"mean"`` if `None` is passed.
147 %(threshold)s
148 Default=None
150 alpha : :obj:`float` or None, default=None
151 Alpha level of the :term:`mesh` (not surf_data).
153 If `'auto'` is chosen, ``alpha`` will default to `0.5` when no
154 ``bg_map`` is passed and to `1` if a ``bg_map`` is passed.
156 .. note::
157 This option is currently only implemented for the ``matplotlib``
158 engine.
160 When using ``matplotlib`` as engine, ``alpha`` will default to `"auto"`
161 if `None` is passed.
163 %(bg_on_data)s
165 %(darkness)s
166 Default=1.
168 %(vmin)s
170 %(vmax)s
172 cbar_vmin : :obj:`float` or None, default=None
173 Lower bound for the colorbar.
174 If `None`, the value will be set from the data.
176 .. note::
177 This option is currently only implemented for the ``matplotlib``
178 engine.
180 cbar_vmax : :obj:`float` or None, default=None
181 Upper bound for the colorbar.
182 If `None`, the value will be set from the data.
184 .. note::
185 This option is currently only implemented for the ``matplotlib``
186 engine.
188 %(cbar_tick_format)s
189 Default="auto" which will select:
191 - `'%%.2g'` (scientific notation) with ``matplotlib`` engine.
192 - `'.1f'` (rounded floats) with ``plotly`` engine.
194 .. versionadded:: 0.7.1
196 %(title)s
198 title_font_size : :obj:`int`, default=None
199 Size of the title font
201 .. note::
202 This option is currently only implemented for the ``plotly``
203 engine.
205 When using ``plotly`` as engine, ``title_font_size`` will default to
206 `18` if `None` is passed.
208 .. versionadded:: 0.9.0
210 %(output_file)s
212 axes : instance of matplotlib axes or None, default=None
213 The axes instance to plot to. The projection must be `"3d"` (e.g.,
214 `figure, axes = plt.subplots(subplot_kw={'projection': "3d"})`,
215 where axes should be passed.).
216 If `None`, a new axes is created.
218 .. note::
219 This option is currently only implemented for the ``matplotlib``
220 engine.
222 %(figure)s
224 .. note::
225 This option is currently only implemented for the ``matplotlib``
226 engine.
228 Returns
229 -------
230 fig : :class:`~matplotlib.figure.Figure` or
231 :class:`~nilearn.plotting.displays.PlotlySurfaceFigure`
232 The surface figure. If ``engine='matplotlib'`` then a
233 :class:`~matplotlib.figure.Figure` is returned.
234 If ``engine='plotly'``, then a
235 :class:`~nilearn.plotting.displays.PlotlySurfaceFigure`
236 is returned
238 See Also
239 --------
240 nilearn.datasets.fetch_surf_fsaverage : For surface data object to be
241 used as background map for this plotting function.
243 nilearn.plotting.plot_surf_roi : For plotting statistical maps on brain
244 surfaces.
246 nilearn.plotting.plot_surf_stat_map : for plotting statistical maps on
247 brain surfaces.
249 nilearn.surface.vol_to_surf : For info on the generation of surfaces.
250 """
251 check_params(locals())
252 check_threshold_not_negative(threshold)
253 surf_map, surf_mesh, bg_map = check_surface_plotting_inputs(
254 surf_map, surf_mesh, hemi, bg_map
255 )
256 check_extensions(surf_map, DATA_EXTENSIONS, FREESURFER_DATA_EXTENSIONS)
258 backend = get_surface_backend(engine)
259 fig = backend._plot_surf(
260 surf_mesh,
261 surf_map=surf_map,
262 bg_map=bg_map,
263 hemi=hemi,
264 view=view,
265 cmap=cmap,
266 symmetric_cmap=symmetric_cmap,
267 colorbar=colorbar,
268 avg_method=avg_method,
269 threshold=threshold,
270 alpha=alpha,
271 bg_on_data=bg_on_data,
272 darkness=darkness,
273 vmin=vmin,
274 vmax=vmax,
275 cbar_vmin=cbar_vmin,
276 cbar_vmax=cbar_vmax,
277 cbar_tick_format=cbar_tick_format,
278 title=title,
279 title_font_size=title_font_size,
280 output_file=output_file,
281 axes=axes,
282 figure=figure,
283 )
285 return fig
288@fill_doc
289def plot_surf_contours(
290 surf_mesh=None,
291 roi_map=None,
292 hemi=DEFAULT_HEMI,
293 levels=None,
294 labels=None,
295 colors=None,
296 legend=False,
297 cmap="tab20",
298 title=None,
299 output_file=None,
300 axes=None,
301 figure=None,
302 **kwargs,
303):
304 """Plot contours of ROIs on a surface, optionally over a statistical map.
306 Parameters
307 ----------
308 %(surf_mesh)s
309 If None is passed, then ``roi_map`` must be a
310 :obj:`~nilearn.surface.SurfaceImage` instance and the mesh from that
311 :obj:`~nilearn.surface.SurfaceImage` instance will be used.
313 roi_map : :obj:`str` or :class:`numpy.ndarray` or \
314 :obj:`~nilearn.surface.SurfaceImage` or None, default=None
315 ROI map to be displayed on the surface mesh, can be a file (valid
316 formats are .gii, .mgz, or Freesurfer specific files such as
317 .thickness, .area, .curv, .sulc, .annot, .label) or a Numpy array with
318 a value for each :term:`vertex` of the `surf_mesh`.
319 The value at each :term:`vertex` one inside the ROI and zero inside
320 ROI, or an integer giving the label number for atlases.
321 If None is passed for ``surf_mesh`` then ``roi_map`` must be a
322 :obj:`~nilearn.surface.SurfaceImage` instance and its the mesh will be
323 used for plotting.
325 When specified `roi_map` is of type :class:`numpy.ndarray`, to have a
326 correct view, `hemi` should have a value corresponding to `roi_map`
327 data.
329 %(hemi)s
330 It is only used if ``roi_map`` is :obj:`~nilearn.surface.SurfaceImage`
331 and / or ``surf_mesh`` is :obj:`~nilearn.surface.PolyMesh`.
332 Otherwise a warning will be displayed.
334 .. versionadded:: 0.11.0
336 levels : :obj:`list` of :obj:`int`, or None, default=None
337 A list of indices of the regions that are to be outlined.
338 Every index needs to correspond to one index in ``roi_map``.
339 If `None`, all regions in ``roi_map`` are used.
341 labels : :obj:`list` of :obj:`str` or None, or None, default=None
342 A list of labels for the individual regions of interest.
343 Provide `None` as list entry to skip showing the label of that region.
344 If `None`, no labels are used.
346 colors : :obj:`list` of matplotlib color names or RGBA values, or None,
347 default=None
348 Colors to be used.
350 legend : :obj:`bool`, default=False
351 Whether to plot a legend of region's labels.
353 %(cmap)s
354 Default='tab20'.
356 %(title)s
358 %(output_file)s
360 axes : instance of matplotlib axes or None, default=None
361 The axes instance to plot to. The projection must be `"3d"` (e.g.,
362 `figure, axes = plt.subplots(subplot_kw={'projection': "3d"})`,
363 where axes should be passed.).
364 If `None`, uses axes from figure if available, else creates new axes.
366 %(figure)s
368 kwargs : extra keyword arguments, optional
369 Extra keyword arguments passed to :func:`~nilearn.plotting.plot_surf`.
371 See Also
372 --------
373 nilearn.datasets.fetch_surf_fsaverage : For surface data object to be
374 used as background map for this plotting function.
376 nilearn.plotting.plot_surf_stat_map : for plotting statistical maps on
377 brain surfaces.
379 nilearn.surface.vol_to_surf : For info on the generation of surfaces.
380 """
381 roi_map, surf_mesh, _ = check_surface_plotting_inputs(
382 roi_map, surf_mesh, hemi, map_var_name="roi_map"
383 )
384 check_extensions(roi_map, DATA_EXTENSIONS, FREESURFER_DATA_EXTENSIONS)
386 backend = get_surface_backend(DEFAULT_ENGINE)
387 fig = backend._plot_surf_contours(
388 surf_mesh=surf_mesh,
389 roi_map=roi_map,
390 hemi=hemi,
391 levels=levels,
392 labels=labels,
393 colors=colors,
394 legend=legend,
395 cmap=cmap,
396 title=title,
397 output_file=output_file,
398 axes=axes,
399 figure=figure,
400 **kwargs,
401 )
402 return fig
405@fill_doc
406def plot_surf_stat_map(
407 surf_mesh=None,
408 stat_map=None,
409 bg_map=None,
410 hemi=DEFAULT_HEMI,
411 view=None,
412 engine=DEFAULT_ENGINE,
413 cmap=DEFAULT_DIVERGING_CMAP,
414 symmetric_cmap=None,
415 colorbar=True,
416 avg_method=None,
417 threshold=None,
418 alpha=None,
419 bg_on_data=False,
420 darkness=0.7,
421 vmin=None,
422 vmax=None,
423 symmetric_cbar="auto",
424 cbar_tick_format="auto",
425 title=None,
426 title_font_size=None,
427 output_file=None,
428 axes=None,
429 figure=None,
430 **kwargs,
431):
432 """Plot a stats map on a surface :term:`mesh` with optional background.
434 .. versionadded:: 0.3
436 Parameters
437 ----------
438 %(surf_mesh)s
439 If None is passed, then ``stat_map`` must be a
440 :obj:`~nilearn.surface.SurfaceImage` instance and the mesh from
441 that :obj:`~nilearn.surface.SurfaceImage` instance will be used.
443 stat_map : :obj:`str` or :class:`numpy.ndarray` or None, default=None
444 Statistical map to be displayed on the surface :term:`mesh`,
445 can be a file
446 (valid formats are .gii, .mgz, or
447 Freesurfer specific files such as
448 .thickness, .area, .curv, .sulc, .annot, .label) or
449 a Numpy array with a value for each :term:`vertex` of the `surf_mesh`.
450 If None is passed for ``surf_mesh``
451 then ``stat_map``
452 must be a :obj:`~nilearn.surface.SurfaceImage` instance
453 and its the mesh will be used for plotting.
455 When specified `surf_map` is of type :class:`numpy.ndarray`, to have a
456 correct view, `hemi` should have a value corresponding to `surf_map`
457 data.
459 %(bg_map)s
461 %(hemi)s
463 %(view)s
465 engine : {'matplotlib', 'plotly'}, default='matplotlib'
467 .. versionadded:: 0.9.0
469 Selects which plotting engine will be used by ``plot_surf_stat_map``.
470 Currently, only ``matplotlib`` and ``plotly`` are supported.
472 .. note::
473 To use the ``plotly`` engine you need to
474 have ``plotly`` installed.
476 .. note::
477 To be able to save figures to disk with the ``plotly``
478 engine you need to have ``kaleido`` installed.
480 .. warning::
481 The ``plotly`` engine is new and experimental.
482 Please report bugs that you may encounter.
485 %(cmap)s
486 default="RdBu_r"
488 symmetric_cmap : :obj:`bool`, default=None
489 Whether to use a symmetric colormap or not.
491 .. note::
492 This option is currently only implemented for the ``plotly``
493 engine.
495 When using ``plotly`` as engine, ``symmetric_cmap`` will default to
496 `False` if `None` is passed.
498 .. versionadded:: 0.12.0
500 %(colorbar)s
502 .. note::
503 This function uses a symmetric colorbar for the statistical map.
505 Default=True.
507 %(avg_method)s
509 .. note::
510 This option is currently only implemented for the
511 ``matplotlib`` engine.
513 When using matplotlib as engine,
514 `avg_method` will default to ``"mean"`` if ``None`` is passed.
516 .. versionadded:: 0.10.3dev
518 %(threshold)s
519 Default=None
521 alpha : :obj:`float` or 'auto' or None, default=None
522 Alpha level of the :term:`mesh` (not the stat_map).
523 Will default to ``"auto"`` if ``None`` is passed.
524 If 'auto' is chosen, alpha will default to .5 when no bg_map is
525 passed and to 1 if a bg_map is passed.
527 .. note::
528 This option is currently only implemented for the
529 ``matplotlib`` engine.
531 %(bg_on_data)s
533 %(darkness)s
534 Default=1.
536 .. note::
537 This option is currently only implemented for the
538 ``matplotlib`` engine.
540 %(vmin)s
542 %(vmax)s
544 %(symmetric_cbar)s
546 %(cbar_tick_format)s
547 Default="auto" which will select:
549 - '%%.2g' (scientific notation) with ``matplotlib`` engine.
550 - '.1f' (rounded floats) with ``plotly`` engine.
552 .. versionadded:: 0.7.1
554 %(title)s
556 title_font_size : :obj:`int`, default=None
557 Size of the title font (only implemented for the plotly engine).
559 .. versionadded:: 0.9.0
561 %(output_file)s
563 axes : instance of matplotlib axes or None, default=None
564 The axes instance to plot to. The projection must be '3d' (e.g.,
565 `figure, axes = plt.subplots(subplot_kw={'projection': '3d'})`,
566 where axes should be passed.).
567 If None, a new axes is created.
569 .. note::
570 This option is currently only implemented for the
571 ``matplotlib`` engine.
573 %(figure)s
575 .. note::
576 This option is currently only implemented for the
577 ``matplotlib`` engine.
579 kwargs : :obj:`dict`, optional
580 Keyword arguments passed to :func:`nilearn.plotting.plot_surf`.
582 See Also
583 --------
584 nilearn.datasets.fetch_surf_fsaverage: For surface data object to be
585 used as background map for this plotting function.
587 nilearn.plotting.plot_surf: For brain surface visualization.
589 nilearn.surface.vol_to_surf : For info on the generation of surfaces.
590 """
591 check_params(locals())
592 check_threshold_not_negative(threshold)
594 stat_map, surf_mesh, bg_map = check_surface_plotting_inputs(
595 stat_map, surf_mesh, hemi, bg_map, map_var_name="stat_map"
596 )
597 check_extensions(stat_map, DATA_EXTENSIONS, FREESURFER_DATA_EXTENSIONS)
598 loaded_stat_map = load_surf_data(stat_map)
600 backend = get_surface_backend(engine)
601 # derive symmetric vmin, vmax and colorbar limits depending on
602 # symmetric_cbar settings
603 cbar_vmin, cbar_vmax, vmin, vmax = (
604 backend._adjust_colorbar_and_data_ranges(
605 loaded_stat_map,
606 vmin=vmin,
607 vmax=vmax,
608 symmetric_cbar=symmetric_cbar,
609 )
610 )
612 fig = plot_surf(
613 surf_mesh,
614 surf_map=loaded_stat_map,
615 bg_map=bg_map,
616 hemi=hemi,
617 view=view,
618 engine=engine,
619 cmap=cmap,
620 symmetric_cmap=symmetric_cmap,
621 colorbar=colorbar,
622 avg_method=avg_method,
623 threshold=threshold,
624 alpha=alpha,
625 bg_on_data=bg_on_data,
626 darkness=darkness,
627 vmin=vmin,
628 vmax=vmax,
629 cbar_vmin=cbar_vmin,
630 cbar_vmax=cbar_vmax,
631 cbar_tick_format=cbar_tick_format,
632 title=title,
633 title_font_size=title_font_size,
634 output_file=output_file,
635 axes=axes,
636 figure=figure,
637 **kwargs,
638 )
639 return fig
642@fill_doc
643def plot_img_on_surf(
644 stat_map,
645 surf_mesh="fsaverage5",
646 mask_img=None,
647 hemispheres=None,
648 views=None,
649 cmap=DEFAULT_DIVERGING_CMAP,
650 colorbar=True,
651 threshold=None,
652 bg_on_data=False,
653 inflate=False,
654 vmin=None,
655 vmax=None,
656 symmetric_cbar="auto",
657 cbar_tick_format="%i",
658 title=None,
659 output_file=None,
660 **kwargs,
661):
662 """Plot multiple views of plot_surf_stat_map \
663 in a single figure.
665 It projects stat_map into meshes and plots views of
666 left and right hemispheres. The *views* argument defines the views
667 that are shown. This function returns the fig, axes elements from
668 matplotlib unless kwargs sets and output_file, in which case nothing
669 is returned.
671 Parameters
672 ----------
673 stat_map : :obj:`str` or :class:`pathlib.Path` or 3D Niimg-like object
674 See :ref:`extracting_data`.
676 surf_mesh : :obj:`str`, :obj:`dict`, or None, default='fsaverage5'
677 If str, either one of the two:
678 'fsaverage5': the low-resolution fsaverage5 :term:`mesh` (10242 nodes)
679 'fsaverage': the high-resolution fsaverage :term:`mesh` (163842 nodes)
680 If dict, a dictionary with keys: ['infl_left', 'infl_right',
681 'pial_left', 'pial_right', 'sulc_left', 'sulc_right'], where
682 values are surface :term:`mesh` geometries as accepted
683 by plot_surf_stat_map.
685 mask_img : Niimg-like object or None, default=None
686 The mask is passed to vol_to_surf.
687 Samples falling out of this mask or out of the image are ignored
688 during projection of the volume to the surface.
689 If ``None``, don't apply any mask.
691 hemispheres : :obj:`list` of :obj:`str`, default=None
692 Hemispheres to display.
693 Will default to ``['left', 'right']`` if ``None`` or "both" is passed.
695 views : :obj:`list` of :obj:`str`, default=None
696 A list containing all views to display.
697 The montage will contain as many rows as views specified by
698 display mode. Order is preserved, and left and right hemispheres
699 are shown on the left and right sides of the figure.
700 Will default to ``['lateral', 'medial']`` if ``None`` is passed.
702 %(cmap)s
703 Default="RdBu_r".
705 %(colorbar)s
707 .. note::
708 This function uses a symmetric colorbar for the statistical map.
710 Default=True.
712 %(threshold)s
713 Default=None
715 %(bg_on_data)s
717 inflate : :obj:`bool`, default=False
718 If True, display images in inflated brain.
719 If False, display images in pial surface.
721 %(vmin)s
723 %(vmax)s
725 %(symmetric_cbar)s
727 %(cbar_tick_format)s
729 %(title)s
731 %(output_file)s
733 kwargs : :obj:`dict`, optional
734 keyword arguments passed to plot_surf_stat_map.
736 .. note::
737 Parameters "figure", "axes", and "engine" which are valid for
738 ``plot_surf_stat_map`` are not valid for ``plot_img_on_surf``.
740 See Also
741 --------
742 nilearn.datasets.fetch_surf_fsaverage : For surface data object to be
743 used as the default background map for this plotting function.
745 nilearn.surface.vol_to_surf : For info on the generation of surfaces.
747 nilearn.plotting.plot_surf_stat_map : For info on kwargs options
748 accepted by plot_img_on_surf.
750 """
751 check_params(locals())
752 check_threshold_not_negative(threshold)
754 for arg in ("figure", "axes", "engine"):
755 if arg in kwargs:
756 raise ValueError(
757 f"plot_img_on_surf does not accept {arg} as an argument"
758 )
760 if hemispheres in (None, "both", ["both"]):
761 hemispheres = ["left", "right"]
762 if not isinstance(hemispheres, list):
763 hemispheres = [hemispheres]
764 hemis = check_hemispheres(hemispheres)
766 if views is None:
767 views = ["lateral", "medial"]
768 modes = check_views(views)
770 stat_map = check_niimg_3d(stat_map, dtype="auto")
771 surf_mesh = check_mesh_is_fsaverage(surf_mesh)
773 mesh_prefix = "infl" if inflate else "pial"
774 surf = {
775 "left": surf_mesh[f"{mesh_prefix}_left"],
776 "right": surf_mesh[f"{mesh_prefix}_right"],
777 }
778 texture = {
779 "left": vol_to_surf(
780 stat_map, surf_mesh["pial_left"], mask_img=mask_img
781 ),
782 "right": vol_to_surf(
783 stat_map, surf_mesh["pial_right"], mask_img=mask_img
784 ),
785 }
787 backend = get_surface_backend(DEFAULT_ENGINE)
788 # get vmin and vmax for entire data (all hemis)
789 _, _, vmin, vmax = backend._adjust_colorbar_and_data_ranges(
790 get_data(stat_map),
791 vmin=vmin,
792 vmax=vmax,
793 symmetric_cbar=symmetric_cbar,
794 )
796 fig = backend._plot_img_on_surf(
797 surf,
798 surf_mesh=surf_mesh,
799 stat_map=stat_map,
800 texture=texture,
801 hemis=hemis,
802 modes=modes,
803 bg_on_data=bg_on_data,
804 inflate=inflate,
805 output_file=output_file,
806 title=title,
807 colorbar=colorbar,
808 vmin=vmin,
809 vmax=vmax,
810 threshold=threshold,
811 symmetric_cbar=symmetric_cbar,
812 cmap=cmap,
813 cbar_tick_format=cbar_tick_format,
814 **kwargs,
815 )
816 return fig
819@fill_doc
820def plot_surf_roi(
821 surf_mesh=None,
822 roi_map=None,
823 bg_map=None,
824 hemi=DEFAULT_HEMI,
825 view=None,
826 engine=DEFAULT_ENGINE,
827 cmap="gist_ncar",
828 colorbar=True,
829 avg_method=None,
830 threshold=None,
831 alpha=None,
832 bg_on_data=False,
833 darkness=0.7,
834 vmin=None,
835 vmax=None,
836 cbar_tick_format="auto",
837 title=None,
838 title_font_size=None,
839 output_file=None,
840 axes=None,
841 figure=None,
842 **kwargs,
843):
844 """Plot ROI on a surface :term:`mesh` with optional background.
846 .. versionadded:: 0.3
848 Parameters
849 ----------
850 %(surf_mesh)s
851 If None is passed, then ``roi_map`` must be a
852 :obj:`~nilearn.surface.SurfaceImage` instance and the mesh from that
853 :obj:`~nilearn.surface.SurfaceImage` instance will be used.
855 roi_map : :obj:`str` or :class:`numpy.ndarray` or \
856 :obj:`list` of :class:`numpy.ndarray` or \
857 :obj:`~nilearn.surface.SurfaceImage` or None, \
858 default=None
859 ROI map to be displayed on the surface :term:`mesh`,
860 can be a file
861 (valid formats are .gii, .mgz, or
862 Freesurfer specific files such as
863 .thickness, .area, .curv, .sulc, .annot, .label) or
864 a Numpy array with a value for each :term:`vertex` of the `surf_mesh`
865 or a :obj:`~nilearn.surface.SurfaceImage` instance.
866 The value at each vertex one inside the ROI and zero inside ROI, or an
867 integer giving the label number for atlases.
868 If None is passed for ``surf_mesh``
869 then ``roi_map``
870 must be a :obj:`~nilearn.surface.SurfaceImage` instance
871 and its the mesh will be used for plotting.
873 When specified `roi_map` is of type :class:`numpy.ndarray`, to have a
874 correct view, `hemi` should have a value corresponding to `roi_map`
875 data.
877 %(bg_map)s
879 %(hemi)s
881 %(view)s
883 engine : {'matplotlib', 'plotly'}, default='matplotlib'
885 .. versionadded:: 0.9.0
887 Selects which plotting engine will be used by ``plot_surf_roi``.
888 Currently, only ``matplotlib`` and ``plotly`` are supported.
890 .. note::
891 To use the ``plotly`` engine you need to have
892 ``plotly`` installed.
894 .. note::
895 To be able to save figures to disk with ``plotly`` engine
896 you need to have ``kaleido`` installed.
898 .. warning::
899 The ``plotly`` engine is new and experimental.
900 Please report bugs that you may encounter.
902 %(cmap_lut)s
903 Default='gist_ncar'.
905 %(colorbar)s
906 Default=True
908 %(avg_method)s
910 .. note::
911 This option is currently only implemented for the
912 ``matplotlib`` engine.
914 When using matplotlib as engine,
915 `avg_method` will default to ``"median"`` if ``None`` is passed.
917 %(threshold)s
918 Default=None
920 .. note::
921 By default, the regions that are labeled 0 are not thresholded.
922 Threshold should be set to a very small number, ex. 1e-14 to
923 threshold the those 0 labeled regions.
925 alpha : :obj:`float` or 'auto' or None, default=None
926 Alpha level of the :term:`mesh` (not surf_data).
927 When using matplotlib as engine,
928 `alpha` will default to ``"auto"`` if ``None`` is passed.
929 If 'auto' is chosen, alpha will default to 0.5 when no bg_map
930 is passed and to 1 if a bg_map is passed.
932 .. note::
933 This option is currently only implemented for the
934 ``matplotlib`` engine.
936 %(bg_on_data)s
938 %(darkness)s
939 Default=1.
941 .. note::
942 This option is currently only implemented for the
943 ``matplotlib`` engine.
945 %(vmin)s
947 %(vmax)s
949 %(cbar_tick_format)s
950 Default="auto" which defaults to integers format:
952 - "%%i" for ``matplotlib`` engine.
953 - "." for ``plotly`` engine.
955 .. versionadded:: 0.7.1
957 %(title)s
959 title_font_size : :obj:`int`, default=None
960 Size of the title font (only implemented for the plotly engine).
962 .. versionadded:: 0.9.0
964 %(output_file)s
966 axes : Axes instance or None, default=None
967 The axes instance to plot to. The projection must be '3d' (e.g.,
968 `plt.subplots(subplot_kw={'projection': '3d'})`).
969 If None, a new axes is created.
971 .. note::
972 This option is currently only implemented for the
973 ``matplotlib`` engine.
975 %(figure)s
977 .. note::
978 This option is currently only implemented for the
979 ``matplotlib`` engine.
981 kwargs : :obj:`dict`, optional
982 Keyword arguments passed to :func:`nilearn.plotting.plot_surf`.
984 See Also
985 --------
986 nilearn.datasets.fetch_surf_fsaverage: For surface data object to be
987 used as background map for this plotting function.
989 nilearn.plotting.plot_surf: For brain surface visualization.
991 nilearn.surface.vol_to_surf : For info on the generation of surfaces.
992 """
993 check_params(locals())
994 check_threshold_not_negative(threshold)
995 roi_map, surf_mesh, bg_map = check_surface_plotting_inputs(
996 roi_map, surf_mesh, hemi, bg_map
997 )
998 check_extensions(roi_map, DATA_EXTENSIONS, FREESURFER_DATA_EXTENSIONS)
1000 # preload roi and mesh to determine vmin, vmax and give more useful
1001 # error messages in case of wrong inputs
1002 roi = load_surf_data(roi_map)
1004 if roi.ndim != 1:
1005 raise ValueError(
1006 "roi_map can only have one dimension but has "
1007 f"{roi.ndim} dimensions"
1008 )
1009 if (roi < 0).any():
1010 # TODO raise ValueError in release 0.13
1011 warn(
1012 (
1013 "Negative values in roi_map will no longer be allowed in"
1014 " Nilearn version 0.13"
1015 ),
1016 DeprecationWarning,
1017 stacklevel=find_stack_level(),
1018 )
1020 mesh = load_surf_mesh(surf_mesh)
1021 if roi.shape[0] != mesh.n_vertices:
1022 raise ValueError(
1023 "roi_map does not have the same number of vertices "
1024 "as the mesh. If you have a list of indices for the "
1025 "ROI you can convert them into a ROI map like this:\n"
1026 "roi_map = np.zeros(n_vertices)\n"
1027 "roi_map[roi_idx] = 1"
1028 )
1030 idx_not_na = ~np.isnan(roi)
1031 if vmin is None:
1032 vmin = float(np.nanmin(roi))
1033 if vmax is None:
1034 vmax = float(1 + np.nanmax(roi))
1036 if not np.array_equal(roi[idx_not_na], roi[idx_not_na].astype(int)):
1037 # TODO raise ValueError in release 0.13
1038 warn(
1039 (
1040 "Non-integer values in roi_map will no longer be allowed "
1041 "in Nilearn version 0.13"
1042 ),
1043 DeprecationWarning,
1044 stacklevel=find_stack_level(),
1045 )
1046 if isinstance(cmap, pd.DataFrame):
1047 cmap = create_colormap_from_lut(cmap)
1049 params = {
1050 "avg_method": avg_method,
1051 "cbar_tick_format": cbar_tick_format,
1052 }
1054 backend = get_surface_backend(engine)
1055 backend._adjust_plot_roi_params(params)
1057 fig = backend._plot_surf(
1058 mesh,
1059 surf_map=roi,
1060 bg_map=bg_map,
1061 hemi=hemi,
1062 view=view,
1063 cmap=cmap,
1064 colorbar=colorbar,
1065 avg_method=params["avg_method"],
1066 threshold=threshold,
1067 alpha=alpha,
1068 bg_on_data=bg_on_data,
1069 darkness=darkness,
1070 vmin=vmin,
1071 vmax=vmax,
1072 cbar_tick_format=params["cbar_tick_format"],
1073 title=title,
1074 title_font_size=title_font_size,
1075 output_file=output_file,
1076 axes=axes,
1077 figure=figure,
1078 **kwargs,
1079 )
1080 return fig