Redrawing figure in matplotlib eventually crashes python.exe

508 views Asked by At

I am very new to matplotlib so please bear with me while I explain.

I am using matplotlib to draw a 2D graph with some shapes inside it. You can see the code and the output graph below:

from random import randint
import matplotlib.path as path
import matplotlib.pyplot as plt
import matplotlib.patches as patches

from matplotlib.pyplot import plot, ion, show
import numpy


box_a_midd_x = 200
box_a_midd_y = -300
box_a_width = 100
box_a_height = 400
box_a_x = box_a_midd_x - box_a_width / 2
box_a_y = box_a_midd_y - box_a_height / 2
box_a = path.Path([(box_a_x, box_a_y), (box_a_x, box_a_y + box_a_height), (box_a_x + box_a_height, box_a_y + box_a_height), (box_a_x + box_a_height, box_a_y)])

box_b_midd_x = 700
box_b_midd_y = 100
box_b_width = 200
box_b_height = 400
box_b_x = box_b_midd_x - box_b_width / 2
box_b_y = box_b_midd_y - box_b_height / 2
box_b = path.Path([(box_b_x, box_b_y), (box_b_x, box_b_y + box_b_height), (box_b_x + box_b_height, box_b_y + box_b_height), (box_b_x + box_b_height, box_b_y)])

box_c_midd_x = 700
box_c_midd_y = 700
box_c_width = 200
box_c_height = 400
box_c_x = box_c_midd_x - box_c_width / 2
box_c_y = box_c_midd_y - box_c_height / 2
box_c = path.Path([(box_c_x, box_c_y), (box_c_x, box_c_y + box_c_height), (box_c_x + box_c_height, box_c_y + box_c_height), (box_c_x + box_c_height, box_c_y)])    

box_d_midd_x = 700
box_d_midd_y = 1400
box_d_width = 200
box_d_height = 400
box_d_x = box_d_midd_x - box_d_width / 2
box_d_y = box_d_midd_y - box_d_height / 2
box_d = path.Path([(box_d_x, box_d_y), (box_d_x, box_d_y + box_d_height), (box_d_x + box_d_height, box_d_y + box_d_height), (box_d_x + box_d_height, box_d_y)])    

monitor_box = path.Path([(35, 1677), (11, -213), (652, -220), (500, 1734)])

print "A: " + str(box_a)
print "B: " + str(box_b)
print "C: " + str(box_c)
print "D: " + str(box_d)

#plt.plot([], [])
#ion()
fig = plt.figure()
ax = fig.add_subplot(111)
patch = patches.PathPatch(monitor_box, facecolor='black', lw=1)
patch_a = patches.PathPatch(box_a, facecolor='orange', lw=2)
patch_b = patches.PathPatch(box_b, facecolor='orange', lw=2)
patch_c = patches.PathPatch(box_c, facecolor='orange', lw=2)
patch_d = patches.PathPatch(box_d, facecolor='orange', lw=2)
ax.add_patch(patch)
ax.add_patch(patch_a)
ax.add_patch(patch_b)
ax.add_patch(patch_c)
ax.add_patch(patch_d)
ax.set_xlim(-2000,2000)
ax.set_ylim(-2000,2000)
plt.gca().invert_yaxis()
#plt.plot([1], [1], 'ro')
#plt.draw()
#plt.show(block=False)
#plt.show()
plt.ion()
xs = [0]
ys = [0]
line, = plt.plot([xs[0], ys[0]], 'ro')
line.set_data(xs, ys)
plt.show()
plt.draw()
plt.pause(0.001)


def update_line(hl, new_data):
    hl.set_xdata(numpy.append(hl.get_xdata(), new_data))
    hl.set_ydata(numpy.append(hl.get_ydata(), new_data))
    plt.draw()



while(True):
    app_x = randint(0,2000)
    app_y = randint(0,2000)

    isInsideA = box_a.contains_points([(app_x,app_y)])
    isInsideB = box_b.contains_points([(app_x,app_y)])
    isInsideC = box_c.contains_points([(app_x,app_y)])
    isInsideD = box_d.contains_points([(app_x,app_y)])
    whichBox = ""
    if isInsideA:
        whichBox = "A"
    elif isInsideB:
        whichBox = "B"
    elif isInsideC:
        whichBox = "C"
    elif isInsideD:
        whichBox = "D"
    else:
        whichBox = "..."

    print ("X: " + str(int(app_x)) + "\t Y: " + str(int(app_y)) + " \t" + str(whichBox))
    xs[0] = int(app_x)
    ys[0] = int(app_y)
    line.set_data(xs, ys)
    plt.show()
    plt.draw()

The output figure looks like this (nothing fancy about it really). graph

The problem is that the graph crashes (Not responsing) after a couple of seconds (30-40 seconds, and it seems random). When the graph window hangs, you can still see that the python code is still running and new values are printed but nothing happens in the graph anymore. I have no idea where to continue. Please run the complete minimal example above and you will hopefully see the issue.

I am running Python 2.7.8 on a Windows 7 machine. More specifically Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32.

2

There are 2 answers

0
ankita babariya On

def myfunc(x): return hasattr(x, 'set_color')

for o in fig.findobj(myfunc):
    o.set_color('blue')

import matplotlib.text as text

for o in fig.findobj(text.Text):
    o.set_fontstyle('italic')
5
Mike Müller On

You create a new plot for each iteration. Better use set_data() and append to lists of x an y coordinates:

plt.ion()
xs = [random.randint(-1000, 1000)]
ys = [random.randint(-1000, 1000)]
line, = plt.plot([xs[0], ys[0]], 'ro')
for _ in range(1000):
    xs.append(random.randint(-1000, 1000))
    ys.append(random.randint(-1000, 1000))
    line.set_data(xs, ys)
    plt.show()
    plt.draw()
    plt.pause(0.001)
plt.ioff()
plt.show()

These are two lists with one random number each:

xs = [random.randint(-1000, 1000)]
ys = [random.randint(-1000, 1000)]

Now, create a plot, using these lists:

line, = plt.plot([xs[0], ys[0]], 'ro')

In the loop, simulate new x an y value you get from LeapMotion Device and append them to your coordinates:

xs.append(random.randint(-1000, 1000))
ys.append(random.randint(-1000, 1000))

update your plot with the new coordinates:

line.set_data(xs, ys)