2017-02-27 67 views
2

我有點困惑matplotlib座標系(使用Jupyter筆記本進行交互式動畫)。如果你創建一個補丁,說一個圓,並使用set_transform()進行翻譯,我發現這個變換不是持久的,這意味着如果你再次使用相同的(x,y)變換來應用變換,圓不會因爲看起來Circle 位置在轉換後未得到更新,所以後續轉換應用於相同的原始色塊位置。我的問題是如何應用轉換,實際上不僅在應用後移動修補程序,還更新修補程序位置?假設我想要應用一系列翻譯,那麼圈子應該四處移動,而不是從原始位置來回擺動。以下是一個示例代碼:如何將永久座標轉換應用於Matplotlib補丁?

%import matplotlib 
%matplotlib notebook 

fig = plt.figure() 
ax = fig.add_subplot(111, xlim=(-10, 10), ylim=(-10, 10)) 
c = ax.add_patch(plt.Circle((x, y), radius=0.5) 
c.set_transform(ax.transData + mpl.transforms.Affine2D().translate(-5,-5)) 
c.set_transform(ax.transData + mpl.transforms.Affine2D().translate(10,10)) 

如果您運行此操作,您會看到註釋掉第一個翻譯不會影響該圓的最終位置。我會預料到,圓心的最終位置是(5,5)NOT(10,10)。這意味着轉換不會實際更新補丁(圓)位置;它只是在圖形/軸上翻譯它。

問題2:我感到迷惑另一件事是,由代碼產生圈之上似乎有0.5的半徑的要求,但是通過(10,10)施加一個翻譯後它被翻譯少得多在圖中!就好像翻譯過程在應用之前被縮小了一些因素!!我沒有解釋這一點,它只是表明我不明白matplotlib座標系和轉換。另一方面,由plot()生成的作爲Line2D對象的對象可以通過set_data()方法進行轉換,該方法按如下方式更新對象的位置(假設來自上面代碼段的fig和ax對象) :

L, = ax.plot(0, 0, 'ro', ms=8) 
sx = 10 # shift in x 
sy = 10 # shift in y 
L.set_data(L.get_data()[0] + sx, L.get_data()[1] + sy) 

我不知道如何做相同的matplotlib補丁?

+0

你看過http://matplotlib.org/users/transforms_tutorial.html嗎? –

+0

對於問題1的第一部分,'set_transform'不會追加變換。它重置整個矩陣。這意味着'c.set_transform(ax.transData + mpl.transforms.Affine2D()。translate(10,10))'之前的任何內容都將被有效地忽略。 –

回答

3

The ax.transData transform將數據座標轉換爲顯示座標。

將變換一起添加時,它們從左到右應用。所以

ax.transData + mpl.transforms.Affine2D().translate(-5,-5) 

從數據首先將顯示座標,然後通過的 偏移平移(-5,-5)在顯示座標(像素)。

相反,

mpl.transforms.Affine2D().translate(-5,-5) + ax.transData 

將由第一移位(-5,-5)數據座標,然後轉換數據座標到顯示座標。


由於變換可通過加入組成,以更新的變換使用

transform = transform + mpl.transforms.Affine2D().translate(...) 

例如,

import matplotlib.pyplot as plt 
import matplotlib as mpl 

fig = plt.figure() 
ax = fig.add_subplot(111, xlim=(-10, 10), ylim=(-10, 10)) 
x, y = 0, 0 
c = ax.add_patch(plt.Circle((x, y), radius=5)) 
transform = mpl.transforms.Affine2D().translate(-5,-5) 
transform += mpl.transforms.Affine2D().translate(10,10) 
c.set_transform(transform+ax.transData) 
ax.set_aspect('equal') 
plt.show() 

enter image description here

圓的中心在(5,5)如預期的那樣,因爲(x,y)+(-5,-5)+(10,10) = (5,5)

或者,您可以計算(或跟蹤)一系列偏移量,並根據需要生成變換,而不是編寫變換。有關此方法的示例,請參閱this post


還要注意,變換不應用直到補丁被呈現(例如,通過調用plt.show())。這解釋了爲什麼c.set_transform的多個呼叫與對c.set_transform的單個呼叫具有相同的效果。只有最後一個轉換被應用到補丁。

補丁,c,商店,你可以訪問使用c.get_transform私有屬性的單一變換:

In [10]: c.get_transform() 
Out[15]: 
CompositeGenericTransform(Affine2D(array([[ 5., 0., 0.], 
     [ 0., 5., 0.], 
     [ 0., 0., 1.]])), CompositeGenericTransform(TransformWrapper(BlendedAffine2D(IdentityTransform(),IdentityTransform())), CompositeGenericTransform(BboxTransformFrom(TransformedBbox(Bbox([[-10.0, -10.0], [10.0, 10.0]]), TransformWrapper(BlendedAffine2D(IdentityTransform(),IdentityTransform())))), BboxTransformTo(TransformedBbox(Bbox([[0.125, 0.09999999999999998], [0.9, 0.9]]), BboxTransformTo(TransformedBbox(Bbox([[0.0, 0.0], [6.4, 4.8]]), Affine2D(array([[ 100., 0., 0.], 
     [ 0., 100., 0.], 
     [ 0., 0., 1.]]))))))))) 

c.set_transform重新分配私有屬性到一個新的轉變。但是,直到plt.show()或其他一些渲染調用(如plt.savefig)製作完成後纔會應用變換。

+0

是的,[Transformations Tutorial](http://matplotlib.org/users/transforms_tutorial.html)是任何想要操作變換的人必讀的。 – unutbu

+0

謝謝。我會閱讀你鏈接的頁面。對我來說,這裏的大細節是Display vs Data(如果我可以稱之爲),座標。但是,您確認這些轉換僅適用於渲染補丁,但實際上並未更新補丁「位置」或座標。 – Kai

+0

正確。一個變換(當前變換,由'c.get_transform()'返回的變換)在渲染時應用。 – unutbu