はじめに
データ可視化において、プロットの特定の領域を拡大することは、データをよりよく理解し分析するために非常に役立ちます。Python 用の人気のあるデータ可視化ライブラリである Matplotlib は、2 つの同じパネルを作成し、右パネルを拡大して最初のパネルに矩形を表示して、拡大領域を示す方法を提供します。この実験では、Matplotlib でこのインタラクティブな拡大機能を作成する方法を学びます。
VM のヒント
VM の起動が完了したら、左上隅をクリックして ノートブック タブに切り替えて、Jupyter Notebook を使って練習します。
時々、Jupyter Notebook が読み込み終了するまで数秒待つ必要がある場合があります。Jupyter Notebook の制限により、操作の検証は自動化できません。
学習中に問題に直面した場合は、Labby にお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。
必要なライブラリをインポートする
まず、Matplotlib と NumPy を含む必要なライブラリをインポートします。
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
UpdatingRect クラスを作成する
Rectangle のサブクラスである UpdatingRect を作成します。このクラスは Axes インスタンスを引数に呼び出されると、矩形の形状を Axes の範囲に合わせて更新します。
class UpdatingRect(Rectangle):
def __call__(self, ax):
self.set_bounds(*ax.viewLim.bounds)
ax.figure.canvas.draw_idle()
MandelbrotDisplay クラスを作成する
ズームインするときにフラクタル集合を再生成し、実際に増えていく詳細を見ることができる MandelbrotDisplay というクラスを作成します。左パネルのボックスがズームしている領域を示します。
class MandelbrotDisplay:
def __init__(self, h=500, w=500, niter=50, radius=2., power=2):
self.height = h
self.width = w
self.niter = niter
self.radius = radius
self.power = power
def compute_image(self, xstart, xend, ystart, yend):
self.x = np.linspace(xstart, xend, self.width)
self.y = np.linspace(ystart, yend, self.height).reshape(-1, 1)
c = self.x + 1.0j * self.y
threshold_time = np.zeros((self.height, self.width))
z = np.zeros(threshold_time.shape, dtype=complex)
mask = np.ones(threshold_time.shape, dtype=bool)
for i in range(self.niter):
z[mask] = z[mask]**self.power + c[mask]
mask = (np.abs(z) < self.radius)
threshold_time += mask
return threshold_time
def ax_update(self, ax):
ax.set_autoscale_on(False)
self.width, self.height = \
np.round(ax.patch.get_window_extent().size).astype(int)
vl = ax.viewLim
extent = vl.x0, vl.x1, vl.y0, vl.y1
im = ax.images[-1]
im.set_data(self.compute_image(*extent))
im.set_extent(extent)
ax.figure.canvas.draw_idle()
プロットを作成する
まず MandelbrotDisplay クラスを使って画像を計算し、その後サブプロットを使って 2 つの同じパネルを作成することでプロットを作成します。imshow を使って両方のパネルに画像を追加し、左パネルに UpdatingRect オブジェクトを追加します。
md = MandelbrotDisplay()
Z = md.compute_image(-2., 0.5, -1.25, 1.25)
fig1, (ax1, ax2) = plt.subplots(1, 2)
ax1.imshow(Z, origin='lower',
extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max()))
ax2.imshow(Z, origin='lower',
extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max()))
rect = UpdatingRect(
[0, 0], 0, 0, facecolor='none', edgecolor='black', linewidth=1.0)
rect.set_bounds(*ax2.viewLim.bounds)
ax1.add_patch(rect)
ズーム機能を追加する
xlim_changed と ylim_changed イベントを UpdatingRect と MandelbrotDisplay オブジェクトに接続することで、ズーム機能を追加します。
ax2.callbacks.connect('xlim_changed', rect)
ax2.callbacks.connect('ylim_changed', rect)
ax2.callbacks.connect('xlim_changed', md.ax_update)
ax2.callbacks.connect('ylim_changed', md.ax_update)
ax2.set_title("Zoom here")
プロットを表示する
show() 関数を使ってプロットを表示します。
plt.show()
まとめ
この実験では、Matplotlib で 2 つの同じパネルと UpdatingRect と MandelbrotDisplay クラスを使ってインタラクティブなズーム機能を作成する方法を学びました。ズーム機能を追加することで、プロット内のデータをより良く理解して分析することができます。