matplotlibでtransformを指定したpatchをadd_patchすると親axesの座標系を無視する
matplotlibでpatchにtransformをつけると消えてしまうように見える現象が起きた。
まず、散布図の上に普通に長方形のpatchを乗せてみる。
clf() scatter(random(100), random(100)) ax = gca() rect = Rectangle((0, 0), 1, 1, alpha=0.3) ax.add_patch(rect) matplotlib.pyplot.savefig("test.png", dpi=100)
ここまではとても自然にできる。じゃあこの長方形を回転してみよう、とtransformを指定すると消えてしまう。transformの作り方がまずいのかと思ったがAffine2D.identity()でも消えてしまう。
clf() scatter(random(100), random(100)) ax = gca() t = Affine2D.identity() rect = Rectangle((0, 0), 1, 1, transform=t, alpha=0.3) ax.add_patch(rect) matplotlib.pyplot.savefig("test.png", dpi=100)
問題解決の鍵は前回(matplotlibのPatchCollectionは子パッチの色を上書きする)同様、patch自体ではなくその上にあった。
Definition: ax.add_patch(self, p) Docstring: Add a :class:`~matplotlib.patches.Patch` *p* to the list of axes patches; the clipbox will be set to the Axes clipping box. If the transform is not set, it will be set to :attr:`transData`.
つまりpatchにtransformを指定してadd_patchすると親axesの座標系を無視してしまう。っていうわけで今回の例で言えばtransformを指定しないときには散布図の軸に従った座標系で0〜1の範囲にあったものが、単位行列をtransformに指定したことで図のグローバル座標系になってしまっているわけだ。そして散布図のクリッピングの外なので消えてしまっている。長方形のサイズを100x100にしてみるとちょこっと頭を出す:「やあ、僕はここだよ!」
rect = Rectangle((0, 0), 100, 100, transform=t, alpha=0.3)
じゃあax.transDataをtransformに指定すればいいわけね。
t = ax.transData rect = Rectangle((0, 0), 1, 1, transform=t, alpha=0.3)
コレは期待通りの結果だったので省略。じゃあ早速回転してみよう。
for i in range(5): t = CompositeGenericTransform(Affine2D.identity().rotate(0.1 * i), ax.transData) rect = Rectangle((0, 0), 1, 1, transform=t, alpha=0.3) ax.add_patch(rect)
できたできた。めでたしめでたし。でも、本当にCompositeGenericTransformなんか使わないといけないのだろうか。もっと楽な方法があるんじゃないかなぁ。
追記。とりあえずidentityは使わなくてもAffine2D()で単位行列になるみたい。