Effizientes Matplotlib-Nachziehen

Ich benutze Matplotlib, um dem Benutzer zu erlauben, interessante Datenpunkte mit Mausklicks auszuwählen, mit einer sehr ähnlichen Methode zu dieser Antwort.

In Wirklichkeit wird ein Streudiagramm über ein Hitzeschutzbild angezeigt, und Mausklicks können Streupunkte hinzufügen oder entfernen.

Meine Daten werden im Hintergrund mit pcolormesh() gezeichnet, also wenn ich die Leinwand mit axis.figure.canvas.draw() aktualisiere, werden sowohl die axis.figure.canvas.draw() als auch die Hintergrund-Hitzemappe neu gezeichnet. Angesichts der Größe der Wärmekapazität ist dies zu langsam für eine nutzbare Schnittstelle.

Gibt es eine Möglichkeit, die Streustellen selektiv neu zu zeichnen, ohne den Hintergrund neu zu zeichnen?

Beispiel Code:

 points = [] # Holds a list of (x,y) scatter points def onclick(event): # Click event handler to add points points.append( (event.x, event.y) ) ax.figure.canvas.draw() fig = plt.figure() ax = plt.figure() # Plot the background ax.pcolormesh(heatmap_data) # Add the listener to handle clicks cid = fig.canvas.mpl_connect("button_press_event", onclick) plt.show() 

One Solution collect form web for “Effizientes Matplotlib-Nachziehen”

Sicher! Was du willst, ist blitzschnell Wenn du kein gui matplotlib.animation , könntest du etwas davon mit matplotlib.animation vereinfachen, aber du musst es direkt behandeln, wenn du willst, dass die Dinge interaktiv sind.

In matplotlib-Begriffen willst du eine Kombination von fig.canvas.copy_from_bbox und dann abwechselnd fig.canvas.restore_region(background) , ax.draw_artist(what_you_want_to_draw) und fig.canvas.blit :

 background = fig.canvas.copy_from_bbox(ax.bbox) for x, y in user_interactions: fig.canvas.restore_region(background) points.append([x, y]) scatter.set_offsets(points) ax.draw_artist(scatter) fig.canvas.blit(ax.bbox) 

Einfache Blitting Beispiel: Hinzufügen von Punkten

In Ihrem Fall, wenn Sie nur Punkte hinzufügen, können Sie tatsächlich überspringen Speichern und Wiederherstellen des Hintergrunds. Wenn du diese Route gehst, dann wirst du mit einigen subtilen Änderungen an der Handlung aufwarten, da antialiierte Punkte immer wieder übereinander gezogen werden.

Auf jeden Fall ist hier das einfachste Beispiel für die Art der Sache, die du willst. Dies betrifft nur das Hinzufügen von Punkten und überspringt das Speichern und Wiederherstellen des Hintergrundes, wie ich oben erwähnt habe:

 import matplotlib.pyplot as plt import numpy as np def main(): fig, ax = plt.subplots() ax.pcolormesh(np.random.random((100, 100)), cmap='gray') ClickToDrawPoints(ax).show() class ClickToDrawPoints(object): def __init__(self, ax): self.ax = ax self.fig = ax.figure self.xy = [] self.points = ax.scatter([], [], s=200, color='red', picker=20) self.fig.canvas.mpl_connect('button_press_event', self.on_click) def on_click(self, event): if event.inaxes is None: return self.xy.append([event.xdata, event.ydata]) self.points.set_offsets(self.xy) self.ax.draw_artist(self.points) self.fig.canvas.blit(self.ax.bbox) def show(self): plt.show() main() 

Manchmal ist einfach zu einfach

Aber sagen wir, wir wollten rechtsklicks einen Punkt löschen.

In diesem Fall müssen wir den Hintergrund wiederherstellen können, ohne ihn neu zu zeichnen.

Ok, alles gut und gut Wir verwenden etwas Ähnliches wie das Pseudocode-Snippet, das ich an der Spitze der Antwort erwähnt habe.

Allerdings gibt es einen Vorbehalt: Wenn die Figur verkleinert ist, müssen wir den Hintergrund aktualisieren. Ähnlich, wenn die Achsen interaktiv gezoomt / geschwenkt werden, müssen wir den Hintergrund aktualisieren. Grundsätzlich müssen Sie den Hintergrund jederzeit aktualisieren, wenn die Handlung gezeichnet wird.

Schon bald muss man ziemlich komplex sein.


Mehr Komplex: Hinzufügen / Ziehen / Löschen von Punkten

Hier ist ein allgemeines Beispiel für die Art von "Gerüst" Sie wind up setzen an Ort und Stelle.

Das ist etwas ineffizient, da die Handlung zweimal gezeichnet wird. (ZB Schwenken wird langsam ). Es ist möglich, das zu umgehen, aber ich werde diese Beispiele für ein anderes Mal verlassen.

Dies implementiert das Hinzufügen von Punkten, das Ziehen von Punkten und das Löschen von Punkten. Um einen Punkt nach dem interaktiven Zoomen / Schwenken hinzuzufügen / zu ziehen, klicken Sie erneut auf die Werkzeugleiste, um sie zu vergrößern / zu verschieben.

Dies ist ein ziemlich komplexes Beispiel, aber hoffentlich gibt es einen Sinn für die Art von Framework, die man typischerweise bauen würde, um matplotlib Künstler interaktiv zu zeichnen / zu ziehen / zu bearbeiten / zu löschen, ohne das gesamte Plot neu zu zeichnen.

 import numpy as np import matplotlib.pyplot as plt class DrawDragPoints(object): """ Demonstrates a basic example of the "scaffolding" you need to efficiently blit drawable/draggable/deleteable artists on top of a background. """ def __init__(self): self.fig, self.ax = self.setup_axes() self.xy = [] self.tolerance = 10 self._num_clicks = 0 # The artist we'll be modifying... self.points = self.ax.scatter([], [], s=200, color='red', picker=self.tolerance, animated=True) connect = self.fig.canvas.mpl_connect connect('button_press_event', self.on_click) self.draw_cid = connect('draw_event', self.grab_background) def setup_axes(self): """Setup the figure/axes and plot any background artists.""" fig, ax = plt.subplots() # imshow would be _much_ faster in this case, but let's deliberately # use something slow... ax.pcolormesh(np.random.random((1000, 1000)), cmap='gray') ax.set_title('Left click to add/drag a point\nRight-click to delete') return fig, ax def on_click(self, event): """Decide whether to add, delete, or drag a point.""" # If we're using a tool on the toolbar, don't add/draw a point... if self.fig.canvas.toolbar._active is not None: return contains, info = self.points.contains(event) if contains: i = info['ind'][0] if event.button == 1: self.start_drag(i) elif event.button == 3: self.delete_point(i) else: self.add_point(event) def update(self): """Update the artist for any changes to self.xy.""" self.points.set_offsets(self.xy) self.blit() def add_point(self, event): self.xy.append([event.xdata, event.ydata]) self.update() def delete_point(self, i): self.xy.pop(i) self.update() def start_drag(self, i): """Bind mouse motion to updating a particular point.""" self.drag_i = i connect = self.fig.canvas.mpl_connect cid1 = connect('motion_notify_event', self.drag_update) cid2 = connect('button_release_event', self.end_drag) self.drag_cids = [cid1, cid2] def drag_update(self, event): """Update a point that's being moved interactively.""" self.xy[self.drag_i] = [event.xdata, event.ydata] self.update() def end_drag(self, event): """End the binding of mouse motion to a particular point.""" for cid in self.drag_cids: self.fig.canvas.mpl_disconnect(cid) def safe_draw(self): """Temporarily disconnect the draw_event callback to avoid recursion""" canvas = self.fig.canvas canvas.mpl_disconnect(self.draw_cid) canvas.draw() self.draw_cid = canvas.mpl_connect('draw_event', self.grab_background) def grab_background(self, event=None): """ When the figure is resized, hide the points, draw everything, and update the background. """ self.points.set_visible(False) self.safe_draw() # With most backends (eg TkAgg), we could grab (and refresh, in # self.blit) self.ax.bbox instead of self.fig.bbox, but Qt4Agg, and # some others, requires us to update the _full_ canvas, instead. self.background = self.fig.canvas.copy_from_bbox(self.fig.bbox) self.points.set_visible(True) self.blit() def blit(self): """ Efficiently update the figure, without needing to redraw the "background" artists. """ self.fig.canvas.restore_region(self.background) self.ax.draw_artist(self.points) self.fig.canvas.blit(self.fig.bbox) def show(self): plt.show() DrawDragPoints().show() 
  • Gibt es eine Möglichkeit, gleiche Längen-Arrays in numpy.hist zurückzugeben?
  • Handlung und Std. Dev Bei bestimmten stündlichen Zecken mit Pandas
  • Matplotlib 3d scatter plot datum
  • Zweck der 'ax' Schlüsselwort in pandas scatter_matrix Funktion
  • Matplotlib zeichnen Außenplot (zwei Skalen)
  • Python, Matplotlib, Plot Multi-Linien (Array) und Animation
  • Heat Map Annotation mit Text
  • Matplotlib-Fenster erscheint auf der Rückseite?
  • Erzeugen von Konturdiagrammen für X, Y-Daten in Python
  • Parallele Koordinaten mit übersprungenen Koordinaten
  • Annotate Bars mit Werten auf Pandas Bar Plots
  • Python ist die beste Programmiersprache der Welt.