Repository: sunpy/sunpy

Issue:
MapCube animation broken
Keeping the astropy normalizer (the sunpy default for the map type below) leads to a TypeError when playing a mapcube peek animation.  Also, the map is not shown. If you change the plot settings to use a native matplotlib normalizer the peek animation does not error.  The code below illustrates the issue (using sunpy/master).

``` python
import sunpy.map
import matplotlib.pyplot as plt
from matplotlib.colors import PowerNorm
m = sunpy.map.Map('/Users/ireland/sunpy/data/sample_data/ssw_cutout_20121030_153001_AIA_94_.fts')
```

The following line works.  An image is shown.

``` python
m.peek()
```

The code errors but keeps playing when the play button is pressed.

``` python
mc = sunpy.map.Map([m,m,m], cube=True)
mc.peek()
plt.show()
```

This runs when the play button is pressed.

``` python
m2 = sunpy.map.Map('/Users/ireland/sunpy/data/sample_data/ssw_cutout_20121030_153001_AIA_94_.fts')
m2.plot_settings['norm'] = PowerNorm(0.5)
mc2 = sunpy.map.Map([m2,m2,m2], cube=True)
mc2.peek()
plt.show()
```

The third map generates the same error as mc.

``` python
mc3 = sunpy.map.Map([m2,m2,m], cube=True) 
mc3.peek()
plt.show()
```



Discussion:
Error looks like:

``` python
Exception in Tkinter callback
Traceback (most recent call last):
  File "c:\Anaconda\lib\lib-tk\Tkinter.py", line 1532, in __call__
    return self.func(*args)
  File "c:\Anaconda\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 416, in button_release_event
    FigureCanvasBase.button_release_event(self, x, y, num, guiEvent=event)
  File "c:\Anaconda\lib\site-packages\matplotlib\backend_bases.py", line 1910, in button_release_event
    self.callbacks.process(s, event)
  File "c:\Anaconda\lib\site-packages\matplotlib\cbook.py", line 540, in process
    proxy(*args, **kwargs)
  File "c:\Anaconda\lib\site-packages\matplotlib\cbook.py", line 415, in __call__
    return mtd(*args, **kwargs)
  File "c:\users\albert\onedrive\code\sunpy\sunpy\visualization\imageanimator.py", line 87, in _release
    func(event, *self.clicked_args[cid])
  File "c:\users\albert\onedrive\code\sunpy\sunpy\visualization\imageanimator.py", line 404, in _click_slider_button
    self._set_active_slider(slider.slider_ind)
  File "c:\users\albert\onedrive\code\sunpy\sunpy\visualization\imageanimator.py", line 288, in _set_active_slider
    self._dehighlight_slider(self.active_slider)
  File "c:\users\albert\onedrive\code\sunpy\sunpy\visualization\imageanimator.py", line 300, in _dehighlight_slider
    self.fig.canvas.draw()
  File "c:\Anaconda\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 349, in draw
    FigureCanvasAgg.draw(self)
  File "c:\Anaconda\lib\site-packages\matplotlib\backends\backend_agg.py", line 469, in draw
    self.figure.draw(self.renderer)
  File "c:\Anaconda\lib\site-packages\matplotlib\artist.py", line 59, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "c:\Anaconda\lib\site-packages\matplotlib\figure.py", line 1085, in draw
    func(*args)
  File "c:\Anaconda\lib\site-packages\matplotlib\artist.py", line 59, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "c:\Anaconda\lib\site-packages\matplotlib\axes\_base.py", line 2110, in draw
    a.draw(renderer)
  File "c:\Anaconda\lib\site-packages\matplotlib\artist.py", line 59, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "c:\Anaconda\lib\site-packages\matplotlib\image.py", line 373, in draw
    im = self.make_image(renderer.get_image_magnification())
  File "c:\Anaconda\lib\site-packages\matplotlib\image.py", line 597, in make_image
    transformed_viewLim)
  File "c:\Anaconda\lib\site-packages\matplotlib\image.py", line 212, in _get_unsampled_image
    x = self.to_rgba(self._A, bytes=False)
  File "c:\Anaconda\lib\site-packages\matplotlib\cm.py", line 262, in to_rgba
    x = self.norm(x)
  File "c:\Anaconda\lib\site-packages\astropy\visualization\mpl_normalize.py", line 71, in __call__
    np.subtract(values, self.vmin, out=values)
TypeError: unsupported operand type(s) for -: 'float' and 'NoneType'
```

`self.vmin` is `None`?  Perhaps there is some bug with Astropy's determination of the minimum value in the array?


Resolving patch:
diff --git a/sunpy/map/mapcube.py b/sunpy/map/mapcube.py
--- a/sunpy/map/mapcube.py
+++ b/sunpy/map/mapcube.py
@@ -2,6 +2,8 @@
 from __future__ import absolute_import
 #pylint: disable=W0401,W0614,W0201,W0212,W0404
 
+from copy import deepcopy
+
 import numpy as np
 import matplotlib.animation
 
@@ -203,7 +205,11 @@ def updatefig(i, im, annotate, ani_data, removes):
 
             im.set_array(ani_data[i].data)
             im.set_cmap(self.maps[i].plot_settings['cmap'])
-            im.set_norm(self.maps[i].plot_settings['norm'])
+
+            norm = deepcopy(self.maps[i].plot_settings['norm'])
+            # The following explicit call is for bugged versions of Astropy's ImageNormalize
+            norm.autoscale_None(ani_data[i].data)
+            im.set_norm(norm)
 
             if wcsaxes_compat.is_wcsaxes(axes):
                 im.axes.reset_wcs(self.maps[i].wcs)
diff --git a/sunpy/visualization/mapcubeanimator.py b/sunpy/visualization/mapcubeanimator.py
--- a/sunpy/visualization/mapcubeanimator.py
+++ b/sunpy/visualization/mapcubeanimator.py
@@ -2,6 +2,8 @@
 
 __all__ = ['MapCubeAnimator']
 
+from copy import deepcopy
+
 from sunpy.visualization import imageanimator, wcsaxes_compat
 from sunpy.visualization.wcsaxes_compat import HAVE_WCSAXES, FORCE_NO_WCSAXES
 
@@ -88,7 +90,12 @@ def updatefig(self, val, im, slider):
         i = int(val)
         im.set_array(self.data[i].data)
         im.set_cmap(self.mapcube[i].plot_settings['cmap'])
-        im.set_norm(self.mapcube[i].plot_settings['norm'])
+
+        norm = deepcopy(self.mapcube[i].plot_settings['norm'])
+        # The following explicit call is for bugged versions of Astropy's ImageNormalize
+        norm.autoscale_None(self.data[i].data)
+        im.set_norm(norm)
+
         if wcsaxes_compat.is_wcsaxes(im.axes):
             im.axes.reset_wcs(self.mapcube[i].wcs)
             wcsaxes_compat.default_wcs_grid(im.axes)


Test patch: