Python (jupyter) animated graph
Can you tell me if it is possible to draw animated graphics in jupyter, like a real-time CPU load graph? I'm trying to monitor the server response time to ping. I understand matplotlib, but either it does not know how to do this, or I did not find it.
import subprocess
import re
from matplotlib import pyplot as plt
def ping(adress):
p = subprocess.Popen(["ping.exe",adress], stdout = subprocess.PIPE)
out = p.communicate()[0]
t = re.search(r'time=(\d*)',str(out))
time = t.group().replace('time=','') if t else '0'
return (time)
x=[0]
%matplotlib inline
for i in range(0,10):
x.append(ping('ya.ru'))
plt.plot(x)
The graph is calculated all and drawn all at once, tell me how to make animation and is it possible at all?
2 answers
You can do this:
import psutil
from datetime import datetime as dt
from collections import deque
import matplotlib.pyplot as plt
from matplotlib.dates import date2num
import matplotlib.animation as animation
%matplotlib notebook
N=600
x = deque([date2num(dt.now())], maxlen=N)
y = deque([0], maxlen=N)
fig, ax = plt.subplots(figsize=(8,3))
line, = ax.plot_date(x, y, marker="")
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
def get_data():
# return ping('ya.ru')
return psutil.cpu_percent(.15)
def animate(i):
x.append(date2num(dt.now()))
y.append(get_data())
ax.relim(visible_only=True)
ax.autoscale_view(True)
line.set_data(x, y)
ax.fill_between(x, -0.5, y, color='lightgrey')
return line,
ani = animation.FuncAnimation(fig, animate, interval=300)
#ani.save("d:/temp/test.gif", writer='imagemagick', fps=10)
plt.show()
Result:
In jupyter, draw animated graphs, like a real-time CPU load graph?
-
Draw the background and axes of the graph:
%matplotlib inline import matplotlib.pyplot as plt fig, ax = plt.subplots() line, = ax.plot([], [], color='g') time_template = 'time = %s' time_text = ax.text(0.05, 0.9, '', transform=ax.transAxes)
-
Creating a function that generates the current values (x, y):
import time import psutil # !pip install psutil def frames(): while True: yield time.time(), psutil.cpu_percent(.15) # CPU % over the second
-
Updating the graph and the screen using the values obtained from
frames()
:import datetime as DT from collections import deque n = 1000 yy = deque([], maxlen=n) xx = deque([], maxlen=n) display_handle = display(None, display_id=True) def animate(args): xx.append(args[0]) yy.append(args[1]) line.set_data(xx, yy) time_text.set_text(time_template % DT.datetime.fromtimestamp(args[0])) ax.relim() # update axes limits ax.autoscale_view(True, True, True) display_handle.update(fig) for x_y in frames(): animate(x_y)
If you don't need Jupyter Lab support or a finite loop is enough, which as a video can be added, then instead of an explicit display_handler.update()
and an explicit loop, where manually animate()
is called, you can use:
%matplotlib notebook
from matplotlib import animation
ani = animation.FuncAnimation(fig, animate, frames=frames)
And/or (finite number of frames):
from IPython.display import HTML
HTML(ani.to_html5_video())