# tkplot マニュアル

## 1. 役割

`tkplot` は、Matplotlib figureへクリック、最近傍データ表示、注釈、crosshair、点・text移動、popup、button、範囲選択を追加するinteractive helperです。`tkPlotEvent` が互換facade、`RangeSelector` がdrag範囲選択を担当します。

## 2. 推奨import

```python
from tkplot import tkPlotEvent, RangeSelector
```

## 3. クリックした最近傍データを表示

```python
import matplotlib.pyplot as plt
import numpy as np
from tkplot import tkPlotEvent

x = np.linspace(0.0, 10.0, 101)
y = np.sin(x)

fig, ax = plt.subplots()
line, = ax.plot(x, y, label="sin")

interactive = tkPlotEvent(plt, distance="r")
interactive.add_data({
    "label": "sin data",
    "plot_type": "2D",
    "axis": ax,
    "data": [line],
})
interactive.register_click(fig)

plt.show()
interactive.disconnect_all()
```

`distance` は `"r"`, `"x"`, `"y"` のいずれかです。距離はaxis表示範囲で規格化されます。

## 4. dataset辞書

`add_data()` に最低限必要なキー:

| キー | 内容 |
|---|---|
| `label` | dataset表示名 |
| `plot_type` | `"2D"`, `"plot"`, `"scatter"` 等 |
| `axis` | Matplotlib Axes |

任意キー:

- `data`: Line2DやPathCollection。省略時はaxisから収集。
- `xlist`, `xlabels`: click時に追加表示する対応データ。
- `axis_scale`: 距離規格化や座標変換に使う別axis。
- その他metadata。

## 5. 範囲選択

```python
import matplotlib.pyplot as plt
from tkplot import RangeSelector

fig, ax = plt.subplots()
ax.plot([0, 1, 2], [1, 3, 2])


def selected(x0, x1, y0, y1):
    xmin, xmax = sorted((x0, x1))
    print("x range:", xmin, xmax)

selector = RangeSelector(
    mode="x",
    axis=ax,
    on_selected=selected,
)
plt.show()
selector.disconnect()
```

`mode="x"`, `"y"`, `"xy"` を使えます。callbackへ渡される端点はdrag方向のままで、昇順保証はありません。必要なら `sorted()` してください。

## 6. その他のcontroller

`tkPlotEvent` から次の登録メソッドを利用できます。

- `register_annotation_event()`
- `register_move_points_event()`
- `register_move_text_event()`
- `register_follow_mouse_event()`
- `register_popup_menu_event()`
- `add_button()` / `add_stop_button()`

これらは内部controllerへ委譲します。詳細なstate fieldと引数はAPIリファレンスを参照してください。

## 7. lifecycle

Matplotlibのevent connectionを保持するため、interactive objectをlocal一時変数だけにせず、figure表示中は参照を保持してください。

```python
fig._tkplot_event = interactive
fig._range_selector = selector
```

終了時は `disconnect_all()` または `RangeSelector.disconnect()` を呼びます。

## 8. GUI backend上の注意

- notebook inline backendではmouse eventの一部が制限されます。
- popupはTk系環境への依存があります。
- redrawやdrag中の性能はdata点数とbackendに依存します。
- `tkPlotEvent` のconstructor第1引数は `matplotlib.pyplot` 相当objectです。

## 9. 生成AI向けコード生成ルール

1. `tkPlotEvent(plt)` とし、FigureやAxesを第1引数にしない。
2. `add_data()` には `label`, `plot_type`, `axis` を必ず渡す。
3. Line2Dとscatterではartistデータ取得方法が異なるため、`plot_type` を正しく指定する。
4. selector/callback objectの参照をfigure表示中保持する。
5. 範囲端点の大小を自動保証しない。
6. GUI終了時にeventをdisconnectする。
7. 画像保存だけのnoninteractive scriptに不要なevent登録を追加しない。
