2013-05-13 16 views
10

Ispirato da this example Sto provando a scrivere un piccolo programma matplotlib che consente all'utente di trascinare e rilasciare i punti dati in un diagramma a dispersione in modo dinamico. In contrasto con l'esempio che utilizza un grafico a barre (e quindi consente il trascinamento di rettangoli) il mio obiettivo era quello di ottenere lo stesso risultato con altre patch, come ad esempio un cerchio (qualsiasi patch più compatibile con lo scatter-plot di un rettangolo). Tuttavia sono bloccato al punto di aggiornare la posizione della mia patch. Mentre un Rectangle fornisce una funzione set_xy Non riesco a trovare un analogico diretto per Cirlce o Ellipse. Ottenere la posizione di un cerchio è anche meno diretto che per un rettangolo, ma è possibile ottenendo il rettangolo di selezione. Il pezzo mancante ora è trovare un modo per aggiornare la posizione della mia patch. Qualsiasi suggerimento su come ottenere questo sarebbe fantastico! L'attuale esempio di lavoro minima sarebbe simile a questa:matplotlib: aggiornamento posizione delle patch (o: set_xy per cerchi)

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.patches as patches 

class DraggablePatch: 

    def __init__(self, patch): 
    self.patch = patch 
    self.storedPosition = None 
    self.connect() 

    def getPosOfPatch(self, marker): 
    ext = marker.get_extents().get_points() 
    x0 = ext[0,0] 
    y0 = ext[0,1] 
    x1 = ext[1,0] 
    y1 = ext[1,1] 
    return 0.5*(x0+x1), 0.5*(y0+y1) 

    def connect(self): 
    'connect to all the events we need' 
    self.cidpress = self.patch.figure.canvas.mpl_connect('button_press_event', self.onPress) 
    self.cidmotion = self.patch.figure.canvas.mpl_connect('motion_notify_event', self.onMove) 

    def onPress(self, event): 
    'on button press we will see if the mouse is over us and store some data' 
    contains, attrd = self.patch.contains(event) 
    if contains: 
     self.storedPosition = self.getPosOfPatch(self.patch), event.xdata, event.ydata 

    def onMove(self, event): 
    'how to update an circle?!' 
    contains, attrd = self.patch.contains(event) 
    if contains and self.storedPosition is not None: 
     oldPos, oldEventXData, oldEventYData = self.storedPosition 
     dx = event.xdata - oldEventXData 
     dy = event.ydata - oldEventYData 
     newX = oldPos[0] + dx 
     newY = oldPos[1] + dy 
     print "now I would like to move my patch to", newX, newY 


def myPatch(x,y): 
    return patches.Circle((x,y), radius=.05, alpha=0.5) 

N = 10 
x = np.random.random(N) 
y = np.random.random(N) 
patches = [myPatch(x[i], y[i]) for i in range(N)] 

fig = plt.figure() 
ax = fig.add_subplot(111) 
drs = [] 
for patch in patches: 
    ax.add_patch(patch) 
    dr = DraggablePatch(patch) 
    drs.append(dr) 

plt.show() 

risposta

11

E 'un po' fastidioso che è incoerente, ma per aggiornare la posizione di un cerchio, impostare circ.center = new_x, new_y.

Come semplice esempio (non trascinabili):

import matplotlib.pyplot as plt 
from matplotlib.patches import Circle 

class InteractiveCircle(object): 
    def __init__(self): 
     self.fig, self.ax = plt.subplots() 
     self.ax.axis('equal') 

     self.circ = Circle((0.5, 0.5), 0.1) 
     self.ax.add_artist(self.circ) 
     self.ax.set_title('Click to move the circle') 

     self.fig.canvas.mpl_connect('button_press_event', self.on_click) 

    def on_click(self, event): 
     if event.inaxes is None: 
      return 
     self.circ.center = event.xdata, event.ydata 
     self.fig.canvas.draw() 

    def show(self): 
     plt.show() 


InteractiveCircle().show() 
+0

La ringrazio molto, che ha fatto il trucco! Poiché sostengo sempre il concetto RTFM, mi chiedo dove posso trovare queste informazioni? Non riesco a vederlo in [patches.Circle] (http://matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib.patches.Circle), [patches.Ellipse] (http: // matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib.patches.Ellipse), [patches.Patch] (http://matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib .patches.Patch) o [artist.Artist] (http://matplotlib.org/api/artist_api.html?highlight=patches.circle#matplotlib.artist.Artist). – bluenote10

+2

Sfortunatamente, non è documentato. Ho dovuto scavare attraverso il codice per trovarlo ('ipython' è anche un grande aiuto). Questi tipi di "angoli" di matplotlib necessitano sicuramente di una documentazione migliore ... –

+0

@JoeKington Quindi, come faccio a fare questo per un arco? Non voglio spostare il suo centro piuttosto voglio cambiare il suo inizio e fine theta cioè la diffusione dell'arco. –

Problemi correlati