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.
I thought it would be enough to perform:
# 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.