Ich brauche einen ziehbaren Datenmarker, um eine Reihe von Punkten in einem Datensatz manuell anzupassen. This Antwort und andere lösen dieses Problem mit einem Patch.Circle. Allerdings muss der Marker beim Zoomen des Plots gleich groß bleiben. Mit Kreisen zoomt der Kreis auch. Ich habe nicht versucht, mit jedem neuen Zoom dynamisch die Größe des Kreises zu ändern, weil es so aussieht, als ob man einen Marker einfacher bewegen könnte. Weiß jemand, wie man das macht?Matplotlib ziehbare Datenmarker
Antwort
Unten, ich präsentiere eine MWE, die eine Möglichkeit zeigt, es mit der objektorientierten API von Matplotlib und PyQt4 zu tun. Die Datenmarker sind mit der mittleren Maustaste ziehbar. Die Strategie besteht darin, Ihre Daten mit einem line2D-Künstler zu zeichnen und anschließend die Marker zu ziehen, indem Sie die Daten des Künstlers manipulieren und den Plot aktualisieren. Dies lässt sich grob in 3 Schritten zusammenfassen:
Schritt 1 - Wenn die mittlere Maustaste angeklickt wird, werden die Koordinaten des Mauscursors in Pixel mit den xy-Daten des line2D-Künstlers in Pixeln verglichen. Wenn der lineare Abstand zwischen dem Cursor und dem nächsten Marker kleiner als ein bestimmter Wert ist (hier definiert als die Größe der Marker), wird der Index dieses Datenmarkers im Klassenattribut draggable
gespeichert. Andernfalls wird draggable
auf None
festgelegt.
Schritt 2 - Wenn die Maus bewegt wird, wenn draggable is not None
, die Koordinate der Datenmarkierung, deren Index in dem Klassenattribut gespeichert wurde draggable
sind zu denjenigen des Mauszeigers eingestellt.
Schritt 3 - Wenn die mittlere Maustaste losgelassen wird, wird draggable
auf None zurückgesetzt.
Hinweis: Falls gewünscht, ist es auch möglich, die pyplot-Schnittstelle zu verwenden, um die Abbildung anstelle der objektorientierten API zu generieren.
import sys
from PyQt4 import QtGui
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
from matplotlib.backends.backend_qt4agg import FigureManagerQT
import numpy as np
class MyFigureCanvas(FigureCanvasQTAgg):
def __init__(self):
super(MyFigureCanvas, self).__init__(Figure())
# init class attributes:
self.background = None
self.draggable = None
self.msize = 6
# plot some data:
x = np.random.rand(25)
self.ax = self.figure.add_subplot(111)
self.markers, = self.ax.plot(x, marker='o', ms=self.msize)
# define event connections:
self.mpl_connect('motion_notify_event', self.on_motion)
self.mpl_connect('button_press_event', self.on_click)
self.mpl_connect('button_release_event', self.on_release)
def on_click(self, event):
if event.button == 2: # 2 is for middle mouse button
# get mouse cursor coordinates in pixels:
x = event.x
y = event.y
# get markers xy coordinate in pixels:
xydata = self.ax.transData.transform(self.markers.get_xydata())
xdata, ydata = xydata.T
# compute the linear distance between the markers and the cursor:
r = ((xdata - x)**2 + (ydata - y)**2)**0.5
if np.min(r) < self.msize:
# save figure background:
self.markers.set_visible(False)
self.draw()
self.background = self.copy_from_bbox(self.ax.bbox)
self.markers.set_visible(True)
self.ax.draw_artist(self.markers)
self.update()
# store index of draggable marker:
self.draggable = np.argmin(r)
else:
self.draggable = None
def on_motion(self, event):
if self.draggable is not None:
if event.xdata and event.ydata:
# get markers coordinate in data units:
xdata, ydata = self.markers.get_data()
# change the coordinate of the marker that is
# being dragged to the ones of the mouse cursor:
xdata[self.draggable] = event.xdata
ydata[self.draggable] = event.ydata
# update the data of the artist:
self.markers.set_xdata(xdata)
self.markers.set_ydata(ydata)
# update the plot:
self.restore_region(self.background)
self.ax.draw_artist(self.markers)
self.update()
def on_release(self, event):
self.draggable = None
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
canvas = MyFigureCanvas()
manager = FigureManagerQT(canvas, 1)
manager.show()
sys.exit(app.exec_())
Das funktioniert super! Vielen Dank! – martinako
Ich frage mich, ob es einen Vorteil gibt, den on_click() in Pixelkoordinaten zu berechnen, um ihn in Datenkoordinaten zu berechnen (wie in on_motion()). Wenn Sie mit Datenkoordinaten in on_click() arbeiten, müssen Sie die Datenkoordinaten nicht in Pixelkoordinaten umwandeln. In jedem Fall ist es für pädagogische Zwecke gut, beide Verwendungen zu sehen :-) – martinako
@martinako Pixelkoordinaten ermöglichen die Berechnung linearer Abstände, die unabhängig von den Skalen der x- und y-Achse sind. Sonst müssten wir die xy-Daten sowieso transformieren, um zu berücksichtigen, dass beide Achsen nicht die gleiche Skalierung haben und auch beim Heraus- und Hineinzoomen berücksichtigen. –
- 1. jquery ziehbare
- 2. Ziehbare Objektkollision
- 3. Berechne ziehbare divs - jquery
- 4. Javascript ziehbare Ausgabe
- 5. Zerstöre JQuery ziehbare
- 6. jQuery ziehbare scrollbare Container
- 7. jQuery auf ziehbare Änderungsachse
- 8. Android MapView ziehbare Marker
- 9. Ziehbare, abwerfbaren und sortierbar
- 10. jQuery ziehbare Positionswerte
- 11. Jquery ziehbare und Klon
- 12. HTML5 UL LI Ziehbare
- 13. jquery ziehbare Optionen
- 14. JQuery Ziehbare/Live
- 15. JQuery ziehbare divs
- 16. jquery sortierbare/ziehbare Bug
- 17. Plotly bewegliche/ziehbare Legenden, Python
- 18. Jquery ui ziehbare mobile Version
- 19. Ziehbare Datenpunkte in Excel 2007?
- 20. So verbinden Sie ziehbare divs
- 21. MKMapKit ziehbare Annotations- und Zeichenpolygone
- 22. ziehbare xml Form Farbwechsel dyanamisch
- 23. Ziehen Sie ziehbare Objekte ineinander
- 24. jQuery: Mehrere ziehbare und Droppables?
- 25. Ändern EditText setError ziehbare Schwerkraft
- 26. Google map api ziehbare Marker
- 27. Jquery UI ziehbare Startfunktion Code
- 28. append ziehbare an container jquery
- 29. ziehbare und dropable jquery socket.io
- 30. jquery Layout und dynamisch ziehbare div Problem
Sie möchten die Position des Patches werden in Daten, aber die Größe des Patch-Koordinaten Koordinaten werden in Achsen? – cphlewis