Coverage for nilearn/plotting/img_plotting.py: 0%
446 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 to do automatic visualization of Niimg-like objects.
3See http://nilearn.github.io/stable/manipulating_images/input_output.html
5Only matplotlib is required.
6"""
8import collections.abc
9import functools
10import numbers
11import warnings
13import matplotlib as mpl
14import matplotlib.pyplot as plt
15import numpy as np
16import pandas as pd
17from matplotlib import gridspec as mgs
18from matplotlib.colors import LinearSegmentedColormap
19from nibabel.spatialimages import SpatialImage
20from scipy.ndimage import binary_fill_holes
22from nilearn import DEFAULT_DIVERGING_CMAP
23from nilearn._utils import (
24 as_ndarray,
25 check_niimg_3d,
26 check_niimg_4d,
27 compare_version,
28 fill_doc,
29 logger,
30)
31from nilearn._utils.extmath import fast_abs_percentile
32from nilearn._utils.logger import find_stack_level
33from nilearn._utils.ndimage import get_border_data
34from nilearn._utils.niimg import safe_get_data
35from nilearn._utils.param_validation import check_params, check_threshold
36from nilearn.datasets import load_mni152_template
37from nilearn.image import (
38 get_data,
39 iter_img,
40 math_img,
41 new_img_like,
42 resample_to_img,
43)
44from nilearn.image.resampling import reorder_img
45from nilearn.maskers import NiftiMasker
46from nilearn.masking import apply_mask, compute_epi_mask
47from nilearn.plotting import cm
48from nilearn.plotting._utils import (
49 check_threshold_not_negative,
50 create_colormap_from_lut,
51 get_cbar_ticks,
52 get_colorbar_and_data_ranges,
53 save_figure_if_needed,
54)
55from nilearn.plotting.displays import get_projector, get_slicer
56from nilearn.signal import clean
59def show():
60 """Show all the figures generated by nilearn and/or matplotlib.
62 This function is equivalent to :func:`matplotlib.pyplot.show`,
63 but is skipped on the 'Agg' backend where it has no effect other
64 than to emit a warning.
66 """
67 if mpl.get_backend().lower() != "agg": # avoid warnings
68 plt.show()
71###############################################################################
72# Core, usage-agnostic functions
75@fill_doc
76def _plot_img_with_bg(
77 img,
78 bg_img=None,
79 cut_coords=None,
80 output_file=None,
81 display_mode="ortho",
82 colorbar=False,
83 figure=None,
84 axes=None,
85 title=None,
86 threshold=None,
87 annotate=True,
88 draw_cross=True,
89 black_bg=False,
90 vmin=None,
91 vmax=None,
92 bg_vmin=None,
93 bg_vmax=None,
94 interpolation="nearest",
95 display_factory=get_slicer,
96 cbar_vmin=None,
97 cbar_vmax=None,
98 cbar_tick_format="%.2g",
99 brain_color=(0.5, 0.5, 0.5),
100 decimals=False,
101 radiological=False,
102 transparency=None,
103 transparency_range=None,
104 **kwargs,
105):
106 """Refer to the docstring of plot_img for parameters not listed below.
108 Parameters
109 ----------
110 %(img)s
111 Image to plot.
113 %(bg_img)s
114 If nothing is specified, no background image is plotted.
115 Default=None.
117 %(cut_coords)s
119 %(output_file)s
121 %(display_mode)s
123 %(colorbar)s
124 Default=False.
126 %(figure)s
128 %(axes)s
130 %(title)s
132 %(threshold)s
134 %(annotate)s
136 %(draw_cross)s
138 %(black_bg)s
139 Default=False.
141 %(vmin)s
143 %(vmax)s
145 bg_vmin : :obj:`float`, optional
146 vmin for `bg_img`.
148 bg_vmax : :obj:`float`, optional
149 vmax for `bg_img`.
151 interpolation : :obj:`str`, default='nearest'
152 Passed to the add_overlay calls.
154 display_factory : function, default=get_slicer
155 Takes a display_mode argument and return a display class.
157 cbar_tick_format : :obj:`str`, default="%%.2g" (scientific notation)
158 Controls how to format the tick labels of the colorbar.
159 Ex: use "%%i" to display as integers.
161 decimals : :obj:`int` or :obj:`bool`, default=False
162 Number of decimal places on slice position annotation.
163 If False,
164 the slice position is integer without decimal point.
166 %(radiological)s
168 %(transparency)s
170 %(transparency_range)s
172 kwargs : extra keyword arguments, optional
173 Extra keyword arguments passed
174 to the display.add_overlay method (see below).
175 Ultimately passed to `matplotlib.pyplot.imshow` via
176 :meth:`~nilearn.plotting.displays.BaseSlicer.add_overlay`.
178 Returns
179 -------
180 display : :class:`~nilearn.plotting.displays.OrthoSlicer` or \
181 :class:`~nilearn.plotting.displays.OrthoProjector` or None
182 An instance of the OrthoSlicer or OrthoProjector class depending on the
183 function defined in ``display_factory``. If ``output_file`` is defined,
184 None is returned.
186 Raises
187 ------
188 ValueError
189 if the specified threshold is a negative number
190 """
191 check_params(locals())
192 check_threshold_not_negative(threshold)
194 show_nan_msg = False
195 if vmax is not None and np.isnan(vmax):
196 vmax = None
197 show_nan_msg = True
198 if vmin is not None and np.isnan(vmin):
199 vmin = None
200 show_nan_msg = True
201 if show_nan_msg:
202 nan_msg = (
203 "NaN is not permitted for the vmax and vmin arguments.\n"
204 "Tip: Use np.nanmax() instead of np.max()."
205 )
206 warnings.warn(nan_msg, stacklevel=find_stack_level())
208 if isinstance(cut_coords, numbers.Number) and display_mode in (
209 "ortho",
210 "tiled",
211 ):
212 raise ValueError(
213 f"The input given for display_mode='{display_mode}' "
214 "needs to be a list of 3d world coordinates in (x, y, z). "
215 "You provided single cut, "
216 f"cut_coords={cut_coords}"
217 )
219 if img is not False and img is not None:
220 img = check_niimg_3d(img, dtype="auto")
221 data = safe_get_data(img, ensure_finite=True)
222 affine = img.affine
224 if np.isnan(np.sum(data)):
225 data = np.nan_to_num(data)
227 # Deal with automatic settings of plot parameters
228 if threshold == "auto":
229 # Threshold epsilon below a percentile value, to be sure that some
230 # voxels pass the threshold
231 threshold = float(fast_abs_percentile(data)) - 1e-5
233 img = new_img_like(img, as_ndarray(data), affine)
235 display = display_factory(display_mode)(
236 img,
237 threshold=threshold,
238 cut_coords=cut_coords,
239 figure=figure,
240 axes=axes,
241 black_bg=black_bg,
242 colorbar=colorbar,
243 brain_color=brain_color,
244 radiological=radiological,
245 )
246 if bg_img is not None:
247 bg_img = check_niimg_3d(bg_img)
248 display.add_overlay(
249 bg_img,
250 vmin=bg_vmin,
251 vmax=bg_vmax,
252 cmap="gray",
253 interpolation=interpolation,
254 )
256 if img is not None and img is not False:
257 display.add_overlay(
258 new_img_like(img, data, affine),
259 threshold=threshold,
260 interpolation=interpolation,
261 colorbar=colorbar,
262 vmin=vmin,
263 vmax=vmax,
264 cbar_vmin=cbar_vmin,
265 cbar_vmax=cbar_vmax,
266 cbar_tick_format=cbar_tick_format,
267 transparency=transparency,
268 transparency_range=transparency_range,
269 **kwargs,
270 )
271 if radiological:
272 for display_axis in display.axes.values():
273 display_axis.ax.invert_xaxis()
274 if annotate:
275 display.annotate(decimals=decimals)
276 if draw_cross:
277 display.draw_cross()
278 if title is not None and title != "":
279 display.title(title)
280 if hasattr(display, "_cbar"):
281 cbar = display._cbar
282 new_tick_locs = _get_cropped_cbar_ticks(
283 cbar.vmin, cbar.vmax, threshold, n_ticks=len(cbar.locator.locs)
284 )
285 cbar.set_ticks(new_tick_locs)
287 return save_figure_if_needed(display, output_file)
290def _get_cropped_cbar_ticks(cbar_vmin, cbar_vmax, threshold=None, n_ticks=5):
291 """Return ticks for cropped colorbars."""
292 new_tick_locs = np.linspace(cbar_vmin, cbar_vmax, n_ticks)
293 if threshold is not None:
294 # Case where cbar is either all positive or all negative
295 if 0 <= cbar_vmin <= cbar_vmax or cbar_vmin <= cbar_vmax <= 0:
296 idx_closest = np.argmin(
297 [abs(abs(new_tick_locs) - threshold) for _ in new_tick_locs]
298 )
299 new_tick_locs[idx_closest] = threshold
300 # Case where we do a symmetric thresholding
301 # within an asymmetric cbar
302 # and both threshold values are within bounds
303 elif cbar_vmin <= -threshold <= threshold <= cbar_vmax:
304 new_tick_locs = get_cbar_ticks(
305 cbar_vmin, cbar_vmax, threshold, n_ticks=len(new_tick_locs)
306 )
307 # Case where one of the threshold values is out of bounds
308 else:
309 idx_closest = np.argmin(
310 [abs(new_tick_locs - threshold) for _ in new_tick_locs]
311 )
312 new_tick_locs[idx_closest] = (
313 -threshold if threshold > cbar_vmax else threshold
314 )
315 return new_tick_locs
318@fill_doc
319def plot_img(
320 img,
321 cut_coords=None,
322 output_file=None,
323 display_mode="ortho",
324 figure=None,
325 axes=None,
326 title=None,
327 threshold=None,
328 annotate=True,
329 draw_cross=True,
330 black_bg=False,
331 colorbar=True,
332 cbar_tick_format="%.2g",
333 resampling_interpolation="continuous",
334 bg_img=None,
335 vmin=None,
336 vmax=None,
337 radiological=False,
338 decimals=False,
339 cmap="gray",
340 transparency=None,
341 transparency_range=None,
342 **kwargs,
343):
344 """Plot cuts of a given image.
346 By default Frontal, Axial, and Lateral.
348 Parameters
349 ----------
350 %(img)s
352 %(cut_coords)s
354 %(output_file)s
356 %(display_mode)s
358 %(figure)s
360 %(axes)s
362 %(title)s
364 %(threshold)s
366 %(annotate)s
368 %(draw_cross)s
370 %(black_bg)s
371 Default=False.
373 %(colorbar)s
374 Default=True.
376 cbar_tick_format : :obj:`str`, default="%%.2g" (scientific notation)
377 Controls how to format the tick labels of the colorbar.
378 Ex: use "%%i" to display as integers.
380 %(resampling_interpolation)s
381 Default='continuous'.
383 %(bg_img)s
384 If nothing is specified, no background image is plotted.
385 Default=None.
387 %(vmin)s
389 %(vmax)s
391 %(radiological)s
393 decimals : :obj:`int` or :obj:`bool`, default=False
394 Number of decimal places on slice position annotation.
395 If False,
396 the slice position is integer without decimal point.
398 %(cmap)s
399 default="gray"
401 %(transparency)s
403 %(transparency_range)s
405 kwargs : extra keyword arguments, optional
406 Extra keyword arguments
407 ultimately passed to `matplotlib.pyplot.imshow` via
408 :meth:`~nilearn.plotting.displays.BaseSlicer.add_overlay`.
410 Returns
411 -------
412 display : :class:`~nilearn.plotting.displays.OrthoSlicer` or None
413 An instance of the OrthoSlicer class. If ``output_file`` is defined,
414 None is returned.
416 Raises
417 ------
418 ValueError
419 if the specified threshold is a negative number
421 .. note::
423 This is a low-level function. For most use cases, other plotting
424 functions might be more appropriate and easier to use.
426 .. seealso::
428 :func:`~nilearn.plotting.plot_anat`
429 To simply plot anatomical images
430 :func:`~nilearn.plotting.plot_epi`
431 To simply plot raw EPI images
432 :func:`~nilearn.plotting.plot_roi`
433 To simply plot max-prob atlases (3D images)
434 :func:`~nilearn.plotting.plot_prob_atlas`
435 To simply plot probabilistic atlases (4D images)
436 :mod:`nilearn.plotting`
437 See API reference for other options
438 """
439 check_params(locals())
440 check_threshold_not_negative(threshold)
442 display = _plot_img_with_bg(
443 img,
444 cut_coords=cut_coords,
445 output_file=output_file,
446 display_mode=display_mode,
447 figure=figure,
448 axes=axes,
449 title=title,
450 threshold=threshold,
451 annotate=annotate,
452 draw_cross=draw_cross,
453 resampling_interpolation=resampling_interpolation,
454 black_bg=black_bg,
455 colorbar=colorbar,
456 cbar_tick_format=cbar_tick_format,
457 bg_img=bg_img,
458 vmin=vmin,
459 vmax=vmax,
460 radiological=radiological,
461 decimals=decimals,
462 cmap=cmap,
463 transparency=transparency,
464 transparency_range=transparency_range,
465 **kwargs,
466 )
468 return display
471###############################################################################
472# Anatomy image for background
475# A constant class to serve as a sentinel for the default MNI template
476class _MNI152Template(SpatialImage):
477 """Constant pointing to the MNI152 Template provided by nilearn."""
479 data = None
480 _affine = None
481 vmax = None
482 _shape = None
483 # Having a header is required by the load_niimg function
484 header = None # type: ignore[assignment]
486 def __init__(self, data=None, affine=None, header=None):
487 # Comply with spatial image requirements while allowing empty init
488 pass
490 def load(self):
491 if self.data is None:
492 anat_img = load_mni152_template(resolution=2)
493 anat_img = reorder_img(anat_img, copy_header=True)
494 data = get_data(anat_img)
495 data = data.astype(np.float64)
496 anat_mask = binary_fill_holes(data > np.finfo(float).eps)
497 data = np.ma.masked_array(data, np.logical_not(anat_mask))
498 self._affine = anat_img.affine
499 self.data = data
500 self.vmax = data.max()
501 self._shape = anat_img.shape
503 @property
504 def _data_cache(self):
505 self.load()
506 return self.data
508 @property
509 def _dataobj(self):
510 self.load()
511 return self.data
513 def get_data(self):
514 self.load()
515 return self.data
517 @property
518 def affine(self):
519 self.load()
520 return self._affine
522 def get_affine(self):
523 self.load()
524 return self._affine
526 @property
527 def shape(self):
528 self.load()
529 return self._shape
531 def get_shape(self):
532 self.load()
533 return self._shape
535 def __str__(self):
536 return "<MNI152Template>"
538 def __repr__(self):
539 return "<MNI152Template>"
542# The constant that we use as a default in functions
543MNI152TEMPLATE = _MNI152Template()
546def load_anat(anat_img=MNI152TEMPLATE, dim="auto", black_bg="auto"):
547 """Load anatomy, for optional diming."""
548 vmin = None
549 vmax = None
550 if anat_img is False or anat_img is None:
551 if black_bg == "auto":
552 # No anatomy given: no need to turn black_bg on
553 black_bg = False
554 return anat_img, black_bg, vmin, vmax
556 if anat_img is MNI152TEMPLATE:
557 anat_img.load()
558 # We special-case the 'canonical anat', as we don't need
559 # to do a few transforms to it.
560 vmin = 0
561 vmax = anat_img.vmax
562 if black_bg == "auto":
563 black_bg = False
564 else:
565 anat_img = check_niimg_3d(anat_img)
566 # Clean anat_img for non-finite values to avoid computing unnecessary
567 # border data values.
568 data = safe_get_data(anat_img, ensure_finite=True)
569 anat_img = new_img_like(anat_img, data, affine=anat_img.affine)
570 if dim or black_bg == "auto":
571 # We need to inspect the values of the image
572 vmin = np.nanmin(data)
573 vmax = np.nanmax(data)
574 if black_bg == "auto":
575 # Guess if the background is rather black or light based on
576 # the values of voxels near the border
577 background = np.median(get_border_data(data, 2))
578 black_bg = not (background > 0.5 * (vmin + vmax))
579 if dim:
580 if dim != "auto" and not isinstance(dim, numbers.Number):
581 raise ValueError(
582 "The input given for 'dim' needs to be a float. "
583 f"You provided dim={dim} in {type(dim)}."
584 )
585 vmean = 0.5 * (vmin + vmax)
586 ptp = 0.5 * (vmax - vmin)
587 if black_bg:
588 if not isinstance(dim, numbers.Number):
589 dim = 0.8
590 vmax = vmean + (1 + dim) * ptp
591 else:
592 if not isinstance(dim, numbers.Number):
593 dim = 0.6
594 vmin = 0.5 * (2 - dim) * vmean - (1 + dim) * ptp
595 return anat_img, black_bg, vmin, vmax
598###############################################################################
599# Usage-specific functions
602@fill_doc
603def plot_anat(
604 anat_img=MNI152TEMPLATE,
605 cut_coords=None,
606 output_file=None,
607 display_mode="ortho",
608 figure=None,
609 axes=None,
610 title=None,
611 annotate=True,
612 threshold=None,
613 draw_cross=True,
614 black_bg="auto",
615 dim="auto",
616 cmap="gray",
617 colorbar=True,
618 cbar_tick_format="%.2g",
619 radiological=False,
620 vmin=None,
621 vmax=None,
622 **kwargs,
623):
624 """Plot cuts of an anatomical image.
626 By default 3 cuts: Frontal, Axial, and Lateral.
628 Parameters
629 ----------
630 anat_img : Niimg-like object, default=MNI152TEMPLATE
631 See :ref:`extracting_data`.
632 The anatomical image to be used as a background. If None is
633 given, nilearn tries to find a T1 template.
635 %(cut_coords)s
637 %(output_file)s
639 %(display_mode)s
641 %(figure)s
643 %(axes)s
645 %(title)s
647 %(annotate)s
649 %(threshold)s
651 %(draw_cross)s
653 %(black_bg)s
654 Default='auto'.
656 %(dim)s
657 Default='auto'.
659 %(cmap)s
660 Default=`gray`.
662 %(colorbar)s
663 Default=True
665 cbar_tick_format : :obj:`str`, default="%%.2g" (scientific notation)
666 Controls how to format the tick labels of the colorbar.
667 Ex: use "%%i" to display as integers.
669 %(radiological)s
671 %(vmin)s
673 %(vmax)s
675 kwargs : extra keyword arguments, optional
676 Extra keyword arguments
677 ultimately passed to `matplotlib.pyplot.imshow` via
678 :meth:`~nilearn.plotting.displays.BaseSlicer.add_overlay`.
680 Returns
681 -------
682 display : :class:`~nilearn.plotting.displays.OrthoSlicer` or None
683 An instance of the OrthoSlicer class. If ``output_file`` is defined,
684 None is returned.
686 Raises
687 ------
688 ValueError
689 if the specified threshold is a negative number
691 Notes
692 -----
693 Arrays should be passed in numpy convention: (x, y, z) ordered.
695 For visualization, non-finite values found in passed 'anat_img'
696 are set to zero.
698 """
699 check_params(locals())
700 check_threshold_not_negative(threshold)
702 anat_img, black_bg, anat_vmin, anat_vmax = load_anat(
703 anat_img, dim=dim, black_bg=black_bg
704 )
706 if vmin is None:
707 vmin = anat_vmin
708 if vmax is None:
709 vmax = anat_vmax
711 display = plot_img(
712 anat_img,
713 cut_coords=cut_coords,
714 output_file=output_file,
715 display_mode=display_mode,
716 figure=figure,
717 axes=axes,
718 title=title,
719 threshold=threshold,
720 annotate=annotate,
721 draw_cross=draw_cross,
722 black_bg=black_bg,
723 colorbar=colorbar,
724 cbar_tick_format=cbar_tick_format,
725 vmin=vmin,
726 vmax=vmax,
727 cmap=cmap,
728 radiological=radiological,
729 **kwargs,
730 )
731 return display
734@fill_doc
735def plot_epi(
736 epi_img=None,
737 cut_coords=None,
738 output_file=None,
739 display_mode="ortho",
740 figure=None,
741 axes=None,
742 title=None,
743 annotate=True,
744 draw_cross=True,
745 black_bg=True,
746 colorbar=True,
747 cbar_tick_format="%.2g",
748 cmap="gray",
749 vmin=None,
750 vmax=None,
751 radiological=False,
752 **kwargs,
753):
754 """Plot cuts of an :term:`EPI` image.
756 By default 3 cuts: Frontal, Axial, and Lateral.
758 Parameters
759 ----------
760 epi_img : a Niimg-like object or None, default=None
761 The :term:`EPI` (T2*) image.
763 %(cut_coords)s
765 %(output_file)s
767 %(display_mode)s
769 %(figure)s
771 %(axes)s
773 %(title)s
775 %(annotate)s
777 %(draw_cross)s
779 %(black_bg)s
780 Default=True.
782 %(colorbar)s
783 Default=True
785 cbar_tick_format : :obj:`str`, default="%%.2g" (scientific notation)
786 Controls how to format the tick labels of the colorbar.
787 Ex: use "%%i" to display as integers.
789 %(cmap)s
790 Default=`gray`.
792 %(vmin)s
794 %(vmax)s
796 %(radiological)s
798 kwargs : extra keyword arguments, optional
799 Extra keyword arguments
800 ultimately passed to `matplotlib.pyplot.imshow` via
801 :meth:`~nilearn.plotting.displays.BaseSlicer.add_overlay`.
803 Returns
804 -------
805 display : :class:`~nilearn.plotting.displays.OrthoSlicer` or None
806 An instance of the OrthoSlicer class. If ``output_file`` is defined,
807 None is returned.
809 Notes
810 -----
811 Arrays should be passed in numpy convention: (x, y, z) ordered.
812 """
813 check_params(locals())
814 display = plot_img(
815 epi_img,
816 cut_coords=cut_coords,
817 output_file=output_file,
818 display_mode=display_mode,
819 figure=figure,
820 axes=axes,
821 title=title,
822 threshold=None,
823 annotate=annotate,
824 draw_cross=draw_cross,
825 black_bg=black_bg,
826 colorbar=colorbar,
827 cbar_tick_format=cbar_tick_format,
828 cmap=cmap,
829 vmin=vmin,
830 vmax=vmax,
831 radiological=radiological,
832 **kwargs,
833 )
834 return display
837def _plot_roi_contours(display, roi_img, cmap, alpha, linewidths):
838 """Help for plotting regions of interest ROIs in contours.
840 Parameters
841 ----------
842 display : :class:`~nilearn.plotting.displays.OrthoSlicer`, object
843 An object with background image on which contours are shown.
845 roi_img : Niimg-like object
846 See :ref:`extracting_data`.
847 The ROI/mask image, it could be binary mask or an atlas or ROIs
848 with integer values.
850 %(cmap)s
852 alpha : :obj:`float` between 0 and 1
853 Alpha sets the transparency of the color inside the filled
854 contours.
856 linewidths : :obj:`float`
857 This option can be used to set the boundary thickness of the
858 contours.
860 Returns
861 -------
862 display : :class:`~nilearn.plotting.displays.OrthoSlicer`, object
863 Contours displayed on the background image.
865 """
866 roi_img = check_niimg_3d(roi_img)
867 roi_data = get_data(roi_img)
868 labels = np.unique(roi_data)
869 cmap = plt.get_cmap(cmap)
870 color_list = cmap(np.linspace(0, 1, len(labels)))
871 for idx, label in enumerate(labels):
872 if label == 0:
873 continue
874 data = roi_data == label
875 data = data.astype(np.int32)
876 img = new_img_like(roi_img, data, affine=roi_img.affine)
877 display.add_contours(
878 img,
879 levels=[0.5],
880 colors=[color_list[idx - 1]],
881 transparency=alpha,
882 linewidths=linewidths,
883 linestyles="solid",
884 )
885 return display
888@fill_doc
889def plot_roi(
890 roi_img,
891 bg_img=MNI152TEMPLATE,
892 cut_coords=None,
893 output_file=None,
894 display_mode="ortho",
895 figure=None,
896 axes=None,
897 title=None,
898 annotate=True,
899 draw_cross=True,
900 black_bg="auto",
901 threshold=0.5,
902 alpha=0.7,
903 cmap="gist_ncar",
904 dim="auto",
905 colorbar=True,
906 cbar_tick_format="%i",
907 vmin=None,
908 vmax=None,
909 resampling_interpolation="nearest",
910 view_type="continuous",
911 linewidths=2.5,
912 radiological=False,
913 **kwargs,
914):
915 """Plot cuts of an ROI/mask image.
917 By default 3 cuts: Frontal, Axial, and Lateral.
919 Parameters
920 ----------
921 roi_img : Niimg-like object
922 See :ref:`extracting_data`.
923 The ROI/mask image, it could be binary mask or an atlas or ROIs
924 with integer values.
926 %(bg_img)s
927 If nothing is specified, the MNI152 template will be used.
928 To turn off background image, just pass "bg_img=None".
929 Default=MNI152TEMPLATE.
931 %(cut_coords)s
933 %(output_file)s
935 %(display_mode)s
937 %(figure)s
939 %(axes)s
941 %(title)s
943 %(annotate)s
945 %(draw_cross)s
947 %(black_bg)s
948 Default='auto'.
950 %(threshold)s
951 Default=0.5.
953 alpha : :obj:`float` between 0 and 1, default=0.7
954 Alpha sets the transparency of the color inside the filled
955 contours.
957 %(cmap_lut)s
958 Default=`gist_ncar`.
960 %(dim)s
961 Default='auto'.
963 %(colorbar)s
964 Default=True
966 cbar_tick_format : :obj:`str`, default="%%i"
967 Controls how to format the tick labels of the colorbar.
968 Ex: use "%%.2g" to use scientific notation.
970 %(vmin)s
972 %(vmax)s
974 %(resampling_interpolation)s
975 Default='nearest'.
977 view_type : {'continuous', 'contours'}, default='continuous'
978 By default view_type == 'continuous',
979 rois are shown as continuous colors.
980 If view_type == 'contours', maps are shown as contours.
981 For this type, label
982 denoted as 0 is considered as background and not shown.
984 %(linewidths)s
985 Default=2.5.
987 %(radiological)s
989 kwargs : extra keyword arguments, optional
990 Extra keyword arguments
991 ultimately passed to `matplotlib.pyplot.imshow` via
992 :meth:`~nilearn.plotting.displays.BaseSlicer.add_overlay`.
994 Returns
995 -------
996 display : :class:`~nilearn.plotting.displays.OrthoSlicer` or None
997 An instance of the OrthoSlicer class. If ``output_file`` is defined,
998 None is returned.
1000 Raises
1001 ------
1002 ValueError
1003 if the specified threshold is a negative number
1005 Notes
1006 -----
1007 A small threshold is applied by default to eliminate numerical
1008 background noise.
1010 For visualization, non-finite values found in passed 'roi_img' or
1011 'bg_img' are set to zero.
1013 See Also
1014 --------
1015 nilearn.plotting.plot_prob_atlas : To simply plot probabilistic atlases
1016 (4D images)
1017 """
1018 check_params(locals())
1019 check_threshold_not_negative(threshold)
1021 valid_view_types = ["continuous", "contours"]
1022 if view_type not in valid_view_types:
1023 raise ValueError(
1024 f"Unknown view type: {view_type}. "
1025 f"Valid view types are {valid_view_types}."
1026 )
1027 elif view_type == "contours":
1028 img = roi_img
1029 roi_img = None
1031 bg_img, black_bg, bg_vmin, bg_vmax = load_anat(
1032 bg_img, dim=dim, black_bg=black_bg
1033 )
1035 if isinstance(cmap, pd.DataFrame):
1036 cmap = create_colormap_from_lut(cmap)
1038 transparency = alpha
1040 display = _plot_img_with_bg(
1041 img=roi_img,
1042 bg_img=bg_img,
1043 cut_coords=cut_coords,
1044 output_file=output_file,
1045 display_mode=display_mode,
1046 figure=figure,
1047 axes=axes,
1048 title=title,
1049 annotate=annotate,
1050 draw_cross=draw_cross,
1051 black_bg=black_bg,
1052 threshold=threshold,
1053 bg_vmin=bg_vmin,
1054 bg_vmax=bg_vmax,
1055 resampling_interpolation=resampling_interpolation,
1056 colorbar=colorbar,
1057 cbar_tick_format=cbar_tick_format,
1058 transparency=transparency,
1059 cmap=cmap,
1060 vmin=vmin,
1061 vmax=vmax,
1062 radiological=radiological,
1063 **kwargs,
1064 )
1066 if view_type == "contours":
1067 display = _plot_roi_contours(
1068 display, img, cmap=cmap, alpha=alpha, linewidths=linewidths
1069 )
1071 return display
1074@fill_doc
1075def plot_prob_atlas(
1076 maps_img,
1077 bg_img=MNI152TEMPLATE,
1078 view_type="auto",
1079 threshold="auto",
1080 linewidths=2.5,
1081 cut_coords=None,
1082 output_file=None,
1083 display_mode="ortho",
1084 figure=None,
1085 axes=None,
1086 title=None,
1087 annotate=True,
1088 draw_cross=True,
1089 black_bg="auto",
1090 dim="auto",
1091 colorbar=True,
1092 cmap="gist_rainbow",
1093 vmin=None,
1094 vmax=None,
1095 alpha=0.7,
1096 radiological=False,
1097 **kwargs,
1098):
1099 """Plot a :term:`Probabilistic atlas` onto the anatomical image \
1100 by default :term:`MNI` template.
1102 Parameters
1103 ----------
1104 maps_img : Niimg-like object or the filename
1105 4D image of the :term:`Probabilistic atlas` maps.
1107 %(bg_img)s
1108 If nothing is specified, the MNI152 template will be used.
1109 To turn off background image, just pass "bg_img=False".
1110 Default=MNI152TEMPLATE.
1112 .. versionadded:: 0.4.0
1114 view_type : {'auto', 'contours', 'filled_contours', 'continuous'}, \
1115 default='auto'
1116 If view_type == 'auto', it means maps will be displayed
1117 automatically using any one of the three view types. The automatic
1118 selection of view type depends on the total number of maps.
1119 If view_type == 'contours', maps are overlaid as contours
1120 If view_type == 'filled_contours', maps are overlaid as contours
1121 along with color fillings inside the contours.
1122 If view_type == 'continuous', maps are overlaid as continuous
1123 colors irrespective of the number maps.
1125 threshold : a :obj:`int` or :obj:`float` or :obj:`str` or \
1126 :obj:`list` of :obj:`int` or :obj:`float` or \
1127 :obj:`str`, default='auto'
1128 This parameter is optional and is used to threshold the maps image
1129 using the given value or automatically selected value. The values
1130 in the image (in absolute value) above the threshold level will be
1131 visualized.
1132 The default strategy, computes a threshold level that seeks to
1133 minimize (yet not eliminate completely) the overlap between several
1134 maps for a better visualization.
1135 The threshold can also be expressed as a percentile over the values
1136 of the whole atlas. In that case, the value must be specified as
1137 string finishing with a percent sign, e.g., "25.3%%".
1138 If a single string is provided, the same percentile will be applied
1139 over the whole atlas. Otherwise, if a list of percentiles is
1140 provided, each 3D map is thresholded with certain percentile
1141 sequentially. Length of percentiles given should match the number
1142 of 3D map in time (4th) dimension.
1143 If a number or a list of numbers, the numbers should be
1144 non-negative. The given value will be used directly to threshold the
1145 maps without any percentile calculation.
1146 If None, a very small threshold is applied to remove numerical
1147 noise from the maps background.
1149 %(linewidths)s
1150 Default=2.5.
1152 %(cut_coords)s
1154 %(output_file)s
1156 %(display_mode)s
1158 %(figure)s
1160 %(axes)s
1162 %(title)s
1164 %(annotate)s
1166 %(draw_cross)s
1168 %(black_bg)s
1169 Default='auto'.
1171 %(dim)s
1172 Default='auto'.
1174 %(cmap)s
1175 Default=`gist_rainbow`.
1177 %(colorbar)s
1178 Default=True.
1180 %(vmin)s
1182 %(vmax)s
1184 alpha : :obj:`float` between 0 and 1, default=0.7
1185 Alpha sets the transparency of the color inside the filled contours.
1186 %(radiological)s
1188 kwargs : extra keyword arguments, optional
1189 Extra keyword arguments
1190 ultimately passed to `matplotlib.pyplot.imshow` via
1191 :meth:`~nilearn.plotting.displays.BaseSlicer.add_overlay`.
1193 Returns
1194 -------
1195 display : :class:`~nilearn.plotting.displays.OrthoSlicer` or None
1196 An instance of the OrthoSlicer class. If ``output_file`` is defined,
1197 None is returned.
1199 Raises
1200 ------
1201 ValueError
1202 if the specified threshold is a negative number
1204 See Also
1205 --------
1206 nilearn.plotting.plot_roi : To simply plot max-prob atlases (3D images)
1207 """
1208 check_params(locals())
1209 check_threshold_not_negative(threshold)
1211 display = plot_anat(
1212 bg_img,
1213 cut_coords=cut_coords,
1214 display_mode=display_mode,
1215 figure=figure,
1216 axes=axes,
1217 title=title,
1218 annotate=annotate,
1219 draw_cross=draw_cross,
1220 black_bg=black_bg,
1221 dim=dim,
1222 radiological=radiological,
1223 vmin=vmin,
1224 vmax=vmax,
1225 **kwargs,
1226 )
1228 maps_img = check_niimg_4d(maps_img)
1229 n_maps = maps_img.shape[3]
1231 valid_view_types = ["auto", "contours", "filled_contours", "continuous"]
1232 if view_type not in valid_view_types:
1233 raise ValueError(
1234 f"Unknown view type: {view_type}. "
1235 f"Valid view types are {valid_view_types}."
1236 )
1238 cmap = plt.get_cmap(cmap)
1239 color_list = cmap(np.linspace(0, 1, n_maps))
1241 if view_type == "auto":
1242 if n_maps > 20:
1243 view_type = "contours"
1244 elif n_maps > 10:
1245 view_type = "filled_contours"
1246 else:
1247 view_type = "continuous"
1249 if threshold is None:
1250 threshold = 1e-6
1251 elif threshold == "auto":
1252 # it will use default percentage,
1253 # strategy is to avoid maximum overlaps as possible
1254 if view_type == "contours":
1255 correction_factor = 1
1256 elif view_type == "filled_contours":
1257 correction_factor = 0.8
1258 else:
1259 correction_factor = 0.5
1260 threshold = f"{100 * (1 - 0.2 * correction_factor / n_maps):f}%"
1262 if isinstance(threshold, collections.abc.Iterable) and not isinstance(
1263 threshold, str
1264 ):
1265 threshold = list(threshold)
1266 if len(threshold) != n_maps:
1267 raise TypeError(
1268 "The list of values to threshold "
1269 "should be equal to number of maps"
1270 )
1271 else:
1272 threshold = [threshold] * n_maps
1274 filled = view_type.startswith("filled")
1275 transparency = alpha
1276 for map_img, color, thr in zip(iter_img(maps_img), color_list, threshold):
1277 data = get_data(map_img)
1278 # To threshold or choose the level of the contours
1279 thr = check_threshold(
1280 thr, data, percentile_func=fast_abs_percentile, name="threshold"
1281 )
1282 # Get rid of background values in all cases
1283 thr = max(thr, 1e-6)
1285 if view_type == "continuous":
1286 display.add_overlay(
1287 map_img,
1288 threshold=thr,
1289 cmap=cm.alpha_cmap(color),
1290 transparency=transparency,
1291 )
1292 else:
1293 display.add_contours(
1294 map_img,
1295 levels=[thr],
1296 linewidths=linewidths,
1297 colors=[color],
1298 filled=filled,
1299 transparency=transparency,
1300 linestyles="solid",
1301 )
1302 if colorbar:
1303 display._colorbar = True
1304 # Create a colormap from color list to feed display
1305 cmap = LinearSegmentedColormap.from_list(
1306 "segmented colors", color_list, n_maps + 1
1307 )
1308 display._show_colorbar(cmap, mpl.colors.Normalize(1, n_maps + 1))
1309 tick_locator = mpl.ticker.MaxNLocator(nbins=10)
1310 display.locator = tick_locator
1311 display._cbar.update_ticks()
1312 tick_location = np.round(
1313 np.linspace(1, n_maps, min(n_maps, 10))
1314 ).astype("int")
1315 display._cbar.set_ticks(tick_location + 0.5)
1316 display._cbar.set_ticklabels(tick_location)
1317 (
1318 left,
1319 bottom,
1320 width,
1321 height,
1322 ) = display._colorbar_ax.get_position().bounds
1323 display._colorbar_ax.set_position([left, bottom, width, height * 0.95])
1324 display._colorbar_ax.annotate(
1325 "Map #",
1326 xy=(1, 1.03),
1327 ha="right",
1328 va="bottom",
1329 xycoords="axes fraction",
1330 )
1332 return save_figure_if_needed(display, output_file)
1335@fill_doc
1336def plot_stat_map(
1337 stat_map_img,
1338 bg_img=MNI152TEMPLATE,
1339 cut_coords=None,
1340 output_file=None,
1341 display_mode="ortho",
1342 colorbar=True,
1343 cbar_tick_format="%.2g",
1344 figure=None,
1345 axes=None,
1346 title=None,
1347 threshold=1e-6,
1348 annotate=True,
1349 draw_cross=True,
1350 black_bg="auto",
1351 cmap=DEFAULT_DIVERGING_CMAP,
1352 symmetric_cbar="auto",
1353 dim="auto",
1354 vmin=None,
1355 vmax=None,
1356 radiological=False,
1357 resampling_interpolation="continuous",
1358 transparency=None,
1359 transparency_range=None,
1360 **kwargs,
1361):
1362 """Plot cuts of an ROI/mask image.
1364 By default 3 cuts: Frontal, Axial, and Lateral.
1366 Parameters
1367 ----------
1368 stat_map_img : Niimg-like object
1369 See :ref:`extracting_data`.
1370 The statistical map image
1372 %(bg_img)s
1373 If nothing is specified, the MNI152 template will be used.
1374 To turn off background image, just pass "bg_img=None".
1375 Default=MNI152TEMPLATE.
1377 %(cut_coords)s
1379 %(output_file)s
1381 %(display_mode)s
1383 %(colorbar)s
1384 Default=True.
1386 cbar_tick_format : :obj:`str`, default="%%.2g" (scientific notation)
1387 Controls how to format the tick labels of the colorbar.
1388 Ex: use "%%i" to display as integers.
1390 %(figure)s
1392 %(axes)s
1394 %(title)s
1396 %(threshold)s
1397 Default=1e-6.
1399 %(annotate)s
1401 %(draw_cross)s
1403 %(black_bg)s
1404 Default='auto'.
1406 %(cmap)s
1408 Default=default="RdBu_r".
1410 %(symmetric_cbar)s
1412 %(dim)s
1413 Default='auto'.
1415 %(vmin)s
1417 %(vmax)s
1419 %(resampling_interpolation)s
1420 Default='continuous'.
1422 %(radiological)s
1424 %(transparency)s
1426 %(transparency_range)s
1428 kwargs : extra keyword arguments, optional
1429 Extra keyword arguments
1430 ultimately passed to `matplotlib.pyplot.imshow` via
1431 :meth:`~nilearn.plotting.displays.BaseSlicer.add_overlay`.
1433 Returns
1434 -------
1435 display : :class:`~nilearn.plotting.displays.OrthoSlicer` or None
1436 An instance of the OrthoSlicer class. If ``output_file`` is defined,
1437 None is returned.
1439 Raises
1440 ------
1441 ValueError
1442 if the specified threshold is a negative number
1444 Notes
1445 -----
1446 Arrays should be passed in numpy convention: (x, y, z) ordered.
1448 For visualization, non-finite values found in passed 'stat_map_img' or
1449 'bg_img' are set to zero.
1451 See Also
1452 --------
1453 nilearn.plotting.plot_anat : To simply plot anatomical images
1454 nilearn.plotting.plot_epi : To simply plot raw EPI images
1455 nilearn.plotting.plot_glass_brain : To plot maps in a glass brain
1456 """
1457 check_params(locals())
1458 check_threshold_not_negative(threshold)
1460 # dim the background
1461 bg_img, black_bg, bg_vmin, bg_vmax = load_anat(
1462 bg_img, dim=dim, black_bg=black_bg
1463 )
1465 stat_map_img = check_niimg_3d(stat_map_img, dtype="auto")
1467 cbar_vmin, cbar_vmax, vmin, vmax = get_colorbar_and_data_ranges(
1468 safe_get_data(stat_map_img, ensure_finite=True),
1469 vmin=vmin,
1470 vmax=vmax,
1471 symmetric_cbar=symmetric_cbar,
1472 )
1474 display = _plot_img_with_bg(
1475 img=stat_map_img,
1476 bg_img=bg_img,
1477 cut_coords=cut_coords,
1478 output_file=output_file,
1479 display_mode=display_mode,
1480 figure=figure,
1481 axes=axes,
1482 title=title,
1483 annotate=annotate,
1484 draw_cross=draw_cross,
1485 black_bg=black_bg,
1486 threshold=threshold,
1487 bg_vmin=bg_vmin,
1488 bg_vmax=bg_vmax,
1489 cmap=cmap,
1490 vmin=vmin,
1491 vmax=vmax,
1492 colorbar=colorbar,
1493 cbar_tick_format=cbar_tick_format,
1494 cbar_vmin=cbar_vmin,
1495 cbar_vmax=cbar_vmax,
1496 resampling_interpolation=resampling_interpolation,
1497 radiological=radiological,
1498 transparency=transparency,
1499 transparency_range=transparency_range,
1500 **kwargs,
1501 )
1503 return display
1506@fill_doc
1507def plot_glass_brain(
1508 stat_map_img,
1509 output_file=None,
1510 display_mode="ortho",
1511 colorbar=True,
1512 cbar_tick_format="%.2g",
1513 figure=None,
1514 axes=None,
1515 title=None,
1516 threshold="auto",
1517 annotate=True,
1518 black_bg=False,
1519 cmap=None,
1520 alpha=0.7,
1521 vmin=None,
1522 vmax=None,
1523 plot_abs=True,
1524 symmetric_cbar="auto",
1525 resampling_interpolation="continuous",
1526 radiological=False,
1527 transparency=None,
1528 **kwargs,
1529):
1530 """Plot 2d projections of an ROI/mask image (by default 3 projections:
1531 Frontal, Axial, and Lateral). The brain glass schematics
1532 are added on top of the image.
1534 The plotted image should be in :term:`MNI` space for this function to work
1535 properly.
1537 Only glass brain can be plotted by switching stat_map_img to None.
1539 Parameters
1540 ----------
1541 stat_map_img : Niimg-like object
1542 See :ref:`extracting_data`.
1543 The statistical map image.
1544 It needs to be in :term:`MNI` space
1545 in order to align with the brain schematics.
1547 %(output_file)s
1549 display_mode : :obj:`str`, default='ortho'
1550 Choose the direction of the cuts: 'x' - sagittal, 'y' - coronal,
1551 'z' - axial, 'l' - sagittal left hemisphere only,
1552 'r' - sagittal right hemisphere only, 'ortho' - three cuts are
1553 performed in orthogonal directions. Possible values are: 'ortho',
1554 'x', 'y', 'z', 'xz', 'yx', 'yz', 'l', 'r', 'lr', 'lzr', 'lyr',
1555 'lzry', 'lyrz'.
1557 %(colorbar)s
1558 Default=True.
1560 cbar_tick_format : :obj:`str`, default="%%.2g" (scientific notation)
1561 Controls how to format the tick labels of the colorbar.
1562 Ex: use "%%i" to display as integers.
1564 %(figure)s
1566 %(axes)s
1568 %(title)s
1570 %(threshold)s
1571 Default='auto'.
1573 %(annotate)s
1575 %(black_bg)s
1576 Default=False.
1578 %(cmap)s
1579 Default=None.
1581 alpha : :obj:`float` between 0 and 1, default=0.7
1582 Alpha transparency for the brain schematics.
1584 %(vmin)s
1586 %(vmax)s
1588 plot_abs : :obj:`bool`, default=True
1589 If set to True maximum intensity projection of the
1590 absolute value will be used (rendering positive and negative
1591 values in the same manner). If set to false the sign of the
1592 maximum intensity will be represented with different colors.
1593 See
1594 :ref:`sphx_glr_auto_examples_01_plotting_plot_demo_glass_brain_extensive.py`
1595 for examples.
1597 %(symmetric_cbar)s
1599 %(resampling_interpolation)s
1600 Default='continuous'.
1602 %(radiological)s
1604 %(transparency)s
1606 %(transparency_range)s
1608 kwargs : extra keyword arguments, optional
1609 Extra keyword arguments
1610 ultimately passed to `matplotlib.pyplot.imshow` via
1611 :meth:`~nilearn.plotting.displays.BaseSlicer.add_overlay`.
1613 Returns
1614 -------
1615 display : :class:`~nilearn.plotting.displays.OrthoProjector` or None
1616 An instance of the OrthoProjector class. If ``output_file`` is defined,
1617 None is returned.
1619 Raises
1620 ------
1621 ValueError
1622 if the specified threshold is a negative number
1624 Notes
1625 -----
1626 Arrays should be passed in numpy convention: (x, y, z) ordered.
1627 """
1628 check_params(locals())
1629 check_threshold_not_negative(threshold)
1631 if cmap is None:
1632 cmap = cm.cold_white_hot
1633 if black_bg:
1634 cmap = cm.cold_hot
1635 if not plot_abs:
1636 cmap = plt.cm.RdBu_r
1637 # use only positive half of colormap if plotting absolute values
1638 if plot_abs:
1639 cmap = LinearSegmentedColormap.from_list(
1640 "cmap_pos",
1641 cmap(np.linspace(0.5, 1, 256)),
1642 )
1644 if stat_map_img:
1645 stat_map_img = check_niimg_3d(stat_map_img, dtype="auto")
1646 if plot_abs:
1647 if vmin is not None and vmin < 0:
1648 warnings.warn(
1649 "vmin is negative but plot_abs is True",
1650 category=UserWarning,
1651 stacklevel=find_stack_level(),
1652 )
1653 force_min_stat_map_value = 0
1654 else:
1655 force_min_stat_map_value = None
1657 cbar_vmin, cbar_vmax, vmin, vmax = get_colorbar_and_data_ranges(
1658 safe_get_data(stat_map_img, ensure_finite=True),
1659 vmin=vmin,
1660 vmax=vmax,
1661 symmetric_cbar=symmetric_cbar,
1662 force_min_stat_map_value=force_min_stat_map_value,
1663 )
1664 else:
1665 cbar_vmin, cbar_vmax = None, None
1667 def display_factory(display_mode):
1668 return functools.partial(
1669 get_projector(display_mode), alpha=alpha, plot_abs=plot_abs
1670 )
1672 display = _plot_img_with_bg(
1673 img=stat_map_img,
1674 output_file=output_file,
1675 display_mode=display_mode,
1676 figure=figure,
1677 axes=axes,
1678 title=title,
1679 annotate=annotate,
1680 black_bg=black_bg,
1681 threshold=threshold,
1682 cmap=cmap,
1683 colorbar=colorbar,
1684 cbar_tick_format=cbar_tick_format,
1685 display_factory=display_factory,
1686 vmin=vmin,
1687 vmax=vmax,
1688 cbar_vmin=cbar_vmin,
1689 cbar_vmax=cbar_vmax,
1690 resampling_interpolation=resampling_interpolation,
1691 radiological=radiological,
1692 transparency=transparency,
1693 **kwargs,
1694 )
1696 if stat_map_img is None and "l" in display.axes:
1697 display.axes["l"].ax.invert_xaxis()
1699 return display
1702@fill_doc
1703def plot_connectome(
1704 adjacency_matrix,
1705 node_coords,
1706 node_color="auto",
1707 node_size=50,
1708 edge_cmap=DEFAULT_DIVERGING_CMAP,
1709 edge_vmin=None,
1710 edge_vmax=None,
1711 edge_threshold=None,
1712 output_file=None,
1713 display_mode="ortho",
1714 figure=None,
1715 axes=None,
1716 title=None,
1717 annotate=True,
1718 black_bg=False,
1719 alpha=0.7,
1720 edge_kwargs=None,
1721 node_kwargs=None,
1722 colorbar=True,
1723 radiological=False,
1724):
1725 """Plot connectome on top of the brain glass schematics.
1727 The plotted image should be in :term:`MNI` space for this function to work
1728 properly.
1730 In the case of 'l' and 'r' directions (for hemispheric projections),
1731 markers in the coordinate x == 0 are included in both hemispheres.
1733 Parameters
1734 ----------
1735 adjacency_matrix : numpy array of shape (n, n)
1736 Represents the link strengths of the graph. The matrix can be
1737 symmetric which will result in an undirected graph, or not
1738 symmetric which will result in a directed graph.
1740 node_coords : numpy array_like of shape (n, 3)
1741 3d coordinates of the graph nodes in world space.
1743 node_color : color or sequence of colors or 'auto', default='auto'
1744 Color(s) of the nodes. If string is given, all nodes
1745 are plotted with same color given in string.
1747 node_size : scalar or array_like, default=50
1748 Size(s) of the nodes in points^2.
1750 edge_cmap : colormap, default="RdBu_r"
1751 Colormap used for representing the strength of the edges.
1753 edge_vmin, edge_vmax : :obj:`float` or None, Default=None
1754 If not None, either or both of these values will be used to
1755 as the minimum and maximum values to color edges. If None are
1756 supplied the maximum absolute value within the given threshold
1757 will be used as minimum (multiplied by -1) and maximum
1758 coloring levels.
1760 edge_threshold : :obj:`str`, number or None, Default=None
1761 If it is a number only the edges with a value greater than
1762 edge_threshold will be shown.
1763 If it is a string it must finish with a percent sign,
1764 e.g. "25.3%%", and only the edges with a abs(value) above
1765 the given percentile will be shown.
1766 %(output_file)s
1767 display_mode : :obj:`str`, default='ortho'
1768 Choose the direction of the cuts: 'x' - sagittal, 'y' - coronal,
1769 'z' - axial, 'l' - sagittal left hemisphere only,
1770 'r' - sagittal right hemisphere only, 'ortho' - three cuts are
1771 performed in orthogonal directions. Possible values are: 'ortho',
1772 'x', 'y', 'z', 'xz', 'yx', 'yz', 'l', 'r', 'lr', 'lzr', 'lyr',
1773 'lzry', 'lyrz'.
1774 %(figure)s
1775 %(axes)s
1776 %(title)s
1777 %(annotate)s
1778 %(black_bg)s
1779 Default=False.
1780 alpha : :obj:`float` between 0 and 1, default=0.7
1781 Alpha transparency for the brain schematics.
1783 edge_kwargs : :obj:`dict` or None, default=None
1784 Will be passed as kwargs for each edge matlotlib Line2D.
1786 node_kwargs : :obj:`dict` or None, default=None
1787 Will be passed as kwargs to the plt.scatter call that plots all
1788 the nodes in one go.
1790 %(colorbar)s
1791 Default=True.
1793 %(radiological)s
1795 Returns
1796 -------
1797 display : :class:`~nilearn.plotting.displays.OrthoProjector` or None
1798 An instance of the OrthoProjector class. If ``output_file`` is defined,
1799 None is returned.
1801 See Also
1802 --------
1803 nilearn.plotting.find_parcellation_cut_coords : Extraction of node
1804 coords on brain parcellations.
1805 nilearn.plotting.find_probabilistic_atlas_cut_coords : Extraction of
1806 node coords on brain probabilistic atlases.
1808 """
1809 display = plot_glass_brain(
1810 None,
1811 display_mode=display_mode,
1812 figure=figure,
1813 axes=axes,
1814 title=title,
1815 annotate=annotate,
1816 black_bg=black_bg,
1817 alpha=alpha,
1818 radiological=radiological,
1819 )
1821 display.add_graph(
1822 adjacency_matrix,
1823 node_coords,
1824 node_color=node_color,
1825 node_size=node_size,
1826 edge_cmap=edge_cmap,
1827 edge_vmin=edge_vmin,
1828 edge_vmax=edge_vmax,
1829 edge_threshold=edge_threshold,
1830 edge_kwargs=edge_kwargs,
1831 node_kwargs=node_kwargs,
1832 colorbar=colorbar,
1833 )
1835 return save_figure_if_needed(display, output_file)
1838@fill_doc
1839def plot_markers(
1840 node_values,
1841 node_coords,
1842 node_size="auto",
1843 node_cmap="gray",
1844 node_vmin=None,
1845 node_vmax=None,
1846 node_threshold=None,
1847 alpha=0.7,
1848 output_file=None,
1849 display_mode="ortho",
1850 figure=None,
1851 axes=None,
1852 title=None,
1853 annotate=True,
1854 black_bg=False,
1855 node_kwargs=None,
1856 colorbar=True,
1857 radiological=False,
1858):
1859 """Plot network nodes (markers) on top of the brain glass schematics.
1861 Nodes are color coded according to provided nodal measure. Nodal measure
1862 usually represents some notion of node importance.
1864 Parameters
1865 ----------
1866 node_values : array_like of length n
1867 Vector containing nodal importance measure. Each node will be colored
1868 according to corresponding node value.
1870 node_coords : numpy array_like of shape (n, 3)
1871 3d coordinates of the graph nodes in world space.
1873 node_size : 'auto' or scalar or array-like, default='auto'
1874 Size(s) of the nodes in points^2. By default the size of the node is
1875 inversely proportional to the number of nodes.
1877 node_cmap : :obj:`str` or colormap, default="gray".
1878 Colormap used to represent the node measure.
1880 node_vmin : :obj:`float` or None, default=None
1881 Lower bound of the colormap. If `None`, the min of the node_values is
1882 used.
1884 node_vmax : :obj:`float` or None, default=None
1885 Upper bound of the colormap. If `None`, the min of the node_values is
1886 used.
1888 node_threshold : :obj:`float` or None, default=None
1889 If provided only the nodes with a value greater than node_threshold
1890 will be shown.
1892 alpha : :obj:`float` between 0 and 1, default=0.7
1893 Alpha transparency for markers.
1894 %(output_file)s
1896 display_mode : :obj:`str`, default='ortho'
1897 Choose the direction of the cuts: 'x' - sagittal, 'y' - coronal,
1898 'z' - axial, 'l' - sagittal left hemisphere only,
1899 'r' - sagittal right hemisphere only, 'ortho' - three cuts are
1900 performed in orthogonal directions. Possible values are: 'ortho',
1901 'x', 'y', 'z', 'xz', 'yx', 'yz', 'l', 'r', 'lr', 'lzr', 'lyr',
1902 'lzry', 'lyrz'.
1903 %(figure)s
1904 %(axes)s
1905 %(title)s
1906 %(annotate)s
1907 %(black_bg)s
1908 Default=False.
1909 node_kwargs : :obj:`dict` or None, default=None
1910 will be passed as kwargs to the plt.scatter call that plots all
1911 the nodes in one go
1912 %(colorbar)s
1913 Default=True.
1914 %(radiological)s
1916 Returns
1917 -------
1918 display : :class:`~nilearn.plotting.displays.OrthoProjector` or None
1919 An instance of the OrthoProjector class. If ``output_file`` is defined,
1920 None is returned.
1921 """
1922 node_values = np.array(node_values).flatten()
1923 node_coords = np.array(node_coords)
1925 # Validate node_values
1926 if node_values.shape != (node_coords.shape[0],):
1927 msg = (
1928 "Dimension mismatch: 'node_values' should be vector of length "
1929 f"{len(node_coords)}, "
1930 f"but current shape is {node_values.shape} "
1931 f"instead of {(node_coords.shape[0],)}"
1932 )
1933 raise ValueError(msg)
1935 display = plot_glass_brain(
1936 None,
1937 display_mode=display_mode,
1938 figure=figure,
1939 axes=axes,
1940 title=title,
1941 annotate=annotate,
1942 black_bg=black_bg,
1943 radiological=radiological,
1944 )
1946 if isinstance(node_size, str) and node_size == "auto":
1947 node_size = min(1e4 / len(node_coords), 100)
1949 # Filter out nodes with node values below threshold
1950 if node_threshold is not None:
1951 if node_threshold > np.max(node_values):
1952 msg = (
1953 f"Provided 'node_threshold' value: {node_threshold} "
1954 "should not exceed "
1955 f"highest node value: {np.max(node_values)}"
1956 )
1957 raise ValueError(msg)
1959 retained_nodes = node_values > node_threshold
1960 node_values = node_values[retained_nodes]
1961 node_coords = node_coords[retained_nodes]
1962 if isinstance(node_size, collections.abc.Iterable):
1963 node_size = [
1964 size
1965 for ok_retain, size in zip(retained_nodes, node_size)
1966 if ok_retain
1967 ]
1969 # Calculate node colors based on value
1970 node_vmin = np.min(node_values) if node_vmin is None else node_vmin
1971 node_vmax = np.max(node_values) if node_vmax is None else node_vmax
1972 if node_vmin == node_vmax:
1973 node_vmin = 0.9 * node_vmin
1974 node_vmax = 1.1 * node_vmax
1975 norm = mpl.colors.Normalize(vmin=node_vmin, vmax=node_vmax)
1976 node_cmap = (
1977 plt.get_cmap(node_cmap) if isinstance(node_cmap, str) else node_cmap
1978 )
1979 node_color = [node_cmap(norm(node_value)) for node_value in node_values]
1981 # Prepare additional parameters for plt.scatter
1982 node_kwargs = {} if node_kwargs is None else node_kwargs
1983 node_kwargs.update([("alpha", alpha)])
1985 display.add_markers(
1986 marker_coords=node_coords,
1987 marker_color=node_color,
1988 marker_size=node_size,
1989 **node_kwargs,
1990 )
1992 if colorbar:
1993 display._colorbar = True
1994 display._show_colorbar(cmap=node_cmap, norm=norm)
1996 return save_figure_if_needed(display, output_file)
1999@fill_doc
2000def plot_carpet(
2001 img,
2002 mask_img=None,
2003 mask_labels=None,
2004 t_r=None,
2005 detrend=True,
2006 output_file=None,
2007 figure=None,
2008 axes=None,
2009 vmin=None,
2010 vmax=None,
2011 title=None,
2012 cmap="gray",
2013 cmap_labels="gist_ncar",
2014 standardize=True,
2015):
2016 """Plot an image representation of :term:`voxel` intensities across time.
2018 This figure is also known as a "grayplot" or "Power plot".
2020 Parameters
2021 ----------
2022 %(img)s
2023 4D image.
2025 mask_img : Niimg-like object or None, default=None
2026 Limit plotted voxels to those inside the provided mask.
2027 If a 3D atlas is provided, voxels will be grouped by atlas
2028 value and a colorbar will be added to the left side of the figure
2029 with atlas labels.
2030 If not specified, a new mask will be derived from data.
2031 See :ref:`extracting_data`.
2033 mask_labels : :obj:`dict` or None, default=None
2034 If ``mask_img`` corresponds to an atlas, then this dictionary maps
2035 values from the ``mask_img`` to labels. Dictionary keys are labels
2036 and values are values within the atlas.
2037 %(t_r)s
2039 .. note::
2040 If ``t_r`` is not provided, it will be inferred from ``img``'s
2041 header (``img.header.get_zooms()[-1]``).
2043 .. versionadded:: 0.9.1
2044 Prior to this, ``t_r`` would be inferred from ``img`` without
2045 user input.
2047 detrend : :obj:`bool`, default=True
2048 Detrend and z-score the data prior to plotting.
2049 %(output_file)s
2050 %(figure)s
2051 %(axes)s
2052 %(vmin)s
2053 %(vmax)s
2054 %(title)s
2055 %(cmap)s
2056 Default=`gray`.
2058 cmap_labels : :class:`matplotlib.colors.Colormap`, or :obj:`str`, \
2059 default=`gist_ncar`
2060 If ``mask_img`` corresponds to an atlas, then cmap_labels
2061 can be used to define the colormap for coloring the labels placed
2062 on the side of the carpet plot.
2064 %(standardize)s
2066 .. note::
2068 Added to control passing value to `standardize` of ``signal.clean``
2069 to call new behavior since passing "zscore" or True (default) is
2070 deprecated. This parameter will be deprecated in version 0.13 and
2071 removed in version 0.15.
2073 Returns
2074 -------
2075 figure : :class:`matplotlib.figure.Figure`
2076 Figure object with carpet plot.
2078 Notes
2079 -----
2080 This figure was originally developed in :footcite:t:`Power2017`.
2082 In cases of long acquisitions (>800 volumes), the data will be downsampled
2083 to have fewer than 800 volumes before being plotted.
2085 References
2086 ----------
2087 .. footbibliography::
2089 """
2090 check_params(locals())
2091 img = check_niimg_4d(img, dtype="auto")
2093 # Define TR and number of frames
2094 t_r = t_r or float(img.header.get_zooms()[-1])
2095 n_tsteps = img.shape[-1]
2097 if mask_img is None:
2098 mask_img = compute_epi_mask(img)
2099 else:
2100 mask_img = check_niimg_3d(mask_img, dtype="auto")
2102 is_atlas = len(np.unique(mask_img.get_fdata())) > 2
2103 if is_atlas:
2104 background_label = 0
2106 atlas_img_res = resample_to_img(
2107 mask_img,
2108 img,
2109 interpolation="nearest",
2110 copy_header=True,
2111 force_resample=False, # TODO change to True in 0.13.0
2112 )
2113 atlas_bin = math_img(
2114 f"img != {background_label}",
2115 img=atlas_img_res,
2116 )
2117 masker = NiftiMasker(atlas_bin, target_affine=img.affine)
2119 data = masker.fit_transform(img)
2120 atlas_values = masker.transform(atlas_img_res)
2121 atlas_values = np.squeeze(atlas_values)
2123 if mask_labels:
2124 label_dtype = type(next(iter(mask_labels.values())))
2125 if label_dtype != atlas_values.dtype:
2126 logger.log(f"Coercing atlas_values to {label_dtype}")
2127 atlas_values = atlas_values.astype(label_dtype)
2129 # Sort data and atlas by atlas values
2130 order = np.argsort(atlas_values)
2131 order = np.squeeze(order)
2132 atlas_values = atlas_values[order]
2133 data = data[:, order]
2134 else:
2135 data = apply_mask(img, mask_img)
2137 # Detrend and standardize data
2138 if detrend:
2139 data = clean(data, t_r=t_r, detrend=True, standardize=standardize)
2141 if figure is None:
2142 if not axes:
2143 figsize = (10, 5)
2144 figure = plt.figure(figsize=figsize)
2145 else:
2146 figure = axes.figure
2148 if axes is None:
2149 axes = figure.add_subplot(1, 1, 1)
2150 else:
2151 assert axes.figure is figure, "The axes passed are not in the figure"
2153 # Determine vmin and vmax based on the full data
2154 std = np.mean(data.std(axis=0))
2155 default_vmin = data.mean() - (2 * std)
2156 default_vmax = data.mean() + (2 * std)
2158 # Avoid segmentation faults for long acquisitions by decimating the data
2159 LONG_CUTOFF = 800
2160 # Get smallest power of 2 greater than the number of volumes divided by the
2161 # cutoff, to determine how much to decimate (downsample) the data.
2162 n_decimations = int(np.ceil(np.log2(np.ceil(n_tsteps / LONG_CUTOFF))))
2163 data = data[:: 2**n_decimations, :]
2165 if is_atlas:
2166 # Define nested GridSpec
2167 legend = False
2168 wratios = [2, 100, 20]
2169 gs = mgs.GridSpecFromSubplotSpec(
2170 1,
2171 2 + int(legend),
2172 subplot_spec=axes.get_subplotspec(),
2173 width_ratios=wratios[: 2 + int(legend)],
2174 wspace=0.0,
2175 )
2177 ax0 = plt.subplot(gs[0])
2178 ax0.set_xticks([])
2179 ax0.imshow(
2180 atlas_values[:, np.newaxis],
2181 interpolation="none",
2182 aspect="auto",
2183 cmap=cmap_labels,
2184 )
2185 if mask_labels:
2186 # Add labels to middle of each associated band
2187 mask_labels_inv = {v: k for k, v in mask_labels.items()}
2188 ytick_locs = [
2189 np.mean(np.where(atlas_values == i)[0])
2190 for i in np.unique(atlas_values)
2191 ]
2192 ax0.set_yticks(ytick_locs)
2193 ax0.set_yticklabels(
2194 [mask_labels_inv[i] for i in np.unique(atlas_values)]
2195 )
2196 else:
2197 ax0.set_yticks([])
2199 # Carpet plot
2200 if compare_version(mpl.__version__, ">=", "3.8.0rc1"):
2201 axes.remove() # remove axes for newer versions of mpl
2202 axes = plt.subplot(gs[1]) # overwrites axes with older versions of mpl
2203 axes.imshow(
2204 data.T,
2205 interpolation="nearest",
2206 aspect="auto",
2207 cmap=cmap,
2208 vmin=vmin or default_vmin,
2209 vmax=vmax or default_vmax,
2210 )
2211 ax0.tick_params(axis="both", which="both", length=0)
2212 else:
2213 axes.imshow(
2214 data.T,
2215 interpolation="nearest",
2216 aspect="auto",
2217 cmap=cmap,
2218 vmin=vmin or default_vmin,
2219 vmax=vmax or default_vmax,
2220 )
2222 axes.grid(False)
2223 axes.set_yticks([])
2224 axes.set_yticklabels([])
2226 # Set 10 frame markers in X axis
2227 interval = max(
2228 (int(data.shape[0] + 1) // 10, int(data.shape[0] + 1) // 5, 1)
2229 )
2230 xticks = list(range(data.shape[0])[::interval])
2231 axes.set_xticks(xticks)
2232 axes.set_xlabel("time (s)")
2234 if title:
2235 axes.set_title(title)
2237 labels = t_r * (np.array(xticks))
2238 labels *= 2**n_decimations
2239 axes.set_xticklabels([f"{t:.02f}" for t in labels.tolist()])
2241 # Remove and redefine spines
2242 for side in ["top", "right"]:
2243 # Toggle the spine objects
2244 axes.spines[side].set_color("none")
2245 axes.spines[side].set_visible(False)
2247 axes.xaxis.set_ticks_position("bottom")
2248 axes.spines["bottom"].set_position(("outward", 10))
2250 if not mask_labels:
2251 axes.yaxis.set_ticks_position("left")
2252 buffer = 20 if is_atlas else 10
2253 axes.spines["left"].set_position(("outward", buffer))
2254 axes.set_ylabel("voxels")
2256 return save_figure_if_needed(figure, output_file)
2259def plot_img_comparison(
2260 ref_imgs,
2261 src_imgs,
2262 masker=None,
2263 plot_hist=True,
2264 log=True,
2265 ref_label="image set 1",
2266 src_label="image set 2",
2267 output_dir=None,
2268 axes=None,
2269):
2270 """Redirect to plot_img_comparison."""
2271 from nilearn.plotting.img_comparison import plot_img_comparison
2273 warnings.warn(
2274 (
2275 "The 'plot_img_comparison' has been moved to "
2276 "'nilearn.plotting.img_comparison'.\n"
2277 "It will be removed from 'nilearn.plotting.img_plotting' "
2278 "in version >= 0.13.1.\n"
2279 "Import 'plot_img_comparison' "
2280 "from 'nilearn.plotting.img_comparison' "
2281 "to silence this warning."
2282 ),
2283 DeprecationWarning,
2284 stacklevel=find_stack_level(),
2285 )
2287 plot_img_comparison(
2288 ref_imgs,
2289 src_imgs,
2290 masker,
2291 plot_hist=plot_hist,
2292 log=log,
2293 ref_label=ref_label,
2294 src_label=src_label,
2295 output_dir=output_dir,
2296 axes=axes,
2297 )