3

matplotlib を使用して行列をプロットしました。ツールキット/モジュールを使用して、このプロットにインタラクティブ性を与えることができるかどうか疑問に思っています。

私たちの分析に基づいて、マトリックスのどのセルが他のセルに接続されているかを先験的に知っています。私たちがやりたいことは、ユーザーがマウスポインターでマトリックスセルにカーソルを合わせたときに、それが接続されている他のセル (ポインターまたはその他の方法) を介して強調表示する機能を持つことです。グラフのデータ構造のようなものですが、ユーザーにインタラクティブな体験をしてもらいたいです。

4

3 に答える 3

3

Matplotlib には、インタラクティブな図に使用できるイベント処理 APIがあります。

以下のスクリプト例は、 を使用して行列をプロットしmatshowます。マトリックスの値は色分けされています。

接続ディクショナリで接続を設定できます。キーは、接続を (タプルとして) 追加するマトリックスの位置であり、接続は接続ポイントのリストで (再びタプルとして) 与えられます。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import patches

class MatrixBrowser(object):

    def __init__(self, matrix, matrix_ax, connections):
        self.matrix = matrix
        self.matrix_ax = matrix_ax
        self.con = connections
        self.index = (0, 0)
        self.rect = patches.Rectangle((0, 0), 1.1, 1.1,
                    linewidth=3, fill=False, visible=False)
        self.con_rects = self.add_connection_rects()

    def add_connection_rects(self):
        max_cons = max([len(_) for _ in self.con.values()])
        rects = []
        for con in range(max_cons):
            con_rect = patches.Rectangle((0, 0), 1.1, 1.1, linewidth=5,
                        fill=False, visible=False, edgecolor='red')
            rects.append(con_rect)
            self.matrix_ax.add_patch(con_rect)
        return rects

    def update_connections(self, event):
        current_ax = event.inaxes
        cx = event.xdata
        cy = event.ydata
        # only if the cursor is on the matrix ax
        if current_ax == self.matrix_ax:
            rx = round(abs(cx))
            ry = round(abs(cy))
            if not self.index == (rx, ry):
                # make every previous rect invisible
                for rect in self.con_rects:
                    rect.set_visible(False)
                cons = self.con.get((rx, ry), [])
                for rect, con in zip(self.con_rects, cons):
                    rect.set_xy((con[0] - 0.55, con[1] - 0.55))
                    rect.set_visible(True)
                self.index = (rx, ry)
            self.rect.set_visible(True)
            self.rect.set_xy((rx - 0.55, ry - 0.55))
        else:
            self.rect.set_visible(False)
        plt.draw()

def main(matrix, connections):
    fig, ax = plt.subplots()
    im = ax.matshow(matrix, aspect='auto', cmap=plt.cm.winter)
    plt.colorbar(im, use_gridspec=True)
    browser = MatrixBrowser(matrix, ax, connections)
    ax.add_patch(browser.rect)
    fig.canvas.mpl_connect('motion_notify_event', browser.update_connections)
    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    matrix = np.random.rand(15, 15) * 10
    connections = {(0, 0): [(1, 1), (2, 2), (10, 2), (8, 5)],
                   (3, 2): [(3, 3)],
                   (14, 14): [(0, 0), (0, 14), (14, 0)]}
    main(matrix, connections)

印象を与えるために、スクリーンショットを追加します。黒い四角形はマウス カーソルと共に移動し、現在のマウス位置に接続がある場合は赤い四角形が表示されます。

このスクリーンショットでは、カーソルは(0, 0)マトリックス内のポイントにあります。このポイントには接続が定義されているため (接続辞書を参照してください: (0, 0): [(1, 1), (2, 2), (10, 2), (8, 5)])、定義された接続は赤い四角形で強調表示されます。

結果のプロット

于 2012-05-03T22:01:19.633 に答える
2

たとえば、gtk を matplotlib と一緒に使用して、アプリケーションにすることができます。そこには多くのチュートリアルがあります (ここにあります)。gtk を選択すると、マウスの動きに反応する matplotlib-widget にリスナーを接続します。そのリスナーのコールバック関数は、グラフのキャンバス上のマウス位置の座標と、プロットしているデータ空間 (event.ydataおよび) の座標の両方を持つイベントを取得します。event.xdata

ホバー効果に関しては、パッチ (matplotlib) を使用することが解決策になる可能性があります。グラフの上にそれらを配置するか、gtk の別のウィジェットの情報を脇に置くことができます。

いくつかのコードが途中にあります (アプリケーション全体を書くのは少し多すぎます。つまり、多くのことはできませんが、それらをコピーして貼り付けるとエラーが発生します)。

from matplotlib.backends.backend_gtk import FigureCanvasGTK as FigureCanvas

self.image_fig = plt.Figure(figsize=figsize, dpi=75)
image_plot = self.image_fig.add_subplot(111)
image_canvas = FigureCanvas(self.image_fig)
self.image_fig.canvas.mpl_connect('motion_notify_event', self.plot_drag
self.plots_vbox.pack_start(image_canvas, False, False, 2)

最後に、プロットを更新したら、キャンバスを再描画する必要があります。私の例の行では、私は

self.image_fig.canvas.draw()
于 2012-05-02T18:33:42.563 に答える
1

matplotlibには、プロットに双方向性を追加するために使用できるいくつかの下位層APIとフックがあります。APIの例は、それを行うためのいくつかの方法を示しています。正確な方法は、使用するバックエンドによって異なる場合があります。

于 2012-05-02T18:19:27.947 に答える