Issue
I am new to matplotlib animation and am trying to animate a scatter plot where points moving towards the right will turn red gradually while points moving towards the left will turn blue gradually. The code doesn't work perfectly as it doesn't change the color of the points gradually. When I pause the animation and maximize it, the gradual change in color suddenly appears, when I play it, it is again the same. The final image should be something like this: But the animation doesn't show gradual change of colors as you can see in the video.
Here is the code, I'd really appreciate your help. Thanks
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import pandas as pd
class AnimatedScatter(object):
"""An animated scatter plot using matplotlib.animations.FuncAnimation."""
def __init__(self, numpoints=5):
self.numpoints = numpoints
self.stream = self.data_stream()
# Setup the figure and axes...
self.fig, self.ax = plt.subplots()
# Then setup FuncAnimation.
self.ani = animation.FuncAnimation(self.fig, self.update, interval=500,
init_func=self.setup_plot, blit=True,repeat=False)
self.fig.canvas.mpl_connect('button_press_event',self.onClick)
#self.ani.save("animation.mp4")
def setup_plot(self):
"""Initial drawing of the scatter plot."""
t=next(self.stream)
x, y, c = t[:,0],t[:,1],t[:,2]
self.scat = self.ax.scatter(x, y, c=c, s=50, animated=True)
self.ax.axis([-15, 15, -10, 10])
# For FuncAnimation's sake, we need to return the artist we'll be using
# Note that it expects a sequence of artists, thus the trailing comma.
return self.scat,
def data_stream(self):
#f=pd.read_csv("crc_viz.csv")
columns = ['TbyN','CbyS']
#f=f[['TbyN','CbyS']]
index=range(1,self.numpoints+1)
x=10*(np.ones((self.numpoints,1))-2*np.random.random((self.numpoints,1)))
y = 5*(np.ones((self.numpoints,1))-2*np.random.random((self.numpoints,1)))
f=np.column_stack((x,y))
f=pd.DataFrame(f,columns=columns)
print f
f['new_cbys'] = f['CbyS']
f['new_cbys'][f['new_cbys']<0] = -1
f['new_cbys'][f['new_cbys']>0] = 1
f=f[:self.numpoints]
cbys=np.array(list(f['CbyS']))
sign = np.array(list(f['new_cbys']))
x = np.array([0]*self.numpoints)
y = np.array(f['TbyN'])
c = np.array([0.5]*self.numpoints)
t = [(255,0,0) for i in range(self.numpoints)]
data=np.column_stack((x,y,c))
x = data[:, 0]
c = data[:,2]
while True:
#print xy
#print cbys
if not pause:
for i in range(len(x)):
if sign[i]==1:
if x[i]<cbys[i]-0.1:
x[i]+=0.1
c[i]+=0.05
else:
x[i]=cbys[i]
elif sign[i]==-1:
if x[i]>cbys[i]+0.1:
x[i]-=0.1
c[i]-=0.05
else:
x[i]=cbys[i]
print c
#print data
#print c
yield data
def onClick(self,event):
global pause
pause ^=True
def update(self, i):
"""Update the scatter plot."""
data = next(self.stream)
print data[:,2]
# Set x and y data...
self.scat.set_offsets(data[:, :2])
# Set colors..
self.scat.set_array(data[:,2])
return self.scat,
def save(self):
plt.rcParams['animation.ffmpeg_path'] = 'C:\\ffmpeg\\bin\\ffmpeg.exe'
self.mywriter = animation.FFMpegWriter()
self.ani.save("myMovie.mp4",writer=self.mywriter)
self.show()
def show(self):
#mng = plt.get_current_fig_manager()
#mng.window.state('zoomed')
plt.show()
pause = False
if __name__ == '__main__':
a = AnimatedScatter(10)
a.show()
#a.save()
Solution
The problem you have is that the scatter plot is redrawn in every iteration, renormalizing the colors to the minimal and maximal value of c
. So even at the start there will be a dot coresponding to the minmal and maximal color in the colormap already.
The solution would be to use a color normalization which is absolute from the start. The easiest way to do this is using the vmin
and vmax
keyword arguments.
ax.scatter(x, y, c=c, vmin=-1.5, vmax=2)
(This means that a value of c=-1.5
is the lowest color in the colormap and c=2
corresponds to the highest.)
Now it may be a bit hard to find the appropriate values, as the values are constantly changing in an infinite loop, so you need to find out appropriate values yourself depending on the use case.
Answered By - ImportanceOfBeingErnest
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.