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

1"""Functions to do automatic visualization of Niimg-like objects. 

2 

3See http://nilearn.github.io/stable/manipulating_images/input_output.html 

4 

5Only matplotlib is required. 

6""" 

7 

8import collections.abc 

9import functools 

10import numbers 

11import warnings 

12 

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 

21 

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 

57 

58 

59def show(): 

60 """Show all the figures generated by nilearn and/or matplotlib. 

61 

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. 

65 

66 """ 

67 if mpl.get_backend().lower() != "agg": # avoid warnings 

68 plt.show() 

69 

70 

71############################################################################### 

72# Core, usage-agnostic functions 

73 

74 

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. 

107 

108 Parameters 

109 ---------- 

110 %(img)s 

111 Image to plot. 

112 

113 %(bg_img)s 

114 If nothing is specified, no background image is plotted. 

115 Default=None. 

116 

117 %(cut_coords)s 

118 

119 %(output_file)s 

120 

121 %(display_mode)s 

122 

123 %(colorbar)s 

124 Default=False. 

125 

126 %(figure)s 

127 

128 %(axes)s 

129 

130 %(title)s 

131 

132 %(threshold)s 

133 

134 %(annotate)s 

135 

136 %(draw_cross)s 

137 

138 %(black_bg)s 

139 Default=False. 

140 

141 %(vmin)s 

142 

143 %(vmax)s 

144 

145 bg_vmin : :obj:`float`, optional 

146 vmin for `bg_img`. 

147 

148 bg_vmax : :obj:`float`, optional 

149 vmax for `bg_img`. 

150 

151 interpolation : :obj:`str`, default='nearest' 

152 Passed to the add_overlay calls. 

153 

154 display_factory : function, default=get_slicer 

155 Takes a display_mode argument and return a display class. 

156 

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. 

160 

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. 

165 

166 %(radiological)s 

167 

168 %(transparency)s 

169 

170 %(transparency_range)s 

171 

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`. 

177 

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. 

185 

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) 

193 

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()) 

207 

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 ) 

218 

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 

223 

224 if np.isnan(np.sum(data)): 

225 data = np.nan_to_num(data) 

226 

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 

232 

233 img = new_img_like(img, as_ndarray(data), affine) 

234 

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 ) 

255 

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) 

286 

287 return save_figure_if_needed(display, output_file) 

288 

289 

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 

316 

317 

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. 

345 

346 By default Frontal, Axial, and Lateral. 

347 

348 Parameters 

349 ---------- 

350 %(img)s 

351 

352 %(cut_coords)s 

353 

354 %(output_file)s 

355 

356 %(display_mode)s 

357 

358 %(figure)s 

359 

360 %(axes)s 

361 

362 %(title)s 

363 

364 %(threshold)s 

365 

366 %(annotate)s 

367 

368 %(draw_cross)s 

369 

370 %(black_bg)s 

371 Default=False. 

372 

373 %(colorbar)s 

374 Default=True. 

375 

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. 

379 

380 %(resampling_interpolation)s 

381 Default='continuous'. 

382 

383 %(bg_img)s 

384 If nothing is specified, no background image is plotted. 

385 Default=None. 

386 

387 %(vmin)s 

388 

389 %(vmax)s 

390 

391 %(radiological)s 

392 

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. 

397 

398 %(cmap)s 

399 default="gray" 

400 

401 %(transparency)s 

402 

403 %(transparency_range)s 

404 

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`. 

409 

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. 

415 

416 Raises 

417 ------ 

418 ValueError 

419 if the specified threshold is a negative number 

420 

421 .. note:: 

422 

423 This is a low-level function. For most use cases, other plotting 

424 functions might be more appropriate and easier to use. 

425 

426 .. seealso:: 

427 

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) 

441 

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 ) 

467 

468 return display 

469 

470 

471############################################################################### 

472# Anatomy image for background 

473 

474 

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.""" 

478 

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] 

485 

486 def __init__(self, data=None, affine=None, header=None): 

487 # Comply with spatial image requirements while allowing empty init 

488 pass 

489 

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 

502 

503 @property 

504 def _data_cache(self): 

505 self.load() 

506 return self.data 

507 

508 @property 

509 def _dataobj(self): 

510 self.load() 

511 return self.data 

512 

513 def get_data(self): 

514 self.load() 

515 return self.data 

516 

517 @property 

518 def affine(self): 

519 self.load() 

520 return self._affine 

521 

522 def get_affine(self): 

523 self.load() 

524 return self._affine 

525 

526 @property 

527 def shape(self): 

528 self.load() 

529 return self._shape 

530 

531 def get_shape(self): 

532 self.load() 

533 return self._shape 

534 

535 def __str__(self): 

536 return "<MNI152Template>" 

537 

538 def __repr__(self): 

539 return "<MNI152Template>" 

540 

541 

542# The constant that we use as a default in functions 

543MNI152TEMPLATE = _MNI152Template() 

544 

545 

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 

555 

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 

596 

597 

598############################################################################### 

599# Usage-specific functions 

600 

601 

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. 

625 

626 By default 3 cuts: Frontal, Axial, and Lateral. 

627 

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. 

634 

635 %(cut_coords)s 

636 

637 %(output_file)s 

638 

639 %(display_mode)s 

640 

641 %(figure)s 

642 

643 %(axes)s 

644 

645 %(title)s 

646 

647 %(annotate)s 

648 

649 %(threshold)s 

650 

651 %(draw_cross)s 

652 

653 %(black_bg)s 

654 Default='auto'. 

655 

656 %(dim)s 

657 Default='auto'. 

658 

659 %(cmap)s 

660 Default=`gray`. 

661 

662 %(colorbar)s 

663 Default=True 

664 

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. 

668 

669 %(radiological)s 

670 

671 %(vmin)s 

672 

673 %(vmax)s 

674 

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`. 

679 

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. 

685 

686 Raises 

687 ------ 

688 ValueError 

689 if the specified threshold is a negative number 

690 

691 Notes 

692 ----- 

693 Arrays should be passed in numpy convention: (x, y, z) ordered. 

694 

695 For visualization, non-finite values found in passed 'anat_img' 

696 are set to zero. 

697 

698 """ 

699 check_params(locals()) 

700 check_threshold_not_negative(threshold) 

701 

702 anat_img, black_bg, anat_vmin, anat_vmax = load_anat( 

703 anat_img, dim=dim, black_bg=black_bg 

704 ) 

705 

706 if vmin is None: 

707 vmin = anat_vmin 

708 if vmax is None: 

709 vmax = anat_vmax 

710 

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 

732 

733 

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. 

755 

756 By default 3 cuts: Frontal, Axial, and Lateral. 

757 

758 Parameters 

759 ---------- 

760 epi_img : a Niimg-like object or None, default=None 

761 The :term:`EPI` (T2*) image. 

762 

763 %(cut_coords)s 

764 

765 %(output_file)s 

766 

767 %(display_mode)s 

768 

769 %(figure)s 

770 

771 %(axes)s 

772 

773 %(title)s 

774 

775 %(annotate)s 

776 

777 %(draw_cross)s 

778 

779 %(black_bg)s 

780 Default=True. 

781 

782 %(colorbar)s 

783 Default=True 

784 

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. 

788 

789 %(cmap)s 

790 Default=`gray`. 

791 

792 %(vmin)s 

793 

794 %(vmax)s 

795 

796 %(radiological)s 

797 

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`. 

802 

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. 

808 

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 

835 

836 

837def _plot_roi_contours(display, roi_img, cmap, alpha, linewidths): 

838 """Help for plotting regions of interest ROIs in contours. 

839 

840 Parameters 

841 ---------- 

842 display : :class:`~nilearn.plotting.displays.OrthoSlicer`, object 

843 An object with background image on which contours are shown. 

844 

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. 

849 

850 %(cmap)s 

851 

852 alpha : :obj:`float` between 0 and 1 

853 Alpha sets the transparency of the color inside the filled 

854 contours. 

855 

856 linewidths : :obj:`float` 

857 This option can be used to set the boundary thickness of the 

858 contours. 

859 

860 Returns 

861 ------- 

862 display : :class:`~nilearn.plotting.displays.OrthoSlicer`, object 

863 Contours displayed on the background image. 

864 

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 

886 

887 

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. 

916 

917 By default 3 cuts: Frontal, Axial, and Lateral. 

918 

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. 

925 

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. 

930 

931 %(cut_coords)s 

932 

933 %(output_file)s 

934 

935 %(display_mode)s 

936 

937 %(figure)s 

938 

939 %(axes)s 

940 

941 %(title)s 

942 

943 %(annotate)s 

944 

945 %(draw_cross)s 

946 

947 %(black_bg)s 

948 Default='auto'. 

949 

950 %(threshold)s 

951 Default=0.5. 

952 

953 alpha : :obj:`float` between 0 and 1, default=0.7 

954 Alpha sets the transparency of the color inside the filled 

955 contours. 

956 

957 %(cmap_lut)s 

958 Default=`gist_ncar`. 

959 

960 %(dim)s 

961 Default='auto'. 

962 

963 %(colorbar)s 

964 Default=True 

965 

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. 

969 

970 %(vmin)s 

971 

972 %(vmax)s 

973 

974 %(resampling_interpolation)s 

975 Default='nearest'. 

976 

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. 

983 

984 %(linewidths)s 

985 Default=2.5. 

986 

987 %(radiological)s 

988 

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`. 

993 

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. 

999 

1000 Raises 

1001 ------ 

1002 ValueError 

1003 if the specified threshold is a negative number 

1004 

1005 Notes 

1006 ----- 

1007 A small threshold is applied by default to eliminate numerical 

1008 background noise. 

1009 

1010 For visualization, non-finite values found in passed 'roi_img' or 

1011 'bg_img' are set to zero. 

1012 

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) 

1020 

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 

1030 

1031 bg_img, black_bg, bg_vmin, bg_vmax = load_anat( 

1032 bg_img, dim=dim, black_bg=black_bg 

1033 ) 

1034 

1035 if isinstance(cmap, pd.DataFrame): 

1036 cmap = create_colormap_from_lut(cmap) 

1037 

1038 transparency = alpha 

1039 

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 ) 

1065 

1066 if view_type == "contours": 

1067 display = _plot_roi_contours( 

1068 display, img, cmap=cmap, alpha=alpha, linewidths=linewidths 

1069 ) 

1070 

1071 return display 

1072 

1073 

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. 

1101 

1102 Parameters 

1103 ---------- 

1104 maps_img : Niimg-like object or the filename 

1105 4D image of the :term:`Probabilistic atlas` maps. 

1106 

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. 

1111 

1112 .. versionadded:: 0.4.0 

1113 

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. 

1124 

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. 

1148 

1149 %(linewidths)s 

1150 Default=2.5. 

1151 

1152 %(cut_coords)s 

1153 

1154 %(output_file)s 

1155 

1156 %(display_mode)s 

1157 

1158 %(figure)s 

1159 

1160 %(axes)s 

1161 

1162 %(title)s 

1163 

1164 %(annotate)s 

1165 

1166 %(draw_cross)s 

1167 

1168 %(black_bg)s 

1169 Default='auto'. 

1170 

1171 %(dim)s 

1172 Default='auto'. 

1173 

1174 %(cmap)s 

1175 Default=`gist_rainbow`. 

1176 

1177 %(colorbar)s 

1178 Default=True. 

1179 

1180 %(vmin)s 

1181 

1182 %(vmax)s 

1183 

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 

1187 

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`. 

1192 

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. 

1198 

1199 Raises 

1200 ------ 

1201 ValueError 

1202 if the specified threshold is a negative number 

1203 

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) 

1210 

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 ) 

1227 

1228 maps_img = check_niimg_4d(maps_img) 

1229 n_maps = maps_img.shape[3] 

1230 

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 ) 

1237 

1238 cmap = plt.get_cmap(cmap) 

1239 color_list = cmap(np.linspace(0, 1, n_maps)) 

1240 

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" 

1248 

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}%" 

1261 

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 

1273 

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) 

1284 

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 ) 

1331 

1332 return save_figure_if_needed(display, output_file) 

1333 

1334 

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. 

1363 

1364 By default 3 cuts: Frontal, Axial, and Lateral. 

1365 

1366 Parameters 

1367 ---------- 

1368 stat_map_img : Niimg-like object 

1369 See :ref:`extracting_data`. 

1370 The statistical map image 

1371 

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. 

1376 

1377 %(cut_coords)s 

1378 

1379 %(output_file)s 

1380 

1381 %(display_mode)s 

1382 

1383 %(colorbar)s 

1384 Default=True. 

1385 

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. 

1389 

1390 %(figure)s 

1391 

1392 %(axes)s 

1393 

1394 %(title)s 

1395 

1396 %(threshold)s 

1397 Default=1e-6. 

1398 

1399 %(annotate)s 

1400 

1401 %(draw_cross)s 

1402 

1403 %(black_bg)s 

1404 Default='auto'. 

1405 

1406 %(cmap)s 

1407 

1408 Default=default="RdBu_r". 

1409 

1410 %(symmetric_cbar)s 

1411 

1412 %(dim)s 

1413 Default='auto'. 

1414 

1415 %(vmin)s 

1416 

1417 %(vmax)s 

1418 

1419 %(resampling_interpolation)s 

1420 Default='continuous'. 

1421 

1422 %(radiological)s 

1423 

1424 %(transparency)s 

1425 

1426 %(transparency_range)s 

1427 

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`. 

1432 

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. 

1438 

1439 Raises 

1440 ------ 

1441 ValueError 

1442 if the specified threshold is a negative number 

1443 

1444 Notes 

1445 ----- 

1446 Arrays should be passed in numpy convention: (x, y, z) ordered. 

1447 

1448 For visualization, non-finite values found in passed 'stat_map_img' or 

1449 'bg_img' are set to zero. 

1450 

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) 

1459 

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 ) 

1464 

1465 stat_map_img = check_niimg_3d(stat_map_img, dtype="auto") 

1466 

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 ) 

1473 

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 ) 

1502 

1503 return display 

1504 

1505 

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. 

1533 

1534 The plotted image should be in :term:`MNI` space for this function to work 

1535 properly. 

1536 

1537 Only glass brain can be plotted by switching stat_map_img to None. 

1538 

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. 

1546 

1547 %(output_file)s 

1548 

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'. 

1556 

1557 %(colorbar)s 

1558 Default=True. 

1559 

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. 

1563 

1564 %(figure)s 

1565 

1566 %(axes)s 

1567 

1568 %(title)s 

1569 

1570 %(threshold)s 

1571 Default='auto'. 

1572 

1573 %(annotate)s 

1574 

1575 %(black_bg)s 

1576 Default=False. 

1577 

1578 %(cmap)s 

1579 Default=None. 

1580 

1581 alpha : :obj:`float` between 0 and 1, default=0.7 

1582 Alpha transparency for the brain schematics. 

1583 

1584 %(vmin)s 

1585 

1586 %(vmax)s 

1587 

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. 

1596 

1597 %(symmetric_cbar)s 

1598 

1599 %(resampling_interpolation)s 

1600 Default='continuous'. 

1601 

1602 %(radiological)s 

1603 

1604 %(transparency)s 

1605 

1606 %(transparency_range)s 

1607 

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`. 

1612 

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. 

1618 

1619 Raises 

1620 ------ 

1621 ValueError 

1622 if the specified threshold is a negative number 

1623 

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) 

1630 

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 ) 

1643 

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 

1656 

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 

1666 

1667 def display_factory(display_mode): 

1668 return functools.partial( 

1669 get_projector(display_mode), alpha=alpha, plot_abs=plot_abs 

1670 ) 

1671 

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 ) 

1695 

1696 if stat_map_img is None and "l" in display.axes: 

1697 display.axes["l"].ax.invert_xaxis() 

1698 

1699 return display 

1700 

1701 

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. 

1726 

1727 The plotted image should be in :term:`MNI` space for this function to work 

1728 properly. 

1729 

1730 In the case of 'l' and 'r' directions (for hemispheric projections), 

1731 markers in the coordinate x == 0 are included in both hemispheres. 

1732 

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. 

1739 

1740 node_coords : numpy array_like of shape (n, 3) 

1741 3d coordinates of the graph nodes in world space. 

1742 

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. 

1746 

1747 node_size : scalar or array_like, default=50 

1748 Size(s) of the nodes in points^2. 

1749 

1750 edge_cmap : colormap, default="RdBu_r" 

1751 Colormap used for representing the strength of the edges. 

1752 

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. 

1759 

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. 

1782 

1783 edge_kwargs : :obj:`dict` or None, default=None 

1784 Will be passed as kwargs for each edge matlotlib Line2D. 

1785 

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. 

1789 

1790 %(colorbar)s 

1791 Default=True. 

1792 

1793 %(radiological)s 

1794 

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. 

1800 

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. 

1807 

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 ) 

1820 

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 ) 

1834 

1835 return save_figure_if_needed(display, output_file) 

1836 

1837 

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. 

1860 

1861 Nodes are color coded according to provided nodal measure. Nodal measure 

1862 usually represents some notion of node importance. 

1863 

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. 

1869 

1870 node_coords : numpy array_like of shape (n, 3) 

1871 3d coordinates of the graph nodes in world space. 

1872 

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. 

1876 

1877 node_cmap : :obj:`str` or colormap, default="gray". 

1878 Colormap used to represent the node measure. 

1879 

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. 

1883 

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. 

1887 

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. 

1891 

1892 alpha : :obj:`float` between 0 and 1, default=0.7 

1893 Alpha transparency for markers. 

1894 %(output_file)s 

1895 

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 

1915 

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) 

1924 

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) 

1934 

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 ) 

1945 

1946 if isinstance(node_size, str) and node_size == "auto": 

1947 node_size = min(1e4 / len(node_coords), 100) 

1948 

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) 

1958 

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 ] 

1968 

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] 

1980 

1981 # Prepare additional parameters for plt.scatter 

1982 node_kwargs = {} if node_kwargs is None else node_kwargs 

1983 node_kwargs.update([("alpha", alpha)]) 

1984 

1985 display.add_markers( 

1986 marker_coords=node_coords, 

1987 marker_color=node_color, 

1988 marker_size=node_size, 

1989 **node_kwargs, 

1990 ) 

1991 

1992 if colorbar: 

1993 display._colorbar = True 

1994 display._show_colorbar(cmap=node_cmap, norm=norm) 

1995 

1996 return save_figure_if_needed(display, output_file) 

1997 

1998 

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. 

2017 

2018 This figure is also known as a "grayplot" or "Power plot". 

2019 

2020 Parameters 

2021 ---------- 

2022 %(img)s 

2023 4D image. 

2024 

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`. 

2032 

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 

2038 

2039 .. note:: 

2040 If ``t_r`` is not provided, it will be inferred from ``img``'s 

2041 header (``img.header.get_zooms()[-1]``). 

2042 

2043 .. versionadded:: 0.9.1 

2044 Prior to this, ``t_r`` would be inferred from ``img`` without 

2045 user input. 

2046 

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`. 

2057 

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. 

2063 

2064 %(standardize)s 

2065 

2066 .. note:: 

2067 

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. 

2072 

2073 Returns 

2074 ------- 

2075 figure : :class:`matplotlib.figure.Figure` 

2076 Figure object with carpet plot. 

2077 

2078 Notes 

2079 ----- 

2080 This figure was originally developed in :footcite:t:`Power2017`. 

2081 

2082 In cases of long acquisitions (>800 volumes), the data will be downsampled 

2083 to have fewer than 800 volumes before being plotted. 

2084 

2085 References 

2086 ---------- 

2087 .. footbibliography:: 

2088 

2089 """ 

2090 check_params(locals()) 

2091 img = check_niimg_4d(img, dtype="auto") 

2092 

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] 

2096 

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") 

2101 

2102 is_atlas = len(np.unique(mask_img.get_fdata())) > 2 

2103 if is_atlas: 

2104 background_label = 0 

2105 

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) 

2118 

2119 data = masker.fit_transform(img) 

2120 atlas_values = masker.transform(atlas_img_res) 

2121 atlas_values = np.squeeze(atlas_values) 

2122 

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) 

2128 

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) 

2136 

2137 # Detrend and standardize data 

2138 if detrend: 

2139 data = clean(data, t_r=t_r, detrend=True, standardize=standardize) 

2140 

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 

2147 

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" 

2152 

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) 

2157 

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, :] 

2164 

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 ) 

2176 

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([]) 

2198 

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 ) 

2221 

2222 axes.grid(False) 

2223 axes.set_yticks([]) 

2224 axes.set_yticklabels([]) 

2225 

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)") 

2233 

2234 if title: 

2235 axes.set_title(title) 

2236 

2237 labels = t_r * (np.array(xticks)) 

2238 labels *= 2**n_decimations 

2239 axes.set_xticklabels([f"{t:.02f}" for t in labels.tolist()]) 

2240 

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) 

2246 

2247 axes.xaxis.set_ticks_position("bottom") 

2248 axes.spines["bottom"].set_position(("outward", 10)) 

2249 

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") 

2255 

2256 return save_figure_if_needed(figure, output_file) 

2257 

2258 

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 

2272 

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 ) 

2286 

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 )