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?

Author: Hidden, 2018-03-20

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:

enter a description of the image here

 9
Author: MaxU, 2018-03-21 07:28:39

In jupyter, draw animated graphs, like a real-time CPU load graph?

  1. 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)
    
  2. 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
    
  3. 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())
 7
Author: jfs, 2018-03-20 19:33:14