4

I am trying to use matplotlib to create a graph to reflect real time results. I am probably not doing this correctly, because moving the window, changing windows, or clicking things causes the graph to freeze. Below is an example of what I mean.

import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

def function1(fig, varse):
  ax = fig.add_subplot(111, projection='3d')
  color_grade_classes = ['#80FF00','#FFFF00','#FF8000', '#FF0000']
  varse = varse +1
  ax.set_xlabel('X')
  ax.set_ylabel('Y')
  for colors, rows  in zip(color_grade_classes, [3,2,1,0] ):  
    indexs = np.arange(5)
    heights = [varse,varse/2,varse/3,0,0]
    ax.bar(indexs, heights, zs = rows,  zdir='y', color=colors, alpha=0.8)
  plt.ion()
  plt.draw()
  plt.show()
  plt.ioff()
  return varse

varse = 0
plt.ion()
fig = plt.figure()
plt.ioff()
while(1):
  varse = function1(fig, varse)
user1170056
  • 131
  • 1
  • 1
  • 5

4 Answers4

2

The way I solved was to use tk as a gui:

import matplotlib
matplotlib.use('TkAgg')

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import random
import numpy as np
import sys
import Tkinter as tk
import time

def function1(fig, ax):
    ax.cla()
    color_grade_classes = ['#80FF00','#FFFF00','#FF8000', '#FF0000']
    varsi =  random.randint(1, 100)

    for colors, rows  in zip(color_grade_classes, [3,2,1,0] ):  
        indexs = np.arange(5)
        heights = [varsi,varsi/2,varsi/3,0,0]
        ax.bar(indexs, heights, zs = rows,  zdir='y', color=colors, alpha=0.8)
    return fig

class App():
    def __init__(self):
        self.root = tk.Tk()
        self.root.wm_title("Embedding in TK")

        self.fig = plt.figure()
        self.ax = self.fig.add_subplot(111, projection='3d')
        self.ax.set_xlabel('X')
        self.ax.set_ylabel('Y')
        self.fig = function1(self.fig, self.ax)

        self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
        self.toolbar = NavigationToolbar2TkAgg( self.canvas, self.root )
        self.toolbar.update()
        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

        self.label = tk.Label(text="")
        self.label.pack()
        self.update_clock()
        self.root.mainloop()

    def update_clock(self):
        self.fig = function1(self.fig,self.ax)
        self.canvas.show()
        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        now = time.strftime("%H:%M:%S")
        self.label.configure(text=now)
        self.root.after(1000, self.update_clock)

app=App()

This allows me to retain control of the graph after I show and it doesn't freeze up whenever I try to move the window.

user1170056
  • 131
  • 1
  • 1
  • 5
1

This may be a duplicate of this question.

In any case, I'm dubious about the way you're doing animation. This doesn't look like any of the matplotlib animation examples and doesn't follow the (older, I think) advice here either.

Most of those examples conclude with a plt.show(); just like any other even driven GUI programming system (because that's what matplotlib is at heart) you need to hand over control to its event loop and learn to work within that framework's provisions for animation if you want stuff to work properly.

Community
  • 1
  • 1
timday
  • 24,582
  • 12
  • 83
  • 135
  • 2
    I disagree with the general doubts about it. In my experience most of the suggested ways to do animations in matplotlib are quite bad, and that moving things to a more `matplotlib.pylab.ion()` friendly approach are a good idea. For an example solution for interactive plotting, consider the [answer that I gave here](http://stackoverflow.com/a/9814936/567620). It should be modifiable to allow basic animations as well. – ely Apr 03 '12 at 20:39
  • The problem also happens with the basic_example animation. I'm not sure how to allow new data in after plt.show(), it doesn't hang but it doesn't update! – user1170056 Apr 03 '12 at 21:03
  • EMS I tried your example solution but it also hangs when I move the window. – user1170056 Apr 03 '12 at 21:12
1

I had the same problem trying to plot some curves in realtime. A quick fix is to add a plot pause in your plotting function.

import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

def function1(fig, varse):
  ax = fig.add_subplot(111, projection='3d')
  color_grade_classes = ['#80FF00','#FFFF00','#FF8000', '#FF0000']
  varse = varse +1
  ax.set_xlabel('X')
  ax.set_ylabel('Y')
  for colors, rows  in zip(color_grade_classes, [3,2,1,0] ):  
    indexs = np.arange(5)
    heights = [varse,varse/2,varse/3,0,0]
    ax.bar(indexs, heights, zs = rows,  zdir='y', color=colors, alpha=0.8)
  plt.draw()
  plt.pause(0.001)
  return varse

varse = 0
plt.ion()
fig = plt.figure()
plt.show()

while(1):
  varse = function1(fig, varse)
user3666197
  • 1
  • 6
  • 50
  • 92
PouyaB
  • 749
  • 7
  • 6
0

I solved it from a really simple way. At the end of my main file in python, I added plt.show() at the end of my code.

from matplotlib import pyplot as plt
#.
#. My code here 
#.

# Last line of code:
plt.show()
DomDev
  • 540
  • 2
  • 12