Source code for scisalt.matplotlib.Imshow_Slider_Array

# import matplotlib.pyplot as _plt

import os as _os
on_rtd = _os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd:
    import matplotlib.widgets as _wdg
    import matplotlib as _mpl
    import numpy as _np
    import matplotlib.pyplot as _plt

from .setup_figure import setup_figure   # noqa
from .imshow import imshow
from .imshow import scaled_figsize
from .colorbar import colorbar

import pdb as pdb


[docs]class Imshow_Slider_Array(object): """ .. versionchanged:: 1.5 Name changed, colorbar options added, *p* changed to :class:`AxesImage <scisalt.matplotlib.Imshow_Slider.AxesImage>`. Convenience class for viewing images. Plots *image* to a to an instance of :class:`matplotlib.axis.imshow(**kwargs)`, with sliders for controlling bounds, with *\*\*kwargs* passed through to :meth:`matplotlib.axes.Axes.imshow`. *usecbar* determines if a colorbar will be used. Color bars can slow down the viewer significantly. """ def __init__(self, images, usecbar=False, **kwargs): # ====================================== # Save input info # ====================================== self._images = images self._num_imgs = len(images) self._image_ind = 0 self._kwargs = kwargs self._usecbar = usecbar # ====================================== # Create figure # ====================================== # self.fig, self.gs = setup_figure(20, 10, figsize=scaled_figsize(self.image)) self.fig, self.gs = setup_figure(20, 10) self._ax_img = self.fig.add_subplot(self.gs[0:-4, :]) self.ax_min = self.fig.add_subplot(self.gs[-3, 1:-1]) self.ax_max = self.fig.add_subplot(self.gs[-2, 1:-1]) self.ax_img = self.fig.add_subplot(self.gs[-1, 1:-1]) self._reset(**kwargs) _plt.connect('key_press_event', self._keypress) def _keypress(self, event): self._event = event newval = None if event.key == 'right': newval = self.imageslider.val + 1 if newval > self.num_imgs: newval = self.num_imgs elif event.key == 'left': newval = self.imageslider.val - 1 if newval < 0: newval = 0 if newval is not None: self.imageslider.set_val(newval) # if event.key in ['A', 'a']: # self.RectangleSelector.set_active(not self.RectangleSelector.active) # elif event.key in ['D', 'd']: # try: # self._rect.remove() # _plt.draw() # self._eclick = None # self._erelease = None # self._selfunc_results = None # except: # pass def _fix_axes(self): shape_x, shape_y = self.image.shape ratio = shape_x / shape_y figsize = self._kwargs.get('figsize', _mpl.rcParams['figure.figsize']) figsize_ratio = figsize[0]/figsize[1] if ratio > figsize_ratio: x_lim = [0, shape_x] y_lim = shape_x / figsize_ratio y_lim = [(shape_y-y_lim)/2, (shape_y+y_lim)/2] else: x_lim = shape_y * figsize_ratio x_lim = [(shape_x-x_lim)/2, (shape_x+x_lim)/2] y_lim = [0, shape_y] self.ax.set_xlim(x_lim) self.ax.set_ylim(y_lim) def _reset(self, **kwargs): # ====================================== # Strip kwargs for vmin, vmax # in order to set sliders correctly # ====================================== minslide = kwargs.get('vmin', self.imgmin) maxslide = kwargs.get('vmax', self.imgmax) # ====================================== # Slider Logic # ====================================== if self.imgmin > 0: slidermin = kwargs.pop('smin', 0) else: slidermin = kwargs.pop('smin', self.imgmin) if self.imgmax < 0: slidermax = kwargs.pop('smax', 0) else: slidermax = kwargs.pop('smax', self.imgmax) # ====================================== # Imshow # ====================================== # self._AxesImage = self.ax.imshow(self.image, **kwargs) self._AxesImage = imshow(self.image, ax=self.ax, add_cbar=False, **kwargs) self._cax, self._cb = colorbar(self.ax, self._AxesImage) self._fix_axes() # ====================================== # Add minimum slider # ====================================== self.minslider = _wdg.Slider(self.ax_min, 'Min', slidermin, slidermax, minslide) # ====================================== # Add maximum slider # ====================================== self.maxslider = _wdg.Slider(self.ax_max, 'Max', slidermin, slidermax, maxslide, slidermin=self.minslider) self.minslider.slidermax = self.maxslider self.minslider.on_changed(self._update_clim) self.maxslider.on_changed(self._update_clim) # ====================================== # Add image slider # ====================================== self.imageslider = _wdg.Slider(ax=self.ax_img, label='Image', valmin=1, valmax=self.num_imgs, valinit=0, valfmt=u'%d') self.imageslider.on_changed(self._update_image) # if self.usecbar: # self.fig.colorbar(self.AxesImage, ax=self.ax, use_gridspec=True) # self.fig.tight_layout() def _update_image(self, value): ind = _np.int(_np.round(value)-1) self._image_ind = ind # ====================================== # Get old axes settings # ====================================== xlim = self.ax.get_xlim() ylim = self.ax.get_ylim() # ====================================== # Clear old axes # ====================================== self.ax.cla() self._cax.cla() # ====================================== # Plot new data # ====================================== self._AxesImage = imshow(self.image, ax=self.ax, add_cbar=False, **self._kwargs) self._cb = _plt.colorbar(self._AxesImage, cax=self._cax) # ====================================== # Fix the axes # ====================================== self._fix_axes() # ====================================== # Keep the colorbar to previous settings # ====================================== self._update_clim(0) # ====================================== # Get old axes settings # ====================================== self.ax.set_xlim(xlim) self.ax.set_ylim(ylim)
[docs] def set_cmap(self, cmap): """ Sets color map to *cmap*. """ self.AxesImage.set_cmap(cmap)
@property def num_imgs(self): return self._num_imgs @property def AxesImage(self): """ The :class:`matplotlib.image.AxesImage` from :meth:`matplotlib.axes.Axes.imshow`. """ return self._AxesImage @property def ax(self): """ The :class:`matplotlib.axes.Axes` used for :meth:`matplotlib.axes.Axes.imshow`. """ return self._ax_img # ====================================== # Get max of image # ====================================== @property def imgmax(self): """ Highest value of input image. """ if not hasattr(self, '_imgmax'): imgmax = _np.max(self.images[0]) for img in self.images: imax = _np.max(img) if imax > imgmax: imgmax = imax self._imgmax = imgmax return self._imgmax # ====================================== # Get min of image # ====================================== @property def imgmin(self): """ Lowest value of input image. """ if not hasattr(self, '_imgmin'): imgmin = _np.min(self.images[0]) for img in self.images: imin = _np.min(img) if imin > imgmin: imgmin = imin self._imgmin = imgmin return _np.min(self.image) # ====================================== # Update the clims # ====================================== def _update_clim(self, val): cmin = self.minslider.val cmax = self.maxslider.val # print('Cmin: {}, Cmax: {}'.format(cmin, cmax)) self.AxesImage.set_clim(cmin, cmax) # ====================================== # Easily get and set slider # ====================================== @property def clim_min(self): """ Slider value for minimum """ return self.minslider.val @clim_min.setter def clim_min(self, val): self.minslider.set_val(val) @property def clim_max(self): """ Slider value for maximum """ return self.maxslider.val @clim_max.setter def clim_max(self, val): self.maxslider.set_val(val) @property def images(self): """ The array of images. """ return self._images @property def image(self): """ The image loaded. """ return self._images[self._image_ind]