0

我有一个脚本,它使用 SpanSelector 小部件生成数据图。小部件调用一个select_window(vmin, vmax)闭包函数,该函数使用窗口限制来分析所选数据。分析函数生成另一个带有一些视觉结果的图。

SpanSelector 的默认行为是select_window在选择后立即执行。由于计算有点繁重,我希望用户通过按键确认所选窗口。第一个选项是使用plt.waitforbuttonpress,但这会响应所有关键事件,包括默认用于平移/缩放/等的事件。在 matplotlib 中。

第二个选项是key_press_event直接连接一个,但我不确定在哪里连接和断开事件处理程序。

工作示例,使用 waitforbuttonpress:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import SpanSelector

def analyse(data, window_min, window_max):
    sliced_data = data[window_min:window_max]
    print(sliced_data)
    fig, ax = plt.subplots()
    ax.plot(sliced_data)
    plt.pause(0.001)

def plot_data(data):
    fig, ax = plt.subplots()
    ax.plot(data)
    def select_window(vmin, vmax):
        if plt.waitforbuttonpress(60):
            window_min = int(np.floor(vmin))
            window_max = int(np.ceil(vmax))
            analyse(data, window_min, window_max)
    widget = SpanSelector(
        ax, select_window, 'horizontal', useblit=True, span_stays=True,
        minspan=1
    )
    plt.show()
    return widget  # Keeping a reference so it isn't garbage collected.

if __name__ == '__main__':
    data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    widget = plot_data(data)
4

1 回答 1

0

关键是在正确的地方使用fig.canvas.mpl_connectfig.canvas.mpl_disconnect。断开连接是必需的,否则绘图将累积在连续的窗口选择上。

这是解决方案,它只接受输入键作为有效的窗口确认。其他键可以通过 访问event.key

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import SpanSelector

def analyse(data, window_min, window_max):
    sliced_data = data[window_min:window_max]
    print(sliced_data)
    fig, ax = plt.subplots()
    ax.plot(sliced_data)
    plt.pause(0.001)

def plot_data(data):
    fig, ax = plt.subplots()
    ax.plot(data)
    def select_window(vmin, vmax):
        def _confirm_selection(event):
            if event.key == 'enter':  # Make the selector wait for <enter> key
                window_min = int(np.floor(vmin))
                window_max = int(np.ceil(vmax))
                analyse(data, window_min, window_max)
                fig.canvas.mpl_disconnect(cid)  # Disconnect the event after analysis
        cid = fig.canvas.mpl_connect('key_press_event', _confirm_selection)
    widget = SpanSelector(
        ax, select_window, 'horizontal', useblit=True, span_stays=True,
        minspan=1
    )
    plt.show()
    return widget  # Keeping a reference so it isn't garbage collected.

if __name__ == '__main__':
    data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    widget = plot_data(data)

事件 ID 可以mpl_disconnect从闭包中访问。因此,事件可以在它自己的回调(即_confirm_selection)中断开连接。我不确定这是否是最好的方法,欢迎改进,但它确实有效;)

于 2020-02-29T01:26:16.370 回答