matplotlib animation with multiple plots and for loop - python-3.x

hey I'm trying to get matplotlib.animation to plot n plots in one graph like the first code block below, but when I run the script everything seems to run except none of the plots show up.
import matplotlib.pyplot as plt
# Data to be ploted
x = []
y = []
x2 = []
y2 = []
for i in range(-9,9):
x.append(i)
y.append(i**2)
x2.append(i)
y2.append(i**3)
# plot the data
plt.plot(x,y, label = 'first line')
# plot other data points
plt.plot(x2,y2, label = 'second line')
# add this before plt.show() to add labels to graph
plt.xlabel('X value')
plt.ylabel('Y value')
# add a title to graph
plt.title('interesting graph\nsubtitle')
plt.legend()
plt.show()
here is the code using animate:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
# better face
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def anima(i):
graph_data = open('a.txt').read()
lines = graph_data.split('\n')
dataPoints = []
for i in lines:
# ignor empty lines
if len(i) > 1:
line = i.split('|') # delimiter is |
for a in range(len(line)):
try:
dataPoints[a].append(int(line[a]))
# if there is no dataPoint[a] it gets created
except:
dataPoints.append(int(line[a]))
# modify axis
ax1.clear()
# plot
for i in range(len(dataPoints)-1):
ax1.plot(dataPoints[1],dataPoints[i+1])
#where to animate, what to animate, how often to update
ani = animation.FuncAnimation(fig, anima, interval = 1000)
plt.show()
in a.txt I have this:
1|56|80|62
2|123|135|55
12|41|12|23
60|12|45|23
12|43|56|54
25|123|23|31
2|213|31|84
61|1|68|54
62|2|87|31
63|4|31|53
64|8|13|13
65|16|51|65
66|32|43|84
80|62|42|15
update:
I gave up on reading a file and am having a threaded function generate values for me and instead for having everything in one plot I am having everything in subplots(the number is going to be edited soon). when I run the code with a normal plot it works fine, but when I try to use animate... it shows the graphs but no plot once again. my problem is showing the animated plot
# check if os is linux
import platform
if str(platform.system()).lower() == str('linux').lower():
# must be set befor importing any other matplotlib
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
from threading import Thread
# Change style
style.use('fivethirtyeight')
fig = plt.figure()
#list with all datapoints eg: [timeList],[graph1List]....
data_points = []
# 'name' of each graph in the list
graphs_ = [0]
def create_plots():
xs = []
ys = []
for i in range(-10,11):
x = i
y = i**3
xs.append(x)
ys.append(y)
data_points.append(xs)
data_points.append(ys)
t = Thread(target=create_plots)
t.start()
def anima(i):
for i in range(len(graphs_)):
graphs_[i]=fig.add_subplot(211+i)
graphs_[i].clear()
graphs_[i].plot(0,i+1)
while len(data_points) == 0:
print('.')
ani = animation.FuncAnimation(fig, anima, interval=1000)
plt.show()

1) Are you sure your anima(i) function gets called?
2) Why are you overwriting the variable i in anima(i) and again in line?
for i in lines:
# ignor empty lines

Related

How to update scatter with plot?

I am updating the graph, but can't join to it the scatter, could someone help me, please? I don't understand, how to realize it.
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
fig = plt.figure()
ax = fig.add_subplot()
line = ax.plot([],[])[0]
x = []
y = []
scat = ax.scatter(x,y,c='Red')
def animate(i):
x.append(i)
y.append((-1)**i)
line.set_data(x, y)
ax.relim()
ax.autoscale_view()
return [line]
anim = FuncAnimation(fig, animate, frames=200, interval=100, blit=True)
plt.show()
I want to add dotes and their coordinates change only in X, Y should be 0.
Several problems have to be addressed here. You have to update the scatter plot, which is a PathCollection that is updated via .set_offsets(). This is in turn requires the x-y data to be in an array of the form (N, 2). We could combine the two lists x, y in every animation loop to such an array but this would be time-consuming. Instead, we declare the numpy array in advance and update it in the loop.
As for axes labels, you might have noticed that they are not updated in your animation. The reason for this is that you use blitting, which suppresses redrawing all artists that are considered unchanged. So, if you don't want to take care manually of the axis limits, you have to turn off blitting.
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
fig, ax = plt.subplots()
line, = ax.plot([],[])
scat = ax.scatter([], [], c='Red')
n=200
#prepare array for data storage
pos = np.zeros((n, 2))
def animate(i):
#calculate new x- and y-values
pos[i, 0] = i
pos[i, 1] = (-1)**i
#update line data
line.set_data(pos[:i, 0], pos[:i, 1])
#update scatter plot data
scat.set_offsets(pos[:i, :])
#update axis view - works only if blit is False
ax.relim()
ax.autoscale_view()
return scat, line
anim = FuncAnimation(fig, animate, frames=n, interval=100, blit=False)
plt.show()
Sample output:

Line on animated matplotlib graph not showing up

I'm not sure why a graph line isn't showing on my widget.
The x-axis is moving with time as it should, and when I print the y-values that should be plotted (Temp), new values come up as expected. However, no line/points show up on the plot.
I've had a similar issue with a plot in the past, which was solved by changing the style of the points plotted (i.e. using 'r*' to make the points visible red stars). I'm not sure how to implement the same sort of thing in this code.
import matplotlib.pyplot as plt
import numpy
import datetime
import matplotlib.animation as animation
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
Time = []
Temp = []
x = datetime.datetime.now()
y = numpy.random.randint(48,52)
Time.append(x)
Temp.append(int(y))
ax1.plot(Time,Temp)
print(Temp)
ani = animation.FuncAnimation(fig,animate, interval=1000)
plt.show()
just put Time and Temp out of function animate
Time = []
Temp = []
def animate(i):
x = datetime.datetime.now()
y = numpy.random.randint(48,52)
Time.append(x)
Temp.append(int(y))
ax1.plot(Time,Temp)
print(Temp)
You can add the marker and it shows the points:
ax1.plot(Time,Temp, marker="s")

Python Matplotlib: Keep shared x axis while updating figure in loop

I want to update a plot every x seconds and keep the shared x axis. The problem is that when using a cla() command the sharedx gets lost and when not using the cla(), the plot is not updated, but "overplotted", as in this minimal example:
import matplotlib.pyplot as plt
import pandas as pd
data = pd.DataFrame([[1,2,1],[3,1,3]], index = [1,2])
n_plots = data.shape[1]
fig, axs = plt.subplots(n_plots , 1, sharex = True)
axs = axs.ravel()
while True:
for i in range(n_plots):
#axs[i].cla()
axs[i].plot(data.iloc[:,i])
axs[i].grid()
plt.tight_layout()
plt.draw()
plt.pause(5)
data = pd.concat([data,data]).reset_index(drop = True)
The behaviour can be seen by uncommenting the axs[i].cla() line.
So the question is:
How can I update a plot (without predefined number of subplots) in a while loop (I want to update some data) and keep a shared x-axis?
Thanks in advance
First, to produce animations with matplotlib you should have a look at FuncAnimation. You'll find lots of posts on SO on this subject, for instance: Dynamically updating plot in matplotlib
The general guideline is to not repetitively call plt.plot() but instead use the set_data() function of the Line2D object returned by plot(). In other words, in a first part of your code you instantiate an object with an empty plot
l, = plt.plot([],[])
and then, whenever you need to update your plot, you keep the same object (do not clear the axes, do not make a new plot() call), and simply update its content:
l.set_data(X,Y)
# alternatively, if only Y-data changes
l.set_ydata(Y) # make sure that len(Y)==len(l.get_xdata())!
EDIT: Here is a minimal example showing 3 axes with shared x-axis, like you are trying to do
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
N_points_to_display = 20
N_lines = 3
line_colors = ['r','g','b']
fig, axs = plt.subplots(N_lines, 1, sharex=True)
my_lines = []
for ax,c in zip(axs,line_colors):
l, = ax.plot([], [], c, animated=True)
my_lines.append(l)
def init():
for ax in axs:
ax.set_xlim((0,N_points_to_display))
ax.set_ylim((-1.5,1.5))
return my_lines
def update(frame):
#generates a random number to simulate new incoming data
new_data = np.random.random(size=(N_lines,))
for l,datum in zip(my_lines,new_data):
xdata, ydata = l.get_data()
ydata = np.append(ydata, datum)
#keep only the last N_points_to_display
ydata = ydata[-N_points_to_display:]
xdata = range(0,len(ydata))
# update the data in the Line2D object
l.set_data(xdata,ydata)
return my_lines
anim = FuncAnimation(fig, update, interval=200,
init_func=init, blit=True)

Python: Matplotlib: update graph by time in second

I have a series to plot at y-axis.
y = [3,4,5,1,4,7,4,7,1,9]
However, I want to plot it by recent time by second. I've done it like this,
import time
def xtime():
t = time.strftime("%H%M%S")
t = int(t)
xtime = [t]
while xtime:
t = time.strftime("%H%M%S")
t = int(t)
xtime.extend([t])
time.sleep(1)
I'm having problem when I want to plot each one of the number at y by each second. Please correct my code here,
import time
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig = plt.figure()
def animate(i):
x = xtime()
y = [3,4,5,1,4,7,4,7,1,9]
plt.plot(x,y)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
xtime function is referred as code at first.
Thanks!
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
# Y data
ydata = [3,4,5,1,4,7,4,7,1,9]
# how many points
N = len(ydata)
# make x data
xdata = np.arange(N)
def animate(i):
# update the date in our Line2D artist
# note that when run this will look at the global namespace for
# an object called `ln` which we will define later
ln.set_data(xdata[:i], ydata[:i])
# return the updated artist for the blitting
return ln,
# make our figure and axes
fig, ax = plt.subplots()
# make the artist we will be using. Note this was used in `animate`
ln, = ax.plot([], [], animated=True)
# set the axes limits
ax.set_xlim(0, N)
ax.set_ylim(0, 10)
# run the animation. Keeping a ref to the animation object is important
# as if it gets garbage collected it takes you timer and callbacks with it
ani = animation.FuncAnimation(fig, animate, frames=N, interval=1000, blit=True)

Matplotlib FuncAnimation not animating line plot

I have two random vectors which are used to create a line plot. Using the same vectors, I would like to animate the line but the animation is static - it just plot the original graph. Any suggestions on how to animate such a line plot?
import numpy as np
import matplotlib.pyplot as py
from matplotlib import animation
# random line plot example
x = np.random.rand(10)
y = np.random.rand(10)
py.figure(3)
py.plot(x, y, lw=2)
py.show()
# animation line plot example
fig = py.figure(4)
ax = py.axes(xlim=(0, 1), ylim=(0, 1))
line, = ax.plot([], [], lw=2)
def init():
line.set_data([], [])
return line,
def animate(i):
line.set_data(x, y)
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=200, interval=20, blit=False)
The final frame of the animation should look something like the plot below. Keep in mind that this is a random plot so the actual figure will change with each run.
Okay, I think what you want is to only plot up to the i-th index for frame i of the animation. In that case, you can just use the frame number to limit the data displayed:
import numpy as np
import matplotlib.pyplot as py
from matplotlib import animation
x = np.random.rand(10)
y = np.random.rand(10)
# animation line plot example
fig = py.figure(4)
ax = py.axes(xlim=(0, 1), ylim=(0, 1))
line, = ax.plot([], [], lw=2)
def init():
line.set_data([], [])
return line,
def animate(i):
line.set_data(x[:i], y[:i])
return line,
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=len(x)+1,
interval=200, blit=False)
Notice I changed the number of frames to len(x)+1 and increased the interval so it's slow enough to see.

Resources