tkplotevent.py ライブラリ ドキュメント
ライブラリの機能や目的
tkplotevent.py ライブラリは、Matplotlibのプロットイベントを処理し、インタラクティブな機能を提供するPythonユーティリティモジュールです。このライブラリは、TkinterとMatplotlibを連携させ、ユーザーがグラフとより直感的に対話できるようにすることを目的としています。
主な機能は以下の通りです。
プロット上の範囲選択 (RangeSelector): マウスドラッグによりX軸、Y軸、または両方の範囲を視覚的に選択し、その範囲情報を取得できます。
データ点のクリックイベント処理と情報表示: プロット上のデータ点をクリックした際に、最も近い点の詳細情報をコンソールに表示します。
ポップアップメニューの表示: 右クリックイベントにカスタムメニューを紐付け、プロット上でコンテキストメニューを表示できます。
プロット上のテキストやマーカーのドラッグ移動: 追加されたテキストやアノテーション、特定のデータマーカーをマウスでドラッグして移動させることができます。
マウスカーソルに追従する補助線やマーカー: マウスカーソルの位置に合わせて、X軸/Y軸方向の補助線やマーカーをリアルタイムで表示します。
mplcursorsによるデータアノテーション: マウスホバー時にデータ点に関する詳細なアノテーション(ツールチップ)を表示し、クリック時にはコンソールに出力します。停止ボタンの追加: プロットにボタンを追加し、特定の処理を停止させるためのトリガーとして利用できます。
このライブラリを利用することで、Matplotlibの静的なグラフに動的な操作性を持たせ、データ探索や分析の効率を高めることが可能になります。
importする方法
このライブラリをPythonプログラムで利用するには、以下のように import 文を使用します。
import matplotlib.pyplot as plt
from tkplotevent import RangeSelector, tkPlotEvent
# RangeSelectorの利用例
# ax = plt.gca()
# selector = RangeSelector(axis=ax)
# tkPlotEventの利用例
# fig = plt.figure()
# ax = fig.add_subplot(111)
# event_handler = tkPlotEvent(plt)
必要な非標準ライブラリとインストール方法
tkplotevent.py は、以下の非標準ライブラリに依存しています。
numpypandasmatplotlibmplcursorstklib(カスタムライブラリ)
numpy, pandas, matplotlib, mplcursors は pip を使用してインストールできます。
pip install numpy pandas matplotlib mplcursors
tklib は、このライブラリと同時に配布されるカスタムライブラリである可能性が高いです。標準の pip リポジトリには存在しない場合があります。もし tklib が見つからないというエラーが発生した場合は、tkplotevent.py が属するプロジェクトのドキュメントを参照し、tklib モジュールを別途入手またはインストールする必要があります。
importできる変数と関数
クラス: RangeSelector
Matplotlibのプロット上で範囲選択を可能にするクラス。マウスドラッグによりX軸またはY軸、あるいは両方の範囲を視覚的に選択し、その選択範囲をコンソールに出力します。選択された範囲は、指定されたスタイルの補助線で表示されます。
コンストラクタ: __init__(self, mode='x', axis=None, color='red', linestyle='dashed', linewidth=0.5, print_level=1)
動作:
RangeSelectorのインスタンスを初期化します。選択モード、Axesオブジェクト、線のスタイルなどを設定し、マウスイベントに接続します。初期状態では補助線は非表示です。引数:
mode(str): 選択する軸を指定 ('x','y','xy'のいずれか)。デフォルトは'x'。axis(matplotlib.axes.Axes): 範囲選択を行うAxesオブジェクト。color(str): 選択範囲を示す線の色。デフォルトは'red'。linestyle(str): 選択範囲を示す線のスタイル (例:'solid','dashed','dotted')。デフォルトは'dashed'。linewidth(float): 選択範囲を示す線の幅。デフォルトは0.5。print_level(int): 選択範囲をコンソールに出力するレベル。0で出力しません。デフォルトは1。
メソッド:
set_mode(self, mode)動作: 選択モード(X軸、Y軸、または両方)を設定します。内部フラグ (
mode_x,mode_y) を更新し、表示される補助線 (vline0,vline1,hline0,hline1) の可視性を制御します。補助線が存在しない場合は、ここで初期化されます。引数:
mode(str): 選択する軸を指定 ('x','y','xy'のいずれか)。
on_press(self, event)(内部イベントハンドラ)動作: マウスのボタンが押されたときのイベントハンドラ。イベントが左クリックで、かつ現在のAxes内で発生した場合に、選択開始点を記録します。その後、対応する補助線(X軸用またはY軸用)を表示し、キャンバスを再描画します。
引数:
event(matplotlib.backend_bases.MouseEvent): Matplotlibのマウスイベントオブジェクト。
on_mouse_move(self, event)(内部イベントハンドラ)動作: マウスが移動したときのイベントハンドラ。範囲選択が進行中の場合、マウスの位置に応じて選択範囲の終点を更新します。対応する補助線(X軸用またはY軸用)をリアルタイムで描画し、キャンバスを再描画します。
引数:
event(matplotlib.backend_bases.MouseEvent): Matplotlibのマウスイベントオブジェクト。
on_release(self, event)(内部イベントハンドラ)動作: マウスのボタンが離されたときのイベントハンドラ。範囲選択が進行中の場合、マウスが離された位置を最終的な選択範囲の終点として記録します。その後、
finalizeメソッドを呼び出して選択操作を確定します。引数:
event(matplotlib.backend_bases.MouseEvent): Matplotlibのマウスイベントオブジェクト。
finalize(self)動作: 範囲選択操作を確定します。最終的な選択範囲の終点を補助線に設定し、
print_levelが0より大きい場合は、選択されたX軸またはY軸の範囲をコンソールに出力します。その後、キャンバスを再描画し、movingフラグをFalseにリセットします。
クラス: tkPlotEvent
Matplotlibのプロットイベントを処理し、インタラクティブな機能を提供するユーティリティクラス。データ点のクリックイベント処理、ポップアップメニュー、移動可能なテキスト/点の管理、マウス追従カーソル、データアノテーションなど、Matplotlibのプロットをよりインタラクティブにするための多岐にわたる機能を提供します。
コンストラクタ: __init__(self, plt, distance='r', **args)
動作:
tkPlotEventのインスタンスを初期化します。MatplotlibのpyplotモジュールまたはFigureオブジェクトと、データ点との距離計算モードを設定し、イベント処理のための各種パラメータを初期化します。各種機能(アノテーション、マウスカーソル、データ移動、停止ボタン)のコンテナも準備されます。引数:
plt(matplotlib.pyplotモジュールまたはmatplotlib.figure.Figureオブジェクト): イベントを関連付ける対象。distance(str): データ点との距離を計算する際の基準 ('r': 半径,'x': X軸方向,'y': Y軸方向)。デフォルトは'r'。args(dict):tklib.tkobject.tkObjectの初期化に渡される追加のキーワード引数。
プロパティ:
status(str): (tkPlotEvent.stop_buttonを経由してアクセス) 停止ボタンの現在の状態を取得するプロパティ。戻り値:
str- ボタンの状態 ('running'または'stop')。
statusセッター (str): (tkPlotEvent.stop_buttonを経由してアクセス) 停止ボタンの現在の状態を設定するプロパティ。引数:
f(str): 設定する状態。
メソッド:
button_click(self, e)動作: ボタンクリックイベントのデフォルトハンドラ。
stop_flagをTrueに設定し、外部のループなどの処理を停止させることを意図します。引数:
e(matplotlib.backend_bases.MouseEvent): イベントオブジェクト。
finalize_button(self, text='finished')動作: 停止ボタンのテキストを更新します。主に処理完了後にボタンの表示を変更するために使用されます。このメソッドが呼び出される前に、
add_buttonまたはadd_stop_buttonでボタンが追加されている必要があります。引数:
text(str): ボタンに表示する新しいテキスト。デフォルトは'finished'。
add_button(self, button_region=[0.15, 0.95, 0.10, 0.03], plot_region=[0.92, 0.15], text='stop', color='#f8e58c', hovercolor='#38b48b', callback=None)動作: MatplotlibのFigureにボタンを追加します。指定された領域にボタンを作成し、クリックされたときのコールバック関数を設定します。プロット領域を調整し、ボタンが重ならないように配置します。
引数:
button_region(list): ボタンを配置するAxesの領域を[left, bottom, width, height]の形式で指定。単位はFigureの割合。デフォルトは[0.15, 0.95, 0.10, 0.03]。plot_region(list): ボタン追加後のプロット領域調整のための領域を[top, bottom]の形式で指定。単位はFigureの割合。デフォルトは[0.92, 0.15]。text(str): ボタンに表示するテキスト。デフォルトは'stop'。color(str): ボタンの背景色 (CSSカラー名またはHEXコード)。デフォルトは'#f8e58c'。hovercolor(str): マウスオーバー時のボタンの背景色。デフォルトは'#38b48b'。callback(callable): ボタンがクリックされたときに呼び出される関数。指定しない場合はbutton_clickが使われます。デフォルトはNone。
戻り値:
matplotlib.widgets.Button- 作成されたMatplotlibのButtonオブジェクト。
layout(self, show=False)動作: プロットのレイアウトを調整します。
plt.subplots_adjustを使用して、add_buttonなどで設定されたplot_regionに基づきプロット領域を調整します。showがTrueの場合、プロットを表示または一時停止します。引数:
show(bool):Trueの場合、プロットを表示または一時停止します。デフォルトはFalse。
remove(self, index)動作:
axis_infリストからデータを削除します。引数indexが整数の場合はリストのインデックスとして、文字列の場合は'label'キーの値として解釈し、対応するデータ情報をself.axis_infリストから削除します。引数:
index(int or str): 削除するデータのインデックス(整数)またはラベル(文字列)。
add_stop_button(self, button_region=[0.15, 0.95, 0.10, 0.03], plot_region=[0.92, 0.15], label='stop', color='#f8e58c', hovercolor='#38b48b', on_stop_clicked=None)動作: プロットに停止ボタンを追加します。ユーザーが処理を中断できるように、指定された領域にボタンを配置します。ボタンは自身の状態を持ち、テキストを変更する機能も持ちます。
tkStopButtonクラスのインスタンスがself.stop_buttonに格納されます。引数:
button_region(list): ボタンを配置するAxesの領域を[left, bottom, width, height]の形式で指定。単位はFigureの割合。デフォルトは[0.15, 0.95, 0.10, 0.03]。plot_region(list): ボタン追加後のプロット領域調整のための領域を[top, bottom]の形式で指定。単位はFigureの割合。デフォルトは[0.92, 0.15]。label(str): ボタンに表示するテキスト。デフォルトは'stop'。color(str): ボタンの背景色。デフォルトは'#f8e58c'。hovercolor(str): マウスオーバー時のボタンの背景色。デフォルトは'#38b48b'。on_stop_clicked(callable): ボタンがクリックされたときに呼び出されるカスタムコールバック関数。指定しない場合はデフォルトのon_clickが使われます。デフォルトはNone。
add_data(self, axis_inf={})動作: プロットデータをイベント処理用に登録します。与えられたデータ情報(
axis_inf辞書)を内部リストself.axis_infに追加します。プロットタイプ('2D', 'plot', 'scatter')に応じてデータ構造を統一し、X軸/Y軸のラベル情報もAxesオブジェクトから取得または設定します。無効なplot_typeが指定された場合はエラーメッセージを出力し終了します。引数:
axis_inf(dict): プロットに関する情報を含む辞書。必須キー:'plot_type','axis','data'。オプションキー:'xlabel','ylabel','x','y'(plot_type='scatter'の場合)。
戻り値:
dict- 登録されたaxis_inf辞書。
find_target_axes(self, event, axes=None)動作: マウスクリックイベントが発生したAxesオブジェクトを特定します。イベントの
inaxesプロパティと登録されたAxesオブジェクトを比較し、イベントが発生したAxesとそのインデックス(またはaxis_inf辞書)を返します。axes引数が指定された場合はそのリストから検索し、指定されない場合は内部のself.axis_infから検索します。引数:
event(matplotlib.backend_bases.MouseEvent): Matplotlibのマウスイベントオブジェクト。axes(list): 検索対象となるAxesオブジェクトのリスト(オプション)。指定しない場合は内部のself.axis_infを使用。デフォルトはNone。
戻り値:
tuple(itargets,hit_axisinfs): ターゲットAxesのインデックスのリスト、または単一のインデックスと、ターゲットAxes情報(axis_inf辞書)のリスト、または単一のAxesオブジェクト。tuple(None,None): ターゲットAxesが見つからない場合。
convert_coord(self, x0, y0, axis_s, axis_t)動作: あるAxes座標から別のAxes座標へ点を変換します。異なるスケールや範囲を持つAxes間で点の位置を相対的に変換する際に使用されます。例えば、
twinx()やtwiny()で作成されたAxes間で座標を変換する場合に有用です。引数:
x0(float): 変換元のX座標。y0(float): 変換元のY座標。axis_s(matplotlib.axes.Axes): 変換元のAxesオブジェクト。axis_t(matplotlib.axes.Axes): 変換先のAxesオブジェクト。
戻り値:
tuple(float,float): 変換後の(x1, y1)座標。tuple(None,None): 入力が無効な場合。
prepare_popup_menu(self, fig, parent=None)動作: ポップアップメニューの準備を行います。TkinterのMenuウィジェットを作成し、これを
self.popup_menu.menuに格納します。メニュー項目を追加するためのヘルパー関数add_menuも提供されます。parentが指定されない場合、非表示のルートTkinterウィンドウが作成されます。引数:
fig(matplotlib.figure.Figure): メニューを関連付けるMatplotlibのFigureオブジェクト。parent(tkinter.Tkまたはtkinter.Toplevel): Tkinterの親ウィジェット(オプション)。デフォルトはNone。
register_popup_menu_event(self, on_click=None)動作: 右クリックイベントにポップアップメニューを表示する機能を登録します。Matplotlibの
'button_press_event'を監視し、イベントが右クリック(ボタン3)の場合に、tk_popupメソッドを使ってTkinterのポップアップメニューをマウスカーソルの位置に表示します。カスタムのon_clickハンドラを指定することも可能です。引数:
on_click(callable): カスタムのクリックイベントハンドラ(オプション)。デフォルトは右クリックでメニュー表示。デフォルトはNone。
prepare_move_points(self)動作: プロット上の点を移動させる機能の準備を行います。移動対象の点を管理するための
gco(Graphics Object) を初期化し、プロットに移動可能な点を追加するためのヘルパー関数addを提供します。
prepare_move_text(self, fig=None)動作: プロット上のテキストやアノテーションを移動させる機能の準備を行います。移動可能なテキストやアノテーションの情報を管理するためのリスト
text_infを初期化し、これらをプロットに追加するためのヘルパー関数add_annotationとadd_textを提供します。座標がDataFrame形式の場合の処理や、自動でY軸範囲内に配置するロジックも含まれます。引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト(オプション)。デフォルトはNone。
register_move_text_event(self, fig=None, activate=False)動作: プロット上のテキストやアノテーションをドラッグして移動させるイベントを登録します。マウスのボタンプレス、リリース、移動イベントを監視し、選択されたテキスト/アノテーションの位置をリアルタイムで更新します。
activateメソッドで移動機能のアクティブ/非アクティブを切り替えられます。twinx/yなどで異なるAxesを使用している場合も座標変換して移動を処理します。引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト(オプション)。デフォルトはNone。activate(bool): 初期状態で移動機能をアクティブにするかどうか。デフォルトはFalse。
register_move_points_event(self, fig)動作: プロット上のマーカーをドラッグして移動させるイベントを登録します。マウスイベントを監視し、ピックされたマーカーをドラッグ中に移動させることができます。これにより、プロット上の特定のデータ点をインタラクティブに操作することが可能になります。
引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト。
prepare_annotation(self)動作:
mplcursorsを用いたアノテーション表示機能の準備を行います。mplcursorsに必要な内部変数を初期化し、アノテーション表示対象となるラインを登録するためのヘルパー関数add_lineを提供します。これにより、複数のラインに対するアノテーションを管理できます。
register_annotation_event(self, fig, activate=True, on_mouse_move=None, on_click=None, print_level=0)動作:
mplcursorsを使用してプロット上のデータ点にアノテーションを表示するイベントを登録します。マウスのホバーやクリックに応じてデータ点に関する情報を表示する機能を提供します。twinx/yを使用したAxesにも対応しており、座標変換を考慮して正しい情報が表示されます。アノテーションの表示/非表示やフォーマットを細かく制御できます。引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト。activate(bool): 初期状態でアノテーション機能をアクティブにするかどうか。デフォルトはTrue。on_mouse_move(callable): カスタムのマウス移動イベントハンドラ(オプション)。デフォルトはNone。on_click(callable): カスタムのクリックイベントハンドラ(オプション)。デフォルトはNone。print_level(int): クリック時に情報をコンソールに出力するレベル。デフォルトは0。
register_follow_mouse_event(self, fig, activate=True, on_mouse_move=None, print_level=0)動作: マウスカーソルに追従する補助線やマーカーを表示するイベントを登録します。マウスの動きに合わせて、指定されたAxes上にカーソルのX/Y座標を示す補助線またはマーカーをリアルタイムで描画します。複数のAxesに同時に表示することも可能です。
activateメソッドで追従機能のアクティブ/非アクティブを切り替えられます。引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト。activate(bool): 初期状態で追従機能をアクティブにするかどうか。デフォルトはTrue。on_mouse_move(callable): カスタムのマウス移動イベントハンドラ(オプション)。デフォルトはNone。print_level(int): 未使用。デフォルトは0。
register_event(self, fig, event="button_press_event", callback=None)動作: 指定されたMatplotlibイベントにコールバック関数を登録する汎用メソッド。MatplotlibのFigureCanvasから特定のイベントを捕捉し、ユーザー定義の関数を呼び出します。これにより、様々な種類のインタラクティブなイベントハンドリングを柔軟に設定できます。
引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト。event(str): 登録するイベントの種類(例:"button_press_event","key_press_event")。デフォルトは"button_press_event"。callback(callable): イベント発生時に呼び出される関数。指定しない場合はデフォルトのハンドラが使用されます。デフォルトはNone。
register_click(self, fig, event="button_press_event", callback=None)動作: マウスクリックイベントにコールバック関数を登録します。
register_eventを使用して、デフォルトでonclickメソッドを呼び出します。カスタムのコールバック関数を指定することも可能です。引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト。event(str): 登録するイベントの種類(デフォルトは"button_press_event")。callback(callable): イベント発生時に呼び出されるカスタム関数(オプション)。デフォルトはNone。
register_pick(self, fig, event="pick_event", callback=None)動作: ピックイベントにコールバック関数を登録します。
register_eventを使用して、デフォルトでonpickメソッドを呼び出します。カスタムのコールバック関数を指定することも可能です。引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト。event(str): 登録するイベントの種類(デフォルトは"pick_event")。callback(callable): イベント発生時に呼び出されるカスタム関数(オプション)。デフォルトはNone。
register_redraw(self, fig, event="draw_event", callback=None)動作: 再描画イベントにコールバック関数を登録します。
register_eventを使用して、デフォルトでondrawメソッドを呼び出します。カスタムのコールバック関数を指定することも可能です。引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト。event(str): 登録するイベントの種類(デフォルトは"draw_event")。callback(callable): イベント発生時に呼び出されるカスタム関数(オプション)。デフォルトはNone。
register_key(self, fig, event="key_press_event", callback=None)動作: キーボードプレスイベントにコールバック関数を登録します。
register_eventを使用して、デフォルトでonkeyメソッドを呼び出します。カスタムのコールバック関数を指定することも可能です。引数:
fig(matplotlib.figure.Figure): イベントを登録するMatplotlibのFigureオブジェクト。event(str): 登録するイベントの種類(デフォルトは"key_press_event")。callback(callable): イベント発生時に呼び出されるカスタム関数(オプション)。デフォルトはNone。
onkey(self, event)動作: キーボードプレスイベントのデフォルトハンドラ。'q'キーが押されたときに、関連するFigureを閉じます。
引数:
event(matplotlib.backend_bases.KeyEvent): Matplotlibのキーイベントオブジェクト。
onclick(self, event)動作: マウスクリックイベントのデフォルトハンドラ。クリックされた位置に最も近いデータ点を見つけ、その情報をコンソールに表示します。
find_target_axesとfind_nearest_dataを使用してデータ点を特定し、display_dataで情報を整形して出力します。引数:
event(matplotlib.backend_bases.MouseEvent): Matplotlibのマウスイベントオブジェクト。
onpick(self, event)動作: ピックイベントのデフォルトハンドラ。クリックされたアーティスト(線、テキストなど)のラベルをコンソールに表示します。
event.artistがget_textまたはget_labelメソッドを持つ場合にのみ処理を行います。引数:
event(matplotlib.backend_bases.PickEvent): Matplotlibのピックイベントオブジェクト。
ondraw(self, event)動作: 再描画イベントのデフォルトハンドラ。プロットが再描画されたときにメッセージを出力します。
引数:
event(matplotlib.backend_bases.DrawEvent): Matplotlibの描画イベントオブジェクト。
find_nearest_data(self, x, y, itarget_list, hit_axisinf_list)動作: 指定された座標に最も近いデータ点を見つけます。複数のAxesとデータセットの中から、マウスクリック位置に最も近いデータ点を特定します。距離計算は、
self.distance('r': 半径, 'x': X軸方向, 'y': Y軸方向) に基づいて行われます。twinx/yなどで異なるスケールのAxesがある場合でも、座標変換を考慮して正しい距離を計算します。ユークリッド距離の二乗: \(r^2 = \left(\frac{x_0 - x_i}{\text{xrange}}\right)^2 + \left(\frac{y_0 - y_i}{\text{yrange}}\right)^2\)
X軸方向の距離の二乗: \(r^2 = \left(\frac{x_0 - x_i}{\text{xrange}}\right)^2\)
Y軸方向の距離の二乗: \(r^2 = \left(\frac{y_0 - y_i}{\text{yrange}}\right)^2\)
引数:
x(float): マウスクリックのX座標 (イベント発生Axesの座標系)。y(float): マウスクリックのY座標 (イベント発生Axesの座標系)。itarget_list(list): 検索対象のself.axis_inf内のAxesのインデックスリスト。hit_axisinf_list(list): 検索対象のAxes情報辞書 (axis_inf) のリスト。
戻り値:
tuple(iinf_hit,idata_hit,ihit,minr2): 検出されたデータが属するself.axis_infリストのインデックス、検出されたデータが属するdataリストのインデックス、検出されたデータ点そのもののインデックス、最小距離の二乗。tuple(None,None,None,None): 検出可能なデータ点が見つからない場合。
display_data(self, iinf, idata, idx, hit_axisinf=None)動作: 指定されたデータ点の情報をコンソールに表示します。
find_nearest_dataによって見つかったデータ点の詳細(ラベル、座標、関連情報など)を整形し、コンソールに出力します。xlistやxlabelsが存在する場合、追加のデータ属性も表示します。引数:
iinf(int): 検出されたデータが属するself.axis_infリストのインデックス。idata(int): 検出されたデータが属するdataリストのインデックス。idx(int): 検出されたデータ点そのもののインデックス。hit_axisinf(dict): 検出されたデータ点を含むaxis_inf辞書(オプション)。指定しない場合はself.axis_inf[iinf]が使用されます。デフォルトはNone。
main scriptとして実行したときの動作
tkplotevent.py のソースコードには、if __name__ == '__main__': ブロックが存在しません。
したがって、このファイルを直接Pythonインタープリタで実行しても、特別なデモンストレーションコードやテストコードは実行されません。
このライブラリは、他のPythonスクリプトやアプリケーションからモジュールとしてインポートされ、その機能が利用されることを前提として設計されています。