I have a list of 2D arrays that I plot them using a slider from matplotlib.
I added some control buttons to my plot, so I want to click a play button, and the plot changes with some time interval.
Here's the function that is called by the button:
def play(mouse_event):
for x in range(len(listOfMoments)):
image.set_data(listOfMoments[x])
time.sleep(0.5)
print(x)
The print(x) shows that x is increasing normally, however, it plots only the last array of the list, after the increment finishes.
My question is: How can I make it plot the array one by one, as it expected to be?
I should mention also that I tried the while loop and got the same results.
You need to tell the backend to update the figure after changing the data each time through the loop:
fig.canvas.draw()
Here's the documentation reference.
If you don't have a reference to the Figure object, you can probably retrieve it with fig = plt.gcf().
Related
I am using sympy.plotting.plot to plot my function but, it shows me a different graph then when I plot the same function in my graphic calculator.
My code is:
def S(t):
return (10*sympy.E**(t/12)*((sympy.sin((sympy.pi*t)/24))**2))
sympy.plotting.plot(S(t), xlim=[0,24])
Also, when I just do this,
sympy.plotting.plot(10*sympy.E**(t/12)*((sympy.sin((sympy.pi*t)/24))**2), xlim=[0,24])
it shows a different graph. In my calculator the function has a maximum at approximately t=14 while in python, the graph stops at t=10.
sympy plot function takes a second argument to specify the range to draw on, it's a tuple of (symbol,min,max), while xlim is used to limit the screen after the plot is drawn, it doesn't affect what's being drawn, ie: you can still move the plot to override xlim.
import sympy
t = sympy.sympify('t')
sympy.plotting.plot(10*sympy.E**(t/12)*((sympy.sin((sympy.pi*t)/24))**2),(t,0,24))
I am trying to use matplotlib's animation feature to animate multiple objects. By default, the animation feature erases old instances of the object each time it calls your animation function and you change the position of the line or patch or whatever. (Of course, this is the whole point of animation). But I have 2 different objects to be animated: a line that sweeps a polar plot in azimuth, and scatter markers. I don't want the markers to disappear. I want them to persist throughout the animation once they've been drawn.
I've tried a couple different things like appending the 'marker' scatter points to a list and returning it, but I'm having trouble with the return of the animate function. Here is the basic code without trying to append to a list. I trimmed down a lot of the figure and axis setup. As this code sits, the line sweeps around the plot and when it reaches a point where a marker is, the marker flashes then disappears.
fig = plt.figure(1)
ax = fig.add_subplot(111,projection='polar')
ax.set_theta_zero_location('N',offset=0)
ax.set_theta_direction(-1)
line, = ax.plot((0,0),(0,0))
list = []
def animate(i):
line.set_data((0,line_az_time[i][0]),(0,300))
if(line_az_time[i][1] in marker_time):
marker = plt.scatter(marker_az[0],marker_range[0])
list.append(marker)
del marker_az[0]
del marker_range[0]
return line, list # wrong return type?
return line, list # how to handle empty list before 1st marker appended?
def init():
line.set_data((0,0),(0,300))
return line,
ani = animation.FuncAnimation(fig,animate,np.arange(len(line_az_time)),
blit=True,interval=0,repeat=True,init_func=init)
plt.show()
'line_az_time' is a nested list of the format [[angle1, time1],[angle2,time2]...]
Basically it saves an angle and the time that angle occurs. the 'marker_xxx' variables are the angles, ranges, and times of target detections. When the line is getting animated, it is checking if a detection is occuring at that time and angle. The times and detections are always sequential, so I just delete them once they've been plotted.
Basically all I need is keeping the 'marker' scatter points to persist throughout the animation. As stated before, I tried appending them to a list and returning the list instead of 'marker' itself. That way, they all get plotted once they've occurred. But that didn't work. I think I am confused by what type of variable to pack them into and how to write the 'return' lines once I append them to a variable.
Or if there is another way, I'd be open to that as well.
I'd like to be able to change things about the slider (the value, the start/end values) programmatically.
So I take the standard slider.py demo, and just add this at the end:
for i in range(5):
amp_slider.value = amp_slider.value + 1
time.sleep(1)
That should move the value upwards every second for a few seconds. But the slider doesn't move. What am I doing wrong? Or similarly if I try to change the .end or .start value.
[I know sliders are supposed to be INPUT not OUTPUT devices. But nonetheless I'm trying to control its behavior.]
bokeh show() outputs the chart as html & javascript. Once it has done this it can no longer be modified (unless you wrote some javascript which was included to modify the page).
You need a library that renders in a 'dynamic' window (such as matplotlib to be able to replot a chart like this.
The only code inside your program that will be used again once the page is created is in the callback functions. If you adjust sliders.py so it reads:
def update_title(attrname, old, new):
amplitude.value += 1
Every time you update the text, the amplitude will increase.
I'm new to Bokeh and was wondering if anyone could lend a little help tell me why my plot is not updating? The code is very simple, and can be found here:
http://pastebin.com/MLAigEG6
The code is just supposed to grab some data using the function "get_dataset", plot a bar chart, and let me update the plot using a dropdown box and slider. The two small dataframes can be found here:
https://github.com/degravek/bdata
The slider is set to default at 15 (30 total values plotted). If the slider is moved, or if the dropdown box is changed, the axes for the plot don't update for some reason. For example, if the slider is set to 2, there should only be 2 bars shown, and the axes should adjust accordingly. Thanks a lot for taking a look.
Nice code. In your update function, you also need to update the x_range.factors of the plot. And global asdata is not needed here.
def update_samples_or_dataset(attrname, old, new):
dataset = dataset_select.value
n_samples = int(samples_slider.value)
asdata = get_dataset(dataset, n_samples)
plot.x_range.factors = asdata['aspects'].tolist() # this was missing
source.data = dict(x=asdata['aspects'].tolist(), y=asdata['importance'].values)
I have a little app that allows me to change an input value with a tKinter scale widget and see how a graph reacts to different changes in inputs. Every time I move the scale, it's bound to an event that redoes the calculations for a list and replots. It's kind of slow.
Now, I'm replotting the entire thing, but it's stacking one axis on top of the other, hundreds after a few minutes of use.
deltaPlot = Figure(figsize=(4,3.5), dpi=75, frameon=False)
c = deltaPlot.add_subplot(111)
c.set_title('Delta')
deltaDataPlot = FigureCanvasTkAgg(deltaPlot, master=master)
deltaDataPlot.get_tk_widget().grid(row=0,rowspan=2)
and the main loop runs
c.cla()
c.plot(timeSpread,tdeltas,'g-')
deltaDataPlot.show()
It's clearing the initial plot, but like I said the axes are stacking (because it's redrawing one each time, corresponding to the slightly altered data points). Anyone know a fix?
To improve speed there are a couple of things you could do:
Either Run the remove method on the line produced by plot:
# inside the loop
line, = c.plot(timeSpread,tdeltas,'g-')
deltaDataPlot.show()
...
line.remove()
Or Re-use the line, updating its coordinates appropriately:
# outside the loop
line, = c.plot(timeSpread,tdeltas,'g-')
# inside the loop
deltaDataPlot.show()
line.set_data(timeSpread,tdeltas)
The documentation of Line2d can be found here.
You might also like to read the cookbook article on animation.
HTH