2017-02-27 10 views
2

私はmatplotlib座標系(インタラクティブなアニメーションのためにJupyterノートブックで使用しています)で少し混乱しています。 set_transform()を使用してパッチを作成してサークルを翻訳し、それを翻訳すると、変換が永続的ではないことがわかります。つまり、同じ(x、y)シフトで変換を再度適用すると、サークルは円ポジションが変換後に更新されないように見えるので、次の変換が同じ元のパッチ位置に適用されるため、移動します。私の質問は、実際に適用された後に実際にパッチを移動するだけでなく、パッチの位置も更新する変換を適用する方法です。一連の翻訳を適用したいとしたら、円は元の位置から前後に動かないようにしてください。ここではサンプルコードです: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)であると予想していたでしょう。つまり、変換によって実際にパッチ(円)の位置は更新されません。 Figure/Axesで変換します。

質問2:私は混乱を見つけるもう一つは、要求されるように、コードによって生成円は上記のそれははるかに少ない翻訳されしかし、(10,10)で翻訳を適用した後、0.5の半径を持っているように見えるということです図の中に!!あたかも翻訳シフトが適用される前に何らかの要素によって縮小されたかのように!私はこれについて何の説明もなく、matplotlib座標系と変換を理解していないことを示しています。

一方Line2Dオブジェクトであるplot()によって生成されたオブジェクトは、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 

は、第1のデータに座標(-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への1回のコールと同じ効果を持つのかを説明します。最後の変換のみがパッチに適用されます。

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新にプライベート属性変換することを再割り当て:

パッチ、cは、単一あなたがc.get_transformを使用してアクセスできるプライベート属性に変換を格納します。しかし、plt.show()plt.savefigのような他のレンダリングコールが行われるまで、変換は適用されません。

+0

はい、[トランスフォーメーションチュートリアル](http://matplotlib.org/users/transforms_tutorial.html)は、トランスフォームを操作したい人にとっては必読です。 – unutbu

+0

ありがとうございます。リンクしたページを読んでいます。私にとってここまでの大きなディテールは、Display vs Data(それを私がそれと呼んでもよい)の座標です。しかし、これらの変換がパッチのレンダリングにのみ適用されることを確認していますが、実際にはパッチの「位置」または座標を更新しません。 – Kai

+0

修正。単一の変換(現在の変換、 'c.get_transform()'によって返された変換)がレンダリングの瞬間に適用されます。 – unutbu

関連する問題