matplotlib:从图中删除补丁 [英] matplotlib: removing patches from plot

查看:40
本文介绍了matplotlib:从图中删除补丁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 matplotlib交互式绘制一些补丁.

I am using matplotlib to interactively plot some patches and points.

我通过队列从一个单独的进程接收数据并将它们发送到我的绘图进程.代码的那部分工作正常,点显示在图形上,并按预期在图中不断更新.

I receive the data from a separate process via a queue and send them to my plot-process. That part of the code works fine and points are shown on the graph and continuously updated in the plot as expected.

应用户要求,我想删除图中的所有旧补丁并替换为新补丁.

Upon request from the user I would like to remove all the old patches in the plot and replace with new ones.

我认为执行就足够了

# remove the old patch
patch.remove() 
# I also tried ax.cla() without any success
# create a new patch
monitor_box = path.Path([(305, 500), (11, -213), (300, -220), (500, 1734)])
patch = patches.PathPatch(monitor_box, facecolor='black', lw=1)
# add the patch to the axis
ax.add_patch(patch)

然后在下一次迭代中,应该使用新补丁更新绘图:

and then during the next iteration, the plot should be updated with new patch:

canvas.draw()

但是当我使用上面的代码时,补丁仍然保留在窗口中并且没有任何变化.(我仍然得到了情节中的点,因此至少仍在不断更新)

but when I use the above code, the patch still remains in the window and nothing changes. (I am still getting the points in the plot so that is at-least still being continuously updated)

下面我提供了该问题的最小工作示例.运行代码时,您可以看到绘制了不同的点,但从未删除补丁.

Below I have provided a minimal working example of the issue. When you run the code, you can see that different points get plotted but the patches are never removed.

import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
import multiprocessing
from Tkinter import *
import matplotlib.path as path
import matplotlib.patches as patches
import sys, thread, time

from random import randint

#Create a window
window=Tk()

sendProximityInfo = True
latest_published_msg = ""

def erasePatchesAndCreateNew_A():
    print "erasePatchesAndCreateNew_A"
    global line, ax, canvas
    global monitor_box
    global patch
    patch.remove()
    ax.cla()            
    monitor_box = path.Path([(35, 1677), (11, -213), (652, -220), (500, 1734)])
    patch = patches.PathPatch(monitor_box, facecolor='black', lw=1)

    ax.add_patch(patch)

def erasePatchesAndCreateNew_B():
    print "erasePatchesAndCreateNew_B"
    global line, ax, canvas
    global monitor_box
    global patch
    patch.remove()
    ax.cla()
    monitor_box = path.Path([(35, 500), (11, -213), (300, -220), (500, 1734)])
    patch = patches.PathPatch(monitor_box, facecolor='red', lw=1)

    ax.add_patch(patch)

monitor_box = path.Path([(35, 1677), (111, -213), (62, -220), (800, 1734)])
fig = matplotlib.figure.Figure()
ax  = fig.add_subplot(1,1,1)
ax.set_xlim(-1500,2000)
ax.set_ylim(-1500,2000)
patch = patches.PathPatch(monitor_box, facecolor='black', lw=1)
ax.add_patch(patch)

def main():
    erasePatchesAndCreateNew_B()

    #Create a queue to share data between process
    q = multiprocessing.Queue()
    #Create and start the simulation process
    simulate = multiprocessing.Process(None, simulation,args=(q,))
    simulate.start()   
    #Create the base plot
    plot()
    #Call a function to update the plot when there is new data
    updateplot(q)

    window.mainloop()
    print 'Done'
    simulate.join() # wait for the other process to finish as well

def plot():    #Function to create the base plot, make sure to make global the lines, axes, canvas and any part that you would want to update later
    global line, ax, canvas
    global monitor_box
    global patch

    fig = matplotlib.figure.Figure()
    ax  = fig.add_subplot(1,1,1)
    ax.set_xlim(-1500,2000)
    ax.set_ylim(-1500,2000)

    patch = patches.PathPatch(monitor_box, facecolor='black', lw=1)
    ax.add_patch(patch)

    ax.invert_yaxis()
    canvas = FigureCanvasTkAgg(fig, master=window)
    canvas.show()
    canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
    canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)
    line, = ax.plot([], [], 'ro')

def updateplot(q):
    try:       #Try to check if there is data in the queue
        result = q.get_nowait()

        if result != 'Q':
            x, y = result
            line.set_data(x, y)
            ax.draw_artist(line)
            canvas.draw()
            window.after(1,updateplot,q)
        else:
            print 'done'
    except:
        window.after(1,updateplot,q)

def simulation(q):   
    try:
        while True:
            for i in range(10):
                q.put( (randint(0,1500), randint(0,1500)) )
                time.sleep(1)
            erasePatchesAndCreateNew_A()
            time.sleep(1)
            for i in range(10):
                q.put( (randint(0,1500), randint(0,1500)) )
                time.sleep(1)
            erasePatchesAndCreateNew_B()
            time.sleep(1)
    except KeyboardInterrupt:
        print "received KeyboardInterrupt"
    finally:
        print "simulation ended"
        sys.exit()

if __name__ == '__main__':
    main()

下面是该程序的屏幕截图,红点在图中移动,但色块(黑色形状)永不改变.

Below is a screenshot from the program, the red dot moves around in the graph but the patch (black shape) never changes.

推荐答案

我设法解决了这个问题,或者确切地说,我找到了解决该问题的方法.我在下面添加了它,也许将来会对其他人有帮助.我基本上是使用队列来交流何时应在主线程中更新图形.

I managed to solve this issue, or to be exact I figured out a around for this issue. I am adding it below and maybe it will help someone else in the future. I am basically using the queue to communicate when the graph should be updated in the main thread.

import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
import multiprocessing
from Tkinter import *
import matplotlib.path as path
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import sys, thread, time

from random import randint

#Create a window
window=Tk()

sendProximityInfo = True
latest_published_msg = ""

monitor_box = path.Path([(1000, -1000), (111, -213), (62, -220), (800, 1734)])
fig = matplotlib.figure.Figure()
ax  = fig.add_subplot(1,1,1)
ax.set_xlim(-1500,2000)
ax.set_ylim(-1500,2000)
patch = patches.PathPatch(monitor_box, facecolor='black', lw=1)
ax.add_patch(patch)

def main():
    #Create a queue to share data between process
    q = multiprocessing.Queue()
    #Create and start the simulation process
    simulate = multiprocessing.Process(target=simulation,args=(q,))
    simulate.start()   
    #Create the base plot
    plot()
    #Call a function to update the plot when there is new data
    updateplot(q)

    window.mainloop()
    print 'Done'
    simulate.join() # wait for the other process to finish as well

def plot():    #Function to create the base plot, make sure to make global the lines, axes, canvas and any part that you would want to update later
    global line, ax, canvas, fig, monitor_box, patch
    patch.remove()
    monitor_box = path.Path([(500, -500), (111, -213), (62, -220), (800, 1734)])
    patch = patches.PathPatch(monitor_box, facecolor='pink', lw=1)
    ax.add_patch(patch)

    canvas = FigureCanvasTkAgg(fig, master=window)
    canvas.show()
    canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
    canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)
    line, = ax.plot([], [], 'ro')

def erasePatchesAndCreateNew_A():
    print "erasePatchesAndCreateNew_A"
    global ax, monitor_box, patch
    patch.remove()
    monitor_box = path.Path([(35, 1677), (11, -213), (652, -220), (500, 1734)])
    patch = patches.PathPatch(monitor_box, facecolor='red', lw=1)
    ax.add_patch(patch)


def erasePatchesAndCreateNew_B():
    print "erasePatchesAndCreateNew_B"
    global ax, monitor_box, patch
    patch.remove()
    monitor_box = path.Path([(-2000, 2000), (11, -213), (300, -220), (500, 1734)])
    patch = patches.PathPatch(monitor_box, facecolor='blue', lw=1)
    ax.add_patch(patch)


def updateplot(q):
    try:       #Try to check if there is data in the queue
        result = q.get_nowait()

        if result != 'A' and result != 'B':
            x, y = result
            line.set_data(x, y)
            ax.draw_artist(line)
            canvas.draw()
            window.after(10,updateplot,q)
        elif result == 'A':
            erasePatchesAndCreateNew_A()
            canvas.draw()
            window.after(10,updateplot,q)
        elif result == 'B':
            erasePatchesAndCreateNew_B()
            canvas.draw()
            window.after(10,updateplot,q)
    except:
        window.after(10,updateplot,q)

def simulation(q):   
    try:
        while True:
            for i in range(5):
                q.put( (randint(0,1500), randint(0,1500)) )
                time.sleep(0.5)
            #erasePatchesAndCreateNew_A()
            q.put('A')
            time.sleep(1)
            for i in range(5):
                q.put( (randint(0,1500), randint(0,1500)) )
                time.sleep(0.5)
            #erasePatchesAndCreateNew_B()
            q.put('B')
            time.sleep(1)
    except KeyboardInterrupt:
        print "received KeyboardInterrupt"
    finally:
        print "simulation ended"
        sys.exit()

if __name__ == '__main__':
    main()

这篇关于matplotlib:从图中删除补丁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆