Search code examples
matplotlibmatplotlib-animation

how to plot asynchronously in matplotlib?


1. Background

I draw a quadratic function curve (ax^2+bx+c, a>0) which has a minimum value, and I use an iterable method to search this value. After every step, there generates a point. What I want to do is draw this point dynamically.

2. Pseudocode

f(x)=ax^2+bx+c, a>0
g(t) is the mentioned method which is used to search the minimum value

plot f(x)
plot initial point (x0,y0)

for t in range(10000):
  new_x,new_y = g(t)

  move (x0,y0) to new position (new_x,new_y)

3. Solution

3.1 interactive plot

3.1.1 Example
import matplotlib
import matplotlib.pyplot as plt
import numpy as np

matplotlib.use("TkAgg")

plt.figure()
plt.grid(True)
plt.ion()

ft = np.linspace(0, 100, 1000)
plt.plot(ft, ft ** 2 + 1, c='r')
for t in range(100):
    plt.scatter(t, t ** 2 + 1, marker='.', c='b')

    plt.pause(1e-6)

plt.ioff()
plt.show()
3.1.2 Note
  1. It works, but it runs slowly.
  2. This method generates a track, which is redundant.

3.2 Animation

3.2.1 Example

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation

matplotlib.use("TkAgg")
def update_points(num):

    point_ani.set_data(x[num], y[num])
    return point_ani,


x = np.linspace(0, 100, 1000)
y = x**2+1

fig = plt.figure(tight_layout=True)
plt.plot(x, y)
point_ani, = plt.plot(x[0], y[0], "ro")
plt.grid(ls="--")
ani = animation.FuncAnimation(fig,
                              update_points,
                              interval=1,
                              blit=True)
plt.show()

print('finish')

3.2.2 Note

This method works without any track, but the entire moving path of point has to be known before drawing.

So, suppose there is an artist, it draws every time it receives a new point; it waits if no point is received. How to implement?


Solution

  • Using the Gradient descent method described in this Wikipedia link, here is the Python implementation, and the animation indicating the new "minima" at each step.

    import numpy as np
    import matplotlib.pyplot as plt
    ###initializing the parameters##################
    next_x = -5  # We start the search at x=-5
    gamma = 0.01  # Step size multiplier
    precision = 0.000001  # Desired precision of result
    max_iters = 10000  # Maximum number of iterations
    ########setup the plot################
    fig, ax = plt.subplots()
    ax.set_ylabel('y')
    ax.set_xlabel('x')
    ft = np.linspace(-50, 50, 1000)
    line, = ax.plot(ft, ft**2 + 1,c='r',linestyle='-')
    ax.set_title('Gradient descent showing the minima at each step')
    plt.ion()   # set interactive mode
    plt.show()
    #################################
    a=1
    b=0
    c=1
    # Derivative function
    def df(a,b,c,x):
        return 2*a*x + b
    # function
    def f(a,b,c,x):
        return a*x**2+b*x+c
    for _ in range(max_iters):
        current_x = next_x
        next_x = next_x - gamma * df(a,b,c,current_x)
        step = next_x - current_x
        #do the plotting after setting up canvas
        plt.gcf().canvas.draw()
        #show the new minima as a '.'
        line, = ax.plot(next_x,f(a,b,c,next_x),'.',c='black')
        plt.pause(0.1)
        #remove the track
        line.remove()
        del line
        if abs(step) <= precision:
            break
    print ("Minima at :{}".format(next_x))
    

    animated