0

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.

theAlse
  • 5,577
  • 11
  • 68
  • 110
  • This thread seems to contain some promising approaches. http://stackoverflow.com/questions/10944621/dynamically-updating-plot-in-matplotlib – Henning Jan 04 '17 at 09:31

2 Answers2

0

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)
Mike Müller
  • 82,630
  • 20
  • 166
  • 161
  • I incorporated your suggestion in my code (the difference is that my code pretty much is forever inside the for-loop and continues plotting the latest point). Still the graph hangs (does not responds) after 1 minute or so. any ideas? – theAlse Jan 05 '17 at 06:01
  • You need to replace the for-loop with your logic for getting new x and y values. When you do `line.set_data(xs, ys)` and **append** different x and y to `xs` and `ys` every time, you should see points at different places. After the loop is finished, `plt.ioff()` stops the animation. Increase the to `for _ in range(1000):` to `for _ in range(100000):` for a longer animation. – Mike Müller Jan 05 '17 at 09:20
  • I am only displaying one point at a time, like this `self.xs[0] = int(app_x) self.ys[0] = int(app_y) self.line.set_data(self.xs, self.ys)`, still the graph crashes after a while – theAlse Jan 05 '17 at 09:52
  • Might be a Windows thing with the crash. There is a more complex approach. Best would to add a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve), i.e. something I can run and test without a USB devise. – Mike Müller Jan 05 '17 at 09:57
  • Please see the updates. I have added a minimal, complete and run able example. – theAlse Jan 09 '17 at 07:45
-1

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')