Reputation: 442
I'm trying to change the values of the colour levels on a matplotlib filled contour plot using a slider. i.e contourf(x,y,z,np.linspace(a,b,n)) where the sliders would control a and b and would change the plot colour levels when a slider is moved. The following code takes column formatted data converts it to the form required by contourf and then the the sliders are implemented. This is what I've tried:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
data=np.genfromtxt('file.dat',skip_header=1)
len=np.sqrt(data[:,0].size)
x=np.reshape(data[:,0],(len,len))
y=np.reshape(data[:,1],(len,len))
z=np.reshape(data[:,3],(len,len))
l=plt.contourf(x,y,z,np.linspace(0,100,255))
axmax = plt.axes([0.25, 0.1, 0.65, 0.03]) #slider location and size
axmin = plt.axes([0.25, 0.15, 0.65, 0.03])
smax = Slider(axmax, 'Max',0, 100, 50) #slider properties
smin = Slider(axmin, 'Min', 0, 100, 0)
def update(val):
l.levels(np.linspace(smin.val,smax.val,255))#changing levels of plot
fig.canvas.draw_idle() #line that throws error
smax.on_changed(update)
smin.on_changed(update)
plt.show()
A large number of matplotlib errors are thrown when a slider is moved with the relevant one being 'TypeError:'numpy.ndarray' object is not callable' which is thrown by the line
fig.canvas.draw_idle()
Upvotes: 5
Views: 3638
Reputation: 13539
The problem is that l.levels
is a array, so you would have to change the values in this array. In my testing changing these values does not cause the plot to update. So another solution is to just clear the axis and redraw the plot.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
data=np.random.random([25,4])
data = data*100
len=np.sqrt(data[:,0].size)
x=np.reshape(data[:,0],(len,len))
y=np.reshape(data[:,1],(len,len))
z=np.reshape(data[:,3],(len,len))
l=plt.contourf(x,y,z,np.linspace(0,100,255))
contour_axis = plt.gca()
axmax = plt.axes([0.25, 0.1, 0.65, 0.03]) #slider location and size
axmin = plt.axes([0.25, 0.15, 0.65, 0.03])
smax = Slider(axmax, 'Max',0, 100, 50) #slider properties
smin = Slider(axmin, 'Min', 0, 100, 0)
def update(val):
contour_axis.clear()
contour_axis.contourf(x,y,z,np.linspace(smin.val,smax.val,255))
plt.draw()
smax.on_changed(update)
smin.on_changed(update)
plt.show()
Upvotes: 4