MatPlotLib's ion() and draw() not working
Solution 1
Adapted for your case from : Python realtime plotting
import matplotlib.pyplot as plt
import numpy as np
import time
fig = plt.figure()
ax = fig.add_subplot(111)
# some X and Y data
x = [0]
y = [0]
li, = ax.plot(x, y,'o')
# draw and show it
fig.canvas.draw()
plt.show(block=False)
# loop to update the data
for i in range(100):
try:
x.append(i)
y.append(i)
# set the new data
li.set_xdata(x)
li.set_ydata(y)
ax.relim()
ax.autoscale_view(True,True,True)
fig.canvas.draw()
time.sleep(0.01)
except KeyboardInterrupt:
plt.close('all')
break
Solution 2
This solution example has worked for me on multiple machines. Try adjusting plt.pause(...)
import matplotlib.pyplot as plt
import numpy as np
F = lambda x: np.sin(2*x)
plt.ion()
x = np.linspace(0, 1, 200)
plt.plot(x, F(x))
for i in range(100):
if 'ax' in globals(): ax.remove()
newx = np.random.choice(x, size = 10)
ax = plt.scatter(newx, F(newx))
plt.pause(0.05)
plt.ioff()
plt.show()
Solution 3
Hey I was having the same problem, I checked other questions and my issue was solved when I plugged a pause into my solution. Here's some example code that worked for me.
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
x = np.arange(0, 4*np.pi, 0.1)
y = [np.sin(i) for i in x]
plt.plot(x, y, 'g-', linewidth=1.5, markersize=4)
plt.pause(0.0001)
plt.plot(x, [i**2 for i in y], 'g-', linewidth=1.5, markersize=4)
plt.pause(0.0001)
plt.plot(x, [i**2*i+0.25 for i in y], 'r-', linewidth=1.5, markersize=4)
plt.pause(0.0001)
The solution was posted here: Matplotlib ion() and subprocesses
Solution 4
The problem - and the solution - is highly dependent on the plot.draw() function within the Python environment and back end, and may even vary in different product releases. It manifests itself in different ways depending on the environment. The problem shows up in many places on stackoverflow with some solutions working for some people and not for others.
The gold standard on my Windows laptop is running the Python from the command line - no IDE, just plain vanilla Python3. draw() as shown in the example always works fine there.
If I try it in Jupyter notebook on the same machine, no amount of draw(), plot.pause(), plot.show(), or any other suggestion works. I tried %matplotlib with notebook, widget and ipympl. Nothing gets drawn until complete end of cell code execution.
Some other sources on stackoverflow suggested using figure.canvas.flush_events(). I had some success with that and investigated further.
The best solution turned out to be to run the draw() at the figure.canvas level instead of the axes or plot level.
You can get the figure by creating your plot with command:
fig, graph, = plt.subplots()
or, if you've already created the plot, as in the code at the top of the ticket, put the following outside the loop:
fig = plt.gcf() #get current figure
Inside the loop, instead of plt.draw(), use
fig.canvas.draw()
It's proven reliable in my Jupyter Notebook environment even when running multiple axes/plots across multiple figures. I can drop in sleep() statements and everything appears when expected.
Your mileage may vary.
Alex
Updated on July 09, 2022Comments
-
Alex almost 2 years
I am trying to plot figures in real time using a for loop. I have the following simple code:
import matplotlib.pyplot as plt plt.ion() plt.figure() for i in range(100): plt.plot([i], [i], 'o') plt.draw() plt.pause(0.0001)
This code does not show the figure until it has finished computing, which I don't want. I want it to draw the figure after every loop. If I replace
plt.draw()
withplt.show
, multiple figures are output in real time, but I want them all to appear in the same figure. Any ideas?EDIT:
I downloaded PyCharm with Anaconda and everything works fine. I guess it's a problem with Spyder since I tried a few different versions of it without success. If anyone has any clue what is causing this problem in Spyder, let me know! -
Alex over 8 yearsThanks for the reply. I tried running your code, but I get an error saying
show() got an unexpected argument
. I read that the block argument was experimental, but I'm not sure why it doesn't work on my Spyder platform. -
CoMartel over 8 yearsDoes it works without the
block
keyword? Apparently it is not working if you already are in an interactive mode. -
Alex over 8 yearsIt does work without the block statement, but doing this outputs many different figures. Is there a way to put them all together?
-
CoMartel over 8 yearsThis looks like a spyder-specific issue, as it works perfectly fine on my computer. I'm not familiar enough with Spyder to help you
-
d.popov over 3 yearsplt.pause() instead of time.sleep() also worked for me
-
d.popov over 3 yearstime.sleep() does not work for me, but using plt.pause() fixes it
-
Matiss Zuravlevs almost 3 yearsThank you! This is example that finally got it working for me. Inital try was not a success, but I did not think lines ax.relim() & ax.autoscale_view(True,True,True) were important. After adding them, it worked.