1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonでプロットしたグラフの値表示

Posted at

Pythonで表示したグラフにマウスオーバーした時,最近傍点の値を表示する

matplotlibで表示したグラフにマウスを持ってきた時,最も近い点の値を表示させたい.

マウスオーバー最近傍点値表示.png

このようにマウスカーソル近傍のx,y値を表示するPythonスクリプトのサンプルを以下に示します.

<操作手順>
1.下記のPythonコードを任意のディレクトリに保存
2.コマンドプロンプトにて,そのディレクトリに移動
3.コマンドプロンプトで実行:python sigmoid_dialog2_dispXY.py
4.表示されたダイアログにそって,係数を入力(この場合は,シグモイド関数プロットの例)
5.グラフが表示されるので,任意カーブ上にマウスカーソルを持っていく
6.上図のように近傍点のx,y値を表示

sigmoid_dialog2_dispXY.py
import numpy as np
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import simpledialog

# シグモイド関数の定義(パラメータ付き)
def sigmoid(x, gain=1, slope=1, x_os=0, y_os=0):
    return gain / (1 + np.exp(-slope * (x - x_os))) + y_os

# ダイアログでパラメータを取得
def get_parameters():
    root = tk.Tk()
    root.withdraw()  # メインウィンドウを非表示

    curves = []
    num_curves = simpledialog.askinteger("入力", "プロットするシグモイド曲線の数を入力してください:")

    for i in range(num_curves):
        gain = simpledialog.askfloat(f"Curve {i+1}", "ゲイン(gain)を入力してください:", initialvalue=1.0)
        slope = simpledialog.askfloat(f"Curve {i+1}", "傾き(slope)を入力してください:", initialvalue=1.0)
        x_os = simpledialog.askfloat(f"Curve {i+1}", "Xオフセット(x_os)を入力してください:", initialvalue=0.0)
        y_os = simpledialog.askfloat(f"Curve {i+1}", "Yオフセット(y_os)を入力してください:", initialvalue=0.0)
        curves.append((gain, slope, x_os, y_os))

    return curves

# メイン処理
def plot_sigmoid_curves():
    x = np.linspace(-10, 10, 400)
    curves = get_parameters()

    fig, ax = plt.subplots(figsize=(10, 6))
    lines = []

    for i, (gain, slope, x_os, y_os) in enumerate(curves):
        y = sigmoid(x, gain, slope, x_os, y_os)
        line, = ax.plot(x, y, label=f'Curve {i+1}: gain={gain}, slope={slope}, x_os={x_os}, y_os={y_os}', linewidth=3)
        lines.append((x, y))

    # フォントサイズの調整
    ax.set_title('Multiple Sigmoid Curves', fontsize=18, fontweight='bold')
    ax.set_xlabel('x', fontsize=16, fontweight='bold')
    ax.set_ylabel('sigmoid(x)', fontsize=16, fontweight='bold')
    ax.tick_params(axis='both', labelsize=14)
    ax.grid(True)
    ax.legend(fontsize=14, loc='upper left')

    # 注釈の準備
    annotation = ax.annotate("", xy=(0, 0), xytext=(20, 20),
                             textcoords="offset points", fontsize=12,
                             bbox=dict(boxstyle="round", fc="w"),
                             arrowprops=dict(arrowstyle="->"))
    annotation.set_visible(False)

    # マウスイベント処理
    def on_mouse_move(event):
        if not event.inaxes:
            annotation.set_visible(False)
            fig.canvas.draw_idle()
            return

        min_dist = float('inf')
        closest_x, closest_y = None, None

        for x_data, y_data in lines:
            idx = np.argmin(np.abs(x_data - event.xdata))
            x_val = x_data[idx]
            y_val = y_data[idx]
            dist = np.hypot(x_val - event.xdata, y_val - event.ydata)
            if dist < min_dist:
                min_dist = dist
                closest_x, closest_y = x_val, y_val

        if min_dist < 0.5:  # しきい値 調整可能
            annotation.xy = (closest_x, closest_y)
            annotation.set_text(f"x={closest_x:.2f}\ny={closest_y:.2f}")
            annotation.set_visible(True)
        else:
            annotation.set_visible(False)

        fig.canvas.draw_idle()

    fig.canvas.mpl_connect("motion_notify_event", on_mouse_move)
    plt.tight_layout()
    plt.show()

plot_sigmoid_curves()
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?