error plotting with slider (python matplotlib)

时间:2016-04-15 15:13:48

标签: python matplotlib plot

I search on internet how using a slider with 3D data and I find this algorithm which plot 3D data in 2D with a slider, so I copy-paste it and I tried to run it in order to adapt it (for solving my real problem : plotting 3D+time data and using a slider to interact with the time). This is my complete code :

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
import scipy.ndimage as ndi

data = np.zeros((10, 10, 10))
data[5, 5, 5] = 10.
data = ndi.filters.gaussian_filter(data, sigma=1)
print(data.max())

def cube_show_slider(cube, axis=0, **kwargs):
    """
    Display a 3d ndarray with a slider to move along the third dimension.
    Extra keyword arguments are passed to imshow
    """
    # check dim
    if not cube.ndim == 3:
        raise ValueError("cube should be an ndarray with ndim == 3")
    # generate figure
    fig = plt.figure()
    ax = plt.subplot(111)
    fig.subplots_adjust(left=0.25, bottom=0.25)
    # select first image
    s = [slice(0, 1) if i == axis else slice(None) for i in range(3)]
    im = cube[s].squeeze()
    # display image
    l = ax.matshow(im, **kwargs)
    cb = plt.colorbar(l)
    cb.set_clim(vmin=data.min(), vmax=data.max())
    cb.draw_all()
    # define slider
    axcolor = 'lightgoldenrodyellow'
    ax = fig.add_axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
    slideryo = Slider(ax, 'Axis %i index' % axis, 0, cube.shape[axis] - 1, valinit=0, valfmt='%i')
    slideryo.on_changed(update)
    plt.show()

def update(val):
    ind = int(slider.val)
    s = [slice(ind, ind + 1) if i == axis else slice(None) for i in    range(3)]
    im = cube[s].squeeze()
    l.set_data(im, **kwargs)
    cb.set_clim(vmin=data.min(), vmax=data.max())
    cb.formatter.set_powerlimits((0, 0))
    cb.update_ticks()
    cb.draw_all()
    fig.canvas.draw()

cube_show_slider(data)

A window with the axis and the slider are on my screen but no data is plotted. The plot is just a big blue square and when I interact with the slider I have this error :

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 1952, in motion_notify_event
      self.callbacks.process(s, event)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/cbook.py", line 563, in process
      proxy(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/cbook.py", line 430, in __call__
      return mtd(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/widgets.py", line 434, in _update
      self.set_val(val)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/widgets.py", line 448, in set_val
      func(val)
  File "<stdin>", line 2, in update
      NameError: global name 'slider' is not defined

I don't understand why it doesn't work. All the functions and files that the console cite were added by the importation. And I know that the code written by mmensing is ok, so I missed something but what? I'm sure that I did a stupid error, but I don't know where.

To check if the data I created are ok, I write this code to see the 3d plot in 3D without slider :

import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
import scipy.ndimage as ndi

mpl.rcParams['legend.fontsize'] = 10
fig = plt.figure()
ax = fig.gca(projection='3d')
data = np.zeros((10, 10, 10))
data[5, 5, 5] = 10.
data = ndi.filters.gaussian_filter(data, sigma=1)
ax.plot(data[0,:,:], data[1,:,:], data[2,:,:], label='my data')
ax.legend()    
plt.show()

But it returns this error :

Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
        File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 1541, in plot
lines = Axes.plot(self, xs, ys, *args[argsi:], **kwargs)
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/__init__.py", line 1812, in inner
    return func(ax, *args, **kwargs)
        File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axes/_axes.py", line 1424, in plot
for line in self._get_lines(*args, **kwargs):
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axes/_base.py", line 386, in _grab_next_args
    for seg in self._plot_args(remaining, kwargs):
        File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axes/_base.py", line 339, in _plot_args
raise ValueError('third arg must be a format string')
    ValueError: third arg must be a format string
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axes/_axes.py:519: UserWarning: No labelled objects found. Use label='...' kwarg on individual plots.
    warnings.warn("No labelled objects found. ")

What can I do ?

1 个答案:

答案 0 :(得分:0)

我已经更正了您的代码,您可以通过比较找到一些错误:

  • 需要在子程序中定义更新功能,以便可以在那里访问,缩进错误
  • 您的滑块在不同位置有两个不同的名称
  • 仅在定义功能后才参考更新功能。

希望现在有效。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
import scipy.ndimage as ndi

data = np.zeros((10, 10, 10))
data[5, 5, 5] = 10.
data = ndi.filters.gaussian_filter(data, sigma=1)
print(data.max())
print data.shape

def cube_show_slider(cube, axis=0, **kwargs):
    """
    Display a 3d ndarray with a slider to move along the third dimension.
    Extra keyword arguments are passed to imshow
    """
    # check dim
    if not cube.ndim == 3:
        raise ValueError("cube should be an ndarray with ndim == 3")

    # generate figure
    fig = plt.figure()
    ax = plt.subplot(111)
    fig.subplots_adjust(left=0.25, bottom=0.25)

    # select first image
    s = [slice(0, 1) if i == axis else slice(None) for i in range(3)]
    im = cube[s].squeeze()

    # display image
    l = ax.matshow(im, **kwargs)
    cb = plt.colorbar(l)
    cb.set_clim(vmin=data.min(), vmax=data.max())
    cb.draw_all()

    # define slider
    axcolor = 'lightgoldenrodyellow'
    ax = fig.add_axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
    slideryo = Slider(ax, 'Axis %i index' % axis, 0, cube.shape[axis] - 1, valinit=0, valfmt='%i')

    def update(val):
        ind = int(slideryo.val)
        s = [slice(ind, ind + 1) if i == axis else slice(None) for i in    range(3)]
        im = cube[s].squeeze()
        l.set_data(im, **kwargs)
        cb.set_clim(vmin=data.min(), vmax=data.max())
        cb.formatter.set_powerlimits((0, 0))
        cb.update_ticks()
        cb.draw_all()
        fig.canvas.draw()

    slideryo.on_changed(update)
    plt.show()


cube_show_slider(data)