物理の駅 Physics station by 現役研究者

テクノロジーは共有されてこそ栄える

Python matplotlib でマウスクリック位置を取得しグラフを再描画する

下記のコードではJupyter Labを使っています。

matplotlibの他に、ipymplが必要なので、pip install ipymplでインストールしてください。

コードを完全に理解していないため、解説は他の記事を参照してください。

マウスでクリックした時の、回数、座標、そのときの二次元ヒストグラムのCountsを取得するコード。

%matplotlib widget 

import numpy as np
import matplotlib.pyplot as plt

#データ生成
np.random.seed(0)
x = np.random.normal(0,1,10000)
y = np.random.normal(3,2,10000)

#カラーバー設定
import copy
cmap = copy.copy(plt.cm.jet)
cmap.set_under('w',1)

#描画
fig, ax = plt.subplots()
h, edgex, edgey, im = ax.hist2d(x, y, range=[[-10,10],[-10,10]], bins=[100,100], cmap=cmap)
im.set_clim(1,50)
fig.colorbar(im)

#ビン中心を計算
centerx = (edgex[1:]+edgex[:-1])*0.5
centery = (edgey[1:]+edgey[:-1])*0.5

# ここから重要
from ipywidgets import Output
out = Output()
display(out)

@out.capture(clear_output=True)
def onclick(event):
    try:
        print('{} click: button={}, x={}, y={}, z={}, xdata={:.3f}, ydata={:.3f}'.format
              ('double' if event.dblclick else 'single', event.button,
               event.x, event.y,
               h[np.argmin(np.abs(centerx-event.xdata)),np.argmin(np.abs(centerx-event.ydata))],
               event.xdata, event.ydata))
    except:
        print("Error",event.x, event.y, event.xdata, event.ydata)
        
cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()

次に、グラフを2分割して、左側のグラフでダブルクリックした位置の周辺を、右側のグラフで拡大して描画するコード。

#jupyterlab
%matplotlib widget 

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(0)
x = np.random.normal(0,1,10000)
y = np.random.normal(3,2,10000)

import copy
cmap = copy.copy(plt.cm.jet)
cmap.set_under('w',1)

fig, axs = plt.subplots(1,2,figsize=(10,4)) #2分割
ax = axs[0] #左側
h, edgex, edgey, im0 = ax.hist2d(x, y, range=[[-10,10],[-10,10]], bins=[100,100], cmap=cmap)
im0.set_clim(1,50)
ax = axs[1] #右側
_,_,_,im1 = ax.hist2d(x, y, range=[[-10,10],[-10,10]], bins=[100,100], cmap=cmap)
im1.set_clim(1,50)

centerx = (edgex[1:]+edgex[:-1])*0.5
centery = (edgey[1:]+edgey[:-1])*0.5

# ここから重要
from ipywidgets import Output
out = Output()
display(out)

@out.capture(clear_output=True)
def onclick(event):
    try:
        print('{} click: button={}, x={}, y={}, z={}, xdata={:.3f}, ydata={:.3f}'.format
              ('double' if event.dblclick else 'single', event.button,
               event.x, event.y,
               h[np.argmin(np.abs(centerx-event.xdata)),np.argmin(np.abs(centerx-event.ydata))],
               event.xdata, event.ydata))
        if event.inaxes is axs[0] and event.dblclick: #左側のグラフでダブルクリックしたとき
            ax.set_xlim(event.xdata-1,event.xdata+1)
            ax.set_ylim(event.ydata-1,event.ydata+1)
    except:
        print("Error",event.x, event.y, event.xdata, event.ydata)
        
cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()

操作中の動画 (クリックするとOneDrive に移動します)