1

Can I remove a matplotlib artist such as a patch by using blitting?

    """Some background code:"""

    from matplotlib.figure import Figure
    from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas

    self.figure = Figure()
    self.axes = self.figure.add_subplot(111)
    self.canvas = FigureCanvas(self, -1, self.figure)

To add a patch to a matplotlib plot by using blit you can do the following:

    """square is some matplotlib patch"""

    self.axes.add_patch(square)
    self.axes.draw_artist(square)
    self.canvas.blit(self.axes.bbox)

This works. However, can I use blit to remove this same artist from the plot? I managed to remove it with square.remove()and I can update the plot with the self.canvas.draw() function. But ofcourse this is slow and I would like to instead make use of blitting.

    """square is some matplotlib patch"""

    square.remove()
    self.canvas.draw()

The following does not work:

    square.remove()
    self.canvas.blit(self.axes.bbox)
2
  • Not sure if I understand the question correctly, but why not blit the canvas again, just without the square? Commented Mar 12, 2018 at 13:58
  • square.remove() and after that self.canvas.blit(self.axes.bbox) does not seem to work. The artist stays present in the plot. Commented Mar 12, 2018 at 14:14

1 Answer 1

3

The idea to remove a blitted object would be to just blit the same region again, just not draw the object beforehands. You may well also remove it, such that it would also not be seen if the canvas is redrawn for any other reason.

It seems in the code from the question you have forgotten to call restore_region. For a complete set of what commands are needed for blitting, see e.g. this question.

An example would be the following, where the rectangle is shown if you click the left mouse button and is removed if you hit the right button.

import matplotlib.pyplot as plt
import numpy as np

class Test:
    def __init__(self):
        self.fig, self.ax = plt.subplots()
        # Axis with large plot
        self.ax.imshow(np.random.random((5000,5000)))
        # Draw the canvas once
        self.fig.canvas.draw()
        # Store the background for later
        self.background = self.fig.canvas.copy_from_bbox(self.ax.bbox)
        # create square
        self.square = plt.Rectangle([2000,2000],900,900, zorder=3, color="crimson")
        # Create callback to mouse movement
        self.cid = self.fig.canvas.callbacks.connect('button_press_event', 
                                                     self.callback)
        plt.show()

    def callback(self, event):
        if event.inaxes == self.ax:
            if event.button == 1:
                # Update point's location            
                self.square.set_xy((event.xdata-450, event.ydata-450))
                # Restore the background
                self.fig.canvas.restore_region(self.background)
                # draw the square on the screen
                self.ax.add_patch(self.square)
                self.ax.draw_artist(self.square)
                # blit the axes
                self.fig.canvas.blit(self.ax.bbox)
            else:
                self.square.remove()
                self.fig.canvas.restore_region(self.background)
                self.fig.canvas.blit(self.ax.bbox)

tt = Test()
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Just reblitting the canvas without the square works .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.