2013-07-09 18 views
15

sto disegnando due sottotrame con Matplotlib, a seguito essenzialmente:Disegno di linee tra due trame in Matplotlib

subplot(211); imshow(a); scatter(..., ...) 
subplot(212); imshow(b); scatter(..., ...) 

Posso tracciare linee tra queste due sottotrame? Come potrei farlo?

+1

sospetta che si può fare questo con 'annotate'. – tacaswell

risposta

6

La soluzione dalle altre risposte sono non ottimale in molti casi (come sarebbero funziona solo se non vengono apportate modifiche alla trama dopo il calcolo dei punti).

Una soluzione migliore sarebbe usare il appositamente progettato ConnectionPatch:

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

fig = plt.figure(figsize=(10,5)) 
ax1 = fig.add_subplot(121) 
ax2 = fig.add_subplot(122) 

x,y = np.random.rand(100),np.random.rand(100) 

ax1.plot(x,y,'ko') 
ax2.plot(x,y,'ko') 

i = 10 
xy = (x[i],y[i]) 
con = ConnectionPatch(xyA=xy, xyB=xy, coordsA="data", coordsB="data", 
         axesA=ax2, axesB=ax1, color="red") 
ax2.add_artist(con) 

ax1.plot(x[i],y[i],'ro',markersize=10) 
ax2.plot(x[i],y[i],'ro',markersize=10) 


plt.show() 

enter image description here

+0

Buon punto. Questo in realtà funziona molto meglio della risposta precedentemente accettata, quindi accetterò invece. Grazie! –

+0

Vale la pena di commentare perché "ax2.add_artist" è su "ax2" piuttosto che su "ax1" github.com/matplotlib/matplotlib/issues/8744 e perché "axesA" è impostato su "ax2" – Joel

22

È possibile utilizzare fig.line. Aggiunge qualsiasi linea alla tua figura. Le linee delle figure sono di livello superiore rispetto alle linee degli assi, quindi non è necessario alcun asse per disegnarlo.

Questo esempio indica lo stesso punto sui due assi. È necessario stare attenti con il sistema di coordinate, ma la trasformazione fa tutto il lavoro duro per te.

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

fig = plt.figure(figsize=(10,5)) 
ax1 = fig.add_subplot(121) 
ax2 = fig.add_subplot(122) 

x,y = np.random.rand(100),np.random.rand(100) 

ax1.plot(x,y,'ko') 
ax2.plot(x,y,'ko') 

i = 10 

transFigure = fig.transFigure.inverted() 

coord1 = transFigure.transform(ax1.transData.transform([x[i],y[i]])) 
coord2 = transFigure.transform(ax2.transData.transform([x[i],y[i]])) 


line = matplotlib.lines.Line2D((coord1[0],coord2[0]),(coord1[1],coord2[1]), 
           transform=fig.transFigure) 
fig.lines = line, 

ax1.plot(x[i],y[i],'ro',markersize=20) 
ax2.plot(x[i],y[i],'ro',markersize=20) 


plt.show() 

enter image description here

+5

probabilmente meglio fare "fig.lines.append (linea)" per non soffiare via nulla già lì. – tacaswell

+0

L'esempio è molto apprezzato, ho avuto difficoltà a capire quale trasformazione di Matplotlib è andata dove prima! @tcaswell ha ragione, ho appena cercato [docs] (http://matplotlib.org/users/annotations_guide.html#using-connectorpatch) su 'annotate', e' ConnectorPatch' sembra essere esattamente quello che sono cercando, quindi proverò e tornerò più tardi! –

+0

Soluzione molto bella. Tuttavia ho ottenuto la linea tracciata con coordinate errate con jupyter. La soluzione era aggiungere 'fig.canvas.draw()' prima di chiamare 'transFigure = fig.transFigure.inverted()' per lavorare con le coordinate corrette. – scholi

1

io non sono sicuro se questo è esattamente quello che stai cercando, ma un semplice trucco per tracciare attraverso sottotrame.

import matplotlib.pyplot as plt 
import numpy as np 

ax1=plt.figure(1).add_subplot(211) 
ax2=plt.figure(1).add_subplot(212) 

x_data=np.linspace(0,10,20) 
ax1.plot(x_data, x_data**2,'o') 
ax2.plot(x_data, x_data**3, 'o') 

ax3 = plt.figure(1).add_subplot(111) 
ax3.plot([5,5],[0,1],'--') 
ax3.set_xlim([0,10]) 
ax3.axis("off") 
plt.show() 
Problemi correlati