はじめに
この実験では、matplotlib のパッチにマウスオーバーしたときに表示されるツールチップを作成する方法についての手順を追ったチュートリアルです。matplotlib でツールチップを作成し、パッチにマウスオーバーしたときにその表示を切り替えるだけです。このアプローチは、事前にコードをもう少し多く書く代わりに、ツールチップの配置と外観を完全に制御できます。
VM のヒント
VM の起動が完了したら、左上隅をクリックしてノートブックタブに切り替え、Jupyter Notebook を使って練習しましょう。
場合によっては、Jupyter Notebook が読み込み終わるまで数秒待つ必要があります。Jupyter Notebook の制限により、操作の検証を自動化することはできません。
学習中に問題がある場合は、Labby にお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。
パッチを作成する
まず、ツールチップが割り当てられるパッチを作成します。
rect1 = plt.Rectangle((10, -20), 10, 5, fc='blue')
rect2 = plt.Rectangle((-20, 15), 10, 5, fc='green')
shapes = [rect1, rect2]
labels = ['This is a blue rectangle.', 'This is a green rectangle']
パッチとツールチップの注釈を追加する
次に、パッチとツールチップの注釈をプロットに追加します。ツールチップの注釈は、annotate メソッドを使用して作成されます。xy パラメータをパッチの座標に設定し、xytext を (0, 0) に設定して、ツールチップをパッチの真上に配置します。また、textcoords パラメータを 'offset points' に設定して、ツールチップをパッチに合わせて整列させます。color パラメータを 'w' に設定してテキストを白に、ha を 'center' に設定してテキストを水平方向に中央揃え、fontsize を 8 に設定してフォントサイズを設定し、bbox を設定してツールチップボックスのスタイルを設定します。
for i, (item, label) in enumerate(zip(shapes, labels)):
patch = ax.add_patch(item)
annotate = ax.annotate(labels[i], xy=item.get_xy(), xytext=(0, 0),
textcoords='offset points', color='w', ha='center',
fontsize=8, bbox=dict(boxstyle='round, pad=.5',
fc=(.1,.1,.1,.92),
ec=(1., 1., 1.), lw=1,
zorder=1))
ax.add_patch(patch)
patch.set_gid(f'mypatch_{i:03d}')
annotate.set_gid(f'mytooltip_{i:03d}')
グラフを SVG 形式で保存する
BytesIO クラスと savefig メソッドを使って、グラフを偽のファイルオブジェクトに保存します。
ax.set_xlim(-30, 30)
ax.set_ylim(-30, 30)
ax.set_aspect('equal')
f = BytesIO()
plt.savefig(f, format="svg")
インタラクティビティを追加する
パッチにマウスオーバーしたときに表示と非表示が切り替わるツールチップを作成することで、プロットにインタラクティビティを追加します。これは、SVG ファイルから XML ツリーを作成し、ツールチップを非表示にし、パッチに onmouseover と onmouseout のコールバックを割り当てることで行います。また、パッチにマウスオーバーしたときに呼び出される ShowTooltip と HideTooltip 関数も定義します。
tree, xmlid = ET.XMLID(f.getvalue())
tree.set('onload', 'init(event)')
for i in shapes:
## Get the index of the shape
index = shapes.index(i)
## Hide the tooltips
tooltip = xmlid[f'mytooltip_{index:03d}']
tooltip.set('visibility', 'hidden')
## Assign onmouseover and onmouseout callbacks to patches.
mypatch = xmlid[f'mypatch_{index:03d}']
mypatch.set('onmouseover', "ShowTooltip(this)")
mypatch.set('onmouseout', "HideTooltip(this)")
## This is the script defining the ShowTooltip and HideTooltip functions.
script = """
<script type="text/ecmascript">
<![CDATA[
function init(event) {
if ( window.svgDocument == null ) {
svgDocument = event.target.ownerDocument;
}
}
function ShowTooltip(obj) {
var cur = obj.id.split("_")[1];
var tip = svgDocument.getElementById('mytooltip_' + cur);
tip.setAttribute('visibility', "visible")
}
function HideTooltip(obj) {
var cur = obj.id.split("_")[1];
var tip = svgDocument.getElementById('mytooltip_' + cur);
tip.setAttribute('visibility', "hidden")
}
]]>
</script>
"""
## Insert the script at the top of the file and save it.
tree.insert(0, ET.XML(script))
ET.ElementTree(tree).write('svg_tooltip.svg')
まとめ
この実験では、matplotlib のパッチにマウスオーバーしたときに表示されるツールチップを作成する方法を学びました。matplotlib でツールチップを作成し、パッチにマウスオーバーしたときにその表示を切り替えるだけで済みました。また、パッチにマウスオーバーしたときに表示と非表示が切り替わるツールチップを作成することで、プロットにインタラクティビティを追加しました。