Matplotlib - Blitting



Blitting, short for "bit block transfer", is a technique used in computer graphics to quickly move blocks of pixels from one place to another on a screen. The basic idea is to copy a rectangular section of an image (often called a "bitmap" or "sprite") and paste it onto another part of the screen.

Imagine you have two images, and you want to combine them or move one of them to a different location on the screen. Instead of manually changing each pixel one by one, blitting allows you to copy a block of pixels from one image and paste it onto another image.

Blitting in Matplotlib

Blitting in matplotlib is a technique used to update and redraw only the specific portion of a plot that have changed during an animation, rather than redrawing the entire figure. By selectively updating only the changed elements, blitting improves performance and provides a smoother experience when working with dynamic visualizations in matplotlib.

Implementing Blitting in Matplotlib

Following are the basic steps used to implement blitting in Matplotlib −

Step 1 − Create a Background

Start by creating the initial background of your plot.

fig, ax = plt.subplots()
background = fig.canvas.copy_from_bbox(ax.bbox)

Step 2 − Update Plot Elements

Within each animation frame, update the specific plot elements that undergo changes.

for i in range(num_frames):
    # Update plot elements (e.g., scatter points, lines, etc.)
    # ...

Step 3 − Restore Background

After updating, restore the background to clear the previously drawn elements.

fig.canvas.restore_region(background)

Step 4 − Update Frames in a Loop

Inside a loop, update the plot for each frame by modifying the data or layout. In this example, the sine wave is shifted horizontally for each frame. The "camera.snap()" method captures the current frame.

num_frames = 50

for i in range(num_frames):
    # Update your plot for each frame
    x = np.linspace(0, 2 * np.pi, 100)
    y = np.sin(x + i * 0.1)
    ax.plot(x, y)

    # Capture the current frame
    camera.snap()

Step 5 − Redraw Modified Elements

Redraw only the elements that have been modified during the current frame.

ax.draw_artist(modified_element)

Step 6 − Blit to the Screen

Finally, use "fig.canvas.blit(ax.bbox)" to efficiently transfer the updated regions to the screen.

fig.canvas.blit(ax.bbox)

Complete Example

Following is the complete example of blitting in Matplotlib. In here, a plot is initialized with a sine wave. Instead of redrawing the entire plot in each frame, the background is saved once. For each iteration, the saved background is restored, and only the sine wave is updated and redrawn, reducing computational load −

import matplotlib.pyplot as plt
import numpy as np

# Initializing the background
fig, ax = plt.subplots()
background = fig.canvas.copy_from_bbox(ax.bbox)

# Updating plot elements
num_frames = 100
x = np.linspace(0, 2 * np.pi, 100)
line, = ax.plot(x, np.sin(x))

for i in range(num_frames):
    # Restoring background
    fig.canvas.restore_region(background)

    # Updating plot elements (Redrawing modified elements)
    line.set_ydata(np.sin(x + i * 0.1))
    ax.draw_artist(line)

    # Blitting to the screen
    fig.canvas.blit(ax.bbox)

# Displaying the final plot
plt.show()

The resulting animated plot displays the sine wave evolving over a specified number of frames.

Animated Scatter Plot with Blitting

An animated scatter plot with blitting is like visualizing a group of points moving around a plot over time. Each point represents data, and as time progresses, the positions of these points change, creating a dynamic and visually engaging animation. Blitting is used to update only the parts of the plot that have changed, making the animation smoother and more efficient.

Example

In here, we are creating an animated scatter plot using Matplotlib. The initial state of the scatter plot is saved as the background. The animation loop iterates through a specified number of frames. For each frame, the background is restored, and the scatter plot is updated by generating new random x and y coordinates. The modified scatter plot is then redrawn, and the process is optimized using blitting, resulting in a visually dynamic animated scatter plot −

import matplotlib.pyplot as plt
import numpy as np

# Initializing the background
fig, ax = plt.subplots()
background = fig.canvas.copy_from_bbox(ax.bbox)

# Creating initial scatter plot
x_initial = np.random.rand(20)
y_initial = np.random.rand(20)
scatter_initial = ax.scatter(x_initial, y_initial)

# Displaying the initial plot
plt.draw()
# Pause for a short time to display the initial plot
plt.pause(1)  

# Creating animated scatter plot
num_frames = 50
x_final = np.random.rand(20)
y_final = np.random.rand(20)
scatter_final = ax.scatter(x_final, y_final)

# Main animation loop
for i in range(num_frames):
    # Restoring background
    fig.canvas.restore_region(background)

    # Updating scatter plot (redrawing modified elements)
    x_final = np.random.rand(20)
    y_final = np.random.rand(20)
    scatter_final.set_offsets(np.column_stack((x_final, y_final)))
    ax.draw_artist(scatter_final)

    # Blitting to the screen
    fig.canvas.blit(ax.bbox)

# Displaying the final plot
plt.show()

Animated Bar Chart with Blitting

An animated bar chart with blitting is like visualizing a set of bars dynamically change in height over time. Each bar represents a different category, and as the animation progresses, the heights of these bars fluctuate, creating a dynamic visualization. Blitting is used to update only the parts of the chart that have undergone changes.

Example

In this example, we are creating an animated bar chart. The initial state of the bar chart is saved as the background. The animation loop iterates through a specified number of frames. For each frame, the background is restored, and the bar chart is updated by generating new random heights for each bar. The modified bar chart is then redrawn, and the process is optimized using blitting, resulting in an efficient and visually dynamic animated bar chart −

import matplotlib.pyplot as plt
import numpy as np

# Initializing the background
fig, ax = plt.subplots()
background = fig.canvas.copy_from_bbox(ax.bbox)

# Creating initial bar chart
x = np.arange(10)
heights_initial = np.random.randint(1, 10, size=10)
bars_initial = ax.bar(x, heights_initial)

# Displaying the initial plot
plt.draw()
# Pause for a short time to display the initial plot
plt.pause(1)  

# Creating animated bar chart
num_frames = 50
bars_final = ax.bar(x, np.random.randint(1, 10, size=10))

# Main animation loop
for i in range(num_frames):
    # Restoring background
    fig.canvas.restore_region(background)

    # Updating bar chart (redrawing modified elements)
    heights_final = np.random.randint(1, 10, size=10)
    for bar, height in zip(bars_final, heights_final):
        bar.set_height(height)
        ax.draw_artist(bar)

    # Blitting to the screen
    fig.canvas.blit(ax.bbox)

# Displaying the final plot
plt.show()
Advertisements