Wobbling in matplotlib animation - python

This is my first post, so I apologise if I am doing something wrong. I couldn't find any similar questions.
I am trying to generate an animation/video using matplotlib. The animation shows a dot moving along a curve. In my attempt to do this, I can see the point wobbling as it moves along the curve. How can I get rid of this effect? Here's a short script able to reproduce the effect and a gif animation. Thanks in advance
import numpy as np
import matplotlib.pyplot as plt
N=800#The bigger this number the worse the effect
s=np.linspace(0,2*np.pi,N)
xy=np.array([s,np.power(s,0.8)])#
plt.ion()
fig, ax=plt.subplots()
line1,=ax.plot(xy[0,:],xy[1,:],'-g')
t=0
ms=8
line2,=ax.plot(xy[0,t],xy[1,t],'or',markersize=ms)
ax.set_aspect('equal')
disc=1
M=N#int(N/2)
for lab in range(0,M,disc):
line1.set_xdata(xy[0,:])
line1.set_ydata(xy[1,:])
line2.set_xdata(xy[0,lab])
line2.set_ydata(xy[1,lab])
fig.canvas.draw()
fig.canvas.flush_events()
print("done!")

Related

Matplotlib is slow when plotting many graphs on a single plot

As the title says when I try to graph a bunch of graphs, it takes a very long time. For example if I try to plot a silly example like this 10000 times:
n=10000
numbers = []
for i in range(n):
numbers.append(i)
for i in range(n):
plt.plot(numbers)
plt.show()
It will take about a minute to show the plot.
I know doing this will make it faster
import matplotlib
matplotlib.use('GTKAgg')
But is there any other way to make plotting a bunch of graphs faster? Any suggestions would be much appreciated, thanks!
You could do a dynamic plot with plt.ion()
example:
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
su = fig.add_subplot(111)
su.axis([-1, 1, -1, 1])
plt.ion() # allows for dynamic plot
for i in range(1000):
y = np.random.random()
su.scatter(y**2, y)
plt.pause(0.4)
while True:
plt.pause(0.05)
This allows you to see points as they come up on your graph.
Is this what you want?
EDIT:
Maybe you could try using matplotlib.pyplot's savefig functionality
https://matplotlib.org/devdocs/api/_as_gen/matplotlib.pyplot.savefig.html
You could have your computer save all of your figures to separate png files. Then you can look at the pictures any time. This method requires minimal time on your part, just let the program run in the background for a bit while it makes the pngs, and you can view them without having to regenerate them at any time.

animate traffic using matplotlib

I would like to make a video with some car traffic. For this I have all state information of all cars. Drawing the situation for a given time is no problem. Animation is. I made some code that looks like the code below but this does not work: nothing is moving. I do not understand the basics of animation. Can someone point me in the right direction?
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.animation as manimation
FFMpegWriter = manimation.writers['ffmpeg']
writer = FFMpegWriter(fps=10)
def animate_traffic():
fig=plt.figure(1)
ax=fig.add_subplot(1,1,1)
tsim=tstart
with writer.saving(fig, "roadtest.mp4", 100):
for i in range(100):
draw_roadlayout()
for car in cars:
# draw each of the cars on the road
# based on time tsim
plt.grid(False)
ax.axis(plt_area)
fig = plt.gcf()
writer.grab_frame()
ax.cla()
tsim+=timestep
plt.close(1)
Thank you.
updated: after writing, I clear the area. The full version works for me now.
If you can generate images that show movement, you can just save them and create video using ffmpeg.
ax.cla() was a large part of the answer. Things can really improve but it works.

Animating a Quadmesh from pcolormesh with matplotlib

As a result of a full day of trial and error, I'm posting my findings as a help to anyone else who may come across this problem.
For the last couple days, I've been trying to simulate a real-time plot of some radar data from a netCDF file to work with a GUI I'm building for a school project. The first thing I tried was a simple redrawing of the data using the 'interactive mode' of matplotlib, as follows:
import matplotlib.pylab as plt
fig = plt.figure()
plt.ion() #Interactive mode on
for i in range(2,155): #Set to the number of rows in your quadmesh, start at 2 for overlap
plt.hold(True)
print i
#Please note: To use this example you must compute X, Y, and C previously.
#Here I take a slice of the data I'm plotting - if this were a real-time
#plot, you would insert the new data to be plotted here.
temp = plt.pcolormesh(X[i-2:i], Y[i-2:i], C[i-2:i])
plt.draw()
plt.pause(.001) #You must use plt.pause or the figure will freeze
plt.hold(False)
plt.ioff() #Interactive mode off
While this technically works, it also disables the zoom functions, as well as pan, and well, everything!
For a radar display plot, this was unacceptable. See my solution to this below.
So I started looking into the matplotlib animation API, hoping to find a solution. The animation did turn out to be exactly what I was looking for, although its use with a QuadMesh object in slices was not exactly documented. This is what I eventually came up with:
import matplotlib.pylab as plt
from matplotlib import animation
fig = plt.figure()
plt.hold(True)
#We need to prime the pump, so to speak and create a quadmesh for plt to work with
plt.pcolormesh(X[0:1], Y[0:1], C[0:1])
anim = animation.FuncAnimation(fig, animate, frames = range(2,155), blit = False)
plt.show()
plt.hold(False)
def animate( self, i):
plt.title('Ray: %.2f'%i)
#This is where new data is inserted into the plot.
plt.pcolormesh(X[i-2:i], Y[i-2:i], C[i-2:i])
Note that blit must be False! Otherwise it will yell at you about a QuadMesh object not being 'iterable'.
I don't have access to the radar yet, so I haven't been able to test this against live data streams, but for a static file, it has worked great thus far. While the data is being plotted, I can zoom and pan with the animation.
Good luck with your own animation/plotting ambitions!

Drawing obtuse circular arc with arrowhead in matplotlib

I am new to Python, though I do have previous programming experience. My current interest is to generate good quality schematics (and maybe later on also data graphs).
I need to draw a circlar arc with an arrowhead at the end point. I have sieved through many posts and tried my hand at a few examples, but it seems I still miss some basic knowledge. So I need something like this:
http://i.stack.imgur.com/Z5V86.png
I was experimenting with the example below, trying to initially plot a circular arc, but even this does not work. I am using matplotlib.patches but I am open to other suggestions for what I need.
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse, Arc
from matplotlib import cm, colors, patches
from math import pi
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ellipse = Arc([2.5,2.5],1,1,0,0,pi,color='green', linewidth='0.5')
ax.add_patch(ellipse)
plt.show()
Well,
if you want an angle of pi, pass 180.
linewidth must be a scalar. pass .5 and not '.5' as linewidth parameter
you need to change the limits of the axes, or you won't see the arc. Add something like ax.set_xlim(1.5,3.1) and ax.set_ylim(2.4,3.7).
You may also want to opt for another strategy, something like
ax.plot([.5],[.5],marker=r'$\circlearrowleft$',ms=100)

Plotting curved line in Python Basemap

I would like to plot curved/arced lines on a Basemap map.
I can plot a straight line using map.plot(x,y,..), but how do I make it curved/have arrows?
In matplotlib, this can be done using annotate(..), but Basemap doesn't have this method.
Any ideas?
This is a very old question, but I thought it might be good to answer anyway. When you said curved lines, I assumed you meant drawing a great circle. There is an example of doing exactly that in the basemap documentation, which I have modified to make a little more easy to modify yourself:
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
m = Basemap(projection='cyl')
p0_ll = -73.98, 40.78
p1_ll = 0.08, 51.53
m.drawgreatcircle(p0_ll[0], p0_ll[1], p1_ll[0], p1_ll[1],
linewidth=2, color='b')
m.drawcoastlines()
m.fillcontinents()
plt.show()
Note that the great circle method cannot handle the crossing of the edges of the map (as mentioned in the documentation), which, although clearly documented, is a pretty major flaw IMHO.
Hope that helps somebody,

Categories