Saturday, November 23, 2024
Google search engine
HomeLanguagesMatplotlib – Animate Multiple Lines

Matplotlib – Animate Multiple Lines

In this article, we are going to learn about how to make an animated chart of multiple lines using matplotlib. Animating the charts can make things more attractive and also help others to visualize the data more appropriately rather than static charts. Animations make even more sense when we are working with projects(stock markets, ECG Anomaly Detection, Internet Traffic Forecasting) that depicts the time series data.

The matplotlib.animation.FuncAnimation class is used to make animation calls recursively. You must store the created Animation in a variable that lives as long as the animation should run. Otherwise, the Animation object will be garbage-collected and the animation stops. 

Syntax: class matplotlib.animation.FuncAnimation(fig, func, frames=None, init_func=None, fargs=None, save_count=None, *, cache_frame_data=True, **kwargs)

Example 1:

For matplotlib there are two important modules we need primarily: pyplot and animation(Funcanimation). Below is a step-wise approach on how to animate lines in matplotlib. We are going to make our first example with 4 manually built plots using the random numbers in a certain range.

  • Import all necessary libraries for creating charts and animation.

Python3




# importing all necessary libraries
import random
import matplotlib
from matplotlib import animation
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
%matplotlib qt


  • Now make 4 different sets of y i.e y1,y2,y3,y4  which are going to share with the same x-axis values. While taking the random values we are going to divide each random value because these will help us to get different exponential lines.

Python3




# add random points for each line
l1 = [random.randint(-20, 4)+(points**1.88)/(random.randint(13, 14))
      for points in range(0, 160, 2)]
l2 = [random.randint(0, 9)+(points**1.9)/(random.randint(9, 11))
      for points in range(0, 160, 2)]
l3 = [random.randint(-10, 10)-(points**1.4)/(random.randint(9, 12))
      for points in range(0, 160, 2)]
l4 = [random.randint(-5, 10)-(points**1.1)/(random.randint(7, 12))
      for points in range(0, 160, 2)]


  • Now use itertools to iterate. This module works fast, it is a memory-efficient tool that is used either by itself or in combination to form iterator algebra. You can also use for loop to iterate just create one list and start storing the variables of y w.r.t x.

Python3




from itertools import count
myvar = count(0, 3)


  • Create 3 extra empty lists for new lines (y2 ,y3, and y4) total of 5 empty lists when we include x1 and y1. Inside the animation function, we will fill those containers at each iteration step. In each iteration single frame created animation. Also, add colors for 4 different lines.

Python3




# subplots() function you can draw
# multiple plots in one figure
fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(10, 5))
 
# set limit for x and y axis
axes.set_ylim(-100, 500)
axes.set_xlim(0, 250)
 
# style for plotting line
plt.style.use("ggplot")
 
# create 5 list to get store element
# after every iteration
x1, y1, y2, y3, y4 = [], [], [], [], []
myvar = count(0, 3)
 
def animate(i):
    x1.append(next(myvar))
    y1.append((l1[i]))
    y2.append((l2[i]))
    y3.append((l3[i]))
    y4.append((l4[i]))
 
    axes.plot(x1, y1, color="red")
    axes.plot(x1, y2, color="gray")
    axes.plot(x1, y3, color="blue")
    axes.plot(x1, y4, color="green")
 
 
# set ani variable to call the
# function recursively
anim = FuncAnimation(fig, animate, interval=30)


Below is the complete program:

Python3




# importing all necessary libraries
from itertools import count
import random
import matplotlib
from matplotlib import animation
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
%matplotlib qt
 
# add random points for each line
l1 = [random.randint(-20, 4)+(points**1.88)/(random.randint(13, 14))
      for points in range(0, 160, 2)]
l2 = [random.randint(0, 9)+(points**1.9)/(random.randint(9, 11))
      for points in range(0, 160, 2)]
l3 = [random.randint(-10, 10)-(points**1.4)/(random.randint(9, 12))
      for points in range(0, 160, 2)]
l4 = [random.randint(-5, 10)-(points**1.1)/(random.randint(7, 12))
      for points in range(0, 160, 2)]
 
myvar = count(0, 3)
 
# subplots() function you can draw
# multiple plots in one figure
fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(10, 5))
 
# set limit for x and y axis
axes.set_ylim(-100, 500)
axes.set_xlim(0, 250)
 
# style for plotting line
plt.style.use("ggplot")
 
# create 5 list to get store element
# after every iteration
x1, y1, y2, y3, y4 = [], [], [], [], []
myvar = count(0, 3)
 
def animate(i):
    x1.append(next(myvar))
    y1.append((l1[i]))
    y2.append((l2[i]))
    y3.append((l3[i]))
    y4.append((l4[i]))
 
    axes.plot(x1, y1, color="red")
    axes.plot(x1, y2, color="gray")
    axes.plot(x1, y3, color="blue")
    axes.plot(x1, y4, color="green")
 
 
# set ani variable to call the
# function recursively
anim = FuncAnimation(fig, animate, interval=30)


Output :

Example 2: 

Here is another example to animate multiple lines in matplotlib.

  • Import all necessary Libraries.

Python3




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


 
 

  • Create a function update line to get a new value for each iteration.

 

Python3




def updateline(num, data, line1, data2, line2):
    line1.set_data(data[..., :num])
    line2.set_data(data2[..., :num])
     
    time_text.set_text("Points: %.0f" % int(num))
     
    return line1, line2
 
 
# generating data of 100 elements
# each for line 1
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
data = np.array([x, y])
 
# generating data of 100 elements
# each for line 2
x2 = np.linspace(0, 2*np.pi, 100)
y2 = np.cos(x2)
data2 = np.array([x2, y2])
 
# setup the formatting for moving files
Writer = animation.writers['ffmpeg']
Writer = Writer(fps=10, metadata=dict(artist="Me"), bitrate=-1)
 
 
fig = plt.figure()
ax = fig.add_subplot(111)
l, = ax.plot([], [], 'r-', label="Sin")
ax2 = ax.twinx()
k = ax2.plot([], [], 'b-', label="Cos")[0]
 
ax.legend([l, k], [l.get_label(), k.get_label()], loc=0)
 
ax.set_xlabel("X")
 
# axis 1
ax.set_ylim(-1.5, 1.5)
ax.set_xlim(0, 7)
 
# axis 2
ax2.set_ylim(-1.5, 1.5)
ax2.set_xlim(0, 7)
 
plt.title('Sin and Cos')
time_text = ax.text(0.1, 0.95, "", transform=ax.transAxes,
                    fontsize=15, color='red')


  • Save mp4 file [By default files saved in your present directory].

Python3




# set line_animation variable to call
# the function recursively
line_animation = animation.FuncAnimation(
    fig, updateline, frames=100, fargs=(data, l, data2, k))
 
line_animation.save("lines.mp4", writer=Writer)


Below is the complete program:

Python3




# import required modules
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as animation
 
 
def updateline(num, data, line1, data2, line2):
    line1.set_data(data[..., :num])
    line2.set_data(data2[..., :num])
     
    time_text.set_text("Points: %.0f" % int(num))
     
    return line1, line2
 
 
# generating data of 100 elements
# each for line 1
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
data = np.array([x, y])
 
# generating data of 100 elements
# each for line 2
x2 = np.linspace(0, 2*np.pi, 100)
y2 = np.cos(x2)
data2 = np.array([x2, y2])
 
# setup the formatting for moving files
Writer = animation.writers['ffmpeg']
Writer = Writer(fps=10, metadata=dict(artist="Me"), bitrate=-1)
 
 
fig = plt.figure()
ax = fig.add_subplot(111)
l, = ax.plot([], [], 'r-', label="Sin")
ax2 = ax.twinx()
k = ax2.plot([], [], 'b-', label="Cos")[0]
 
ax.legend([l, k], [l.get_label(), k.get_label()], loc=0)
 
ax.set_xlabel("X")
 
# axis 1
ax.set_ylim(-1.5, 1.5)
ax.set_xlim(0, 7)
 
# axis 2
ax2.set_ylim(-1.5, 1.5)
ax2.set_xlim(0, 7)
 
plt.title('Sin and Cos')
time_text = ax.text(0.1, 0.95, "", transform=ax.transAxes,
                    fontsize=15, color='red')
 
# set line_animation variable to call
# the function recursively
line_animation = animation.FuncAnimation(
    fig, updateline, frames=100, fargs=(data, l, data2, k))
line_animation.save("lines.mp4", writer=Writer)


Output :

RELATED ARTICLES

Most Popular

Recent Comments