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")
Related
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:
I am trying to make an animation using ArtistAnimation like this:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
ims = []
for i in range(60):
x = np.linspace(0,i,1000)
y = np.sin(x)
im = ax.plot(x,y, color='black')
ims.append(im)
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,
repeat_delay=1000)
plt.show()
This animates a sine wave growing across the figure. Currently I'm just adding the Lines2D object returned by ax.plot() to ims. However, I would like to potentially draw multiple overlapping plots on the Axes and adjust the title, legend and x-axis range for each frame. How do I get an object that I can add to ims after plotting and making all the changes I want for each frame?
The list you supply to ArtistAnimation should be a list of lists of artists, one list per frame.
artist_list = [[line1a, line1b, title1], [line2a, line2b, title2], ...]
where the first list is shown in the first frame, the second list in the second frame etc.
The reason your code works is that ax.plot returns a list of lines (in your case only a list of a single line).
In any case, the following might be a more understandable version of your code where an additional text is animated.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
artist_list = []
for i in range(60):
x = np.linspace(0,i,1000)
y = np.sin(x)
line, = ax.plot(x,y, color='black')
text = ax.text(i,0,i)
artist_list.append([line, text])
ani = animation.ArtistAnimation(fig, artist_list, interval=50, blit=True,
repeat_delay=1000)
plt.show()
In general, it will be hard to animate changing axes limits with ArtistAnimation, so if that is an ultimate goal consider using a FuncAnimation instead.
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)
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
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)