cannot update pyplot dynamically in python 3.5 - python

Want to use the following piece of code to dynamically demonstrate how the prediction (<<2) is approaching the real values (<<1). However, only <<1 shows up and totally cannot see <<2 showing up. Any idea to fix it ?
.....
# plot the real data
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(x_data, y_data) <<<< 1
plt.ion()
plt.show()
for i in range(1001):
sess.run(train_step, feed_dict={xs:x_data, ys:y_data})
if i % 50 == 0:
print(sess.run(loss,feed_dict={xs:x_data, ys:y_data}))
try:
ax.lines.remove(lines[0])
except Exception: # if plotting the first time
pass
prediction_value = sess.run(prediction, feed_dict={xs:x_data})
lines = ax.plot(x_data,prediction_value,'r-', lw = 5) <<< 2
plt.pause(0.1)
Thanks in advance !

plt.show() waits for you to close the plot windows before proceeding. If you remove it, but still keep the plt.ion() and your platform supports it, it should run fine:
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(0, 0, 'o')
for i in range(1,10):
ax.plot(i, i, 'o')
plt.pause(1)
works for me with matplotlib 2.0.0, Python 3.5 on Mac (draws a point every second)

You need to call plt.show() at the end of your script. Otherwise it blocks everything else, as the plotting window takes over the event loop.
In order to show the figure, use plt.draw() in interactive mode.
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.scatter(x_data, y_data)
plt.ion()
plt.draw()
for i in range(1001):
...
lines = ax.plot(x_data,prediction_value,'r-', lw = 5)
plt.draw()
plt.pause(0.1)
plt.ioff()
plt.show()

Adding magic command of %matplotlib serves the intention, with a popped-up window drawn on.
But just wondering whether this is the only way ... any other way without any additional window popped up ?

Related

How gradually plot a curve in console

So the following code creates a gif file.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig, ax = plt.subplots()
line, = ax.plot(x, y, color='k')
def update(num, x, y, line):
line.set_data(x[:num], y[:num])
line.axes.axis([0, 10, 0, 1])
return line,
ani = animation.FuncAnimation(fig, update, len(x), fargs=[x, y, line],
interval=25, blit=True)
ani.save('test.gif')
plt.show()
When I run it, it shows the final result of the animation in the console.
However, I would like to see the entire animation in the console.
How can this be done?
It should also work when there is a large number of frames.
EDIT:
I am using Python 3.8.5 and Spyder 4.2.1. I would like to use the 'plots' pane of Spyder.
Well I dont have enough reputation for a comment
But as far as i know ani.save() is blocking try to switch the last two lines.
plt.show(block=False)
ani.save("test.gif")
The window will close as soon ani.save() is done if you don't want that change block to True but it will not save until you closed the window

Plot lines not showing

Whenever I try to run this code the plot lines don't show up. Does anyone have any ideas as to why?This is a picture of my code too for reference
import numpy as np
import matplotlib.pyplot as plt
p1 = 1*(10**-3)
p2 = list(range(1,101))
newlist = []
for i in range(1,100):
db = 10*np.log10(p2[i]/p1)
plt.figure(1)
plt.plot (db, p2[i], 'c')
plt.title('Log-Linear Plot')
plt.ylabel('Power')
plt.xlabel('db')
plt.grid
plt.show()
plt.grid(True)
for i in range(1,100):
plt.figure(2)
plt.semilogy(db, p2[i], 'r')
plt.title('Linear Plot')
plt.ylabel('Power in Watts')
plt.xlabel('Power in Decibels')
plt.show()
plt.grid(True)
I think this is probably what you're after.
You were using the loop to update the array, but also had plot and show in the loop, which would create many separate plots. There's no need to call plot point by point, so that came out of the loop.
Also, though, using Numpy's vectorization, you don't even need to do the calculation in the loop, so I took that out as well, which left no loop at all.
p1 = 1*(10**-3)
p2 = np.arange(1,101)
newlist = []
db = 10*np.log10(p2/p1)
plt.plot (db, p2, 'c')
plt.title('Log-Linear Plot')
plt.ylabel('Power')
plt.xlabel('db')
plt.grid(True)
plt.show()
plt.figure(2)
plt.semilogy(db, p2, 'r')
plt.title('Linear Plot')
plt.ylabel('Power in Watts')
plt.xlabel('Power in Decibels')
plt.grid(True)
plt.show()

Updating a plot doesn't clear old plots, if event trigger came from another figure?

I am updating a line plot. There is an event trigger that starts this updating. If the trigger came from the figure that contains the plot, everything is fine. However, if the trigger came from another figure, then weird results happen: the line that's been updated appears to leave its trace uncleared.
Here is an example:
import matplotlib.pyplot as plt
import numpy as np
def onclick(event):
for ii in np.linspace(0., np.pi, 100):
y1 = y * np.sin(ii)
line1.set_ydata(y1)
ax.draw_artist(line1)
line2.set_ydata(-y1)
ax2.draw_artist(line2)
ax2.set_ylim(y1.min(), y1.max())
fig.canvas.update()
plt.pause(0.1)
x = np.linspace(0., 2*np.pi, 100)
y = np.sin(x)
fig = plt.figure()
ax = fig.add_subplot(1, 2, 1)
line1 = ax.plot(x, y)[0]
ax2 = fig.add_subplot(1, 2, 2)
line2 = ax2.plot(x, y)[0]
fig2 = plt.figure()
cid = fig2.canvas.mpl_connect('button_press_event', onclick)
plt.show()
What I see on screen:
Please note, if you resize the plot, or save it as figure, then all the residue image will be gone.
On the other hand, if change one line to:
cid = fig2.canvas.mpl_connect('button_press_event', onclick)
then it is correct. The animation works as intended.
Not sure what fig.canvas.update() would do. If you replace that line by
fig.canvas.draw_idle()
it should work as expected. In that case you would not need to draw the artists individually.

Redrawing legend when the figure is closed

Using matplotlib, I'm trying to execute a callback function when a figure is closed, which redraws the figure legend. However, when I call ax.legend(), it seems to block any further code being executed. So in the code below, 'after' is never printed.
Could someone explain why this is? And is it possible for me to run code after the legend() call, but before the figure closes? The ultimate goal is to save two different versions of a figure when it is closed, redrawing the legend in between saves. Thanks.
from __future__ import print_function
import matplotlib.pyplot as plt
def handle_close(evt):
f = evt.canvas.figure
print('Figure {0} closing'.format(f.get_label()))
ax = f.get_axes()
print('before')
leg = ax.legend() # This line causes a problem
print('after') # This line (and later) is not executed
xs = range(0, 10, 1)
ys = [x*x for x in xs]
zs = [3*x for x in xs]
fig = plt.figure('red and blue')
ax = fig.add_subplot(111)
ax.plot(xs, ys, 'b-', label='blue plot')
ax.plot(xs, zs, 'r-', label='red plot')
fig.canvas.mpl_connect('close_event', handle_close)
ax.legend()
plt.show()
Ok, sorry, I have figured it out. f.get_axes() returns a list of axes objects. So the later call to ax.legend() doesn't work correctly.
Changing to the lines below fixes the problem:
axs = f.get_axes()
for ax in axs:
leg = ax.legend()
I'm still not sure why this didn't produce some kind of interpreter error though.

matplotlib: multiple plots on one figure

I have some code:
import matplotlib.pyplot as plt
def print_fractures(fractures):
xpairs = []
ypairs = []
plt.figure(2)
plt.subplot(212)
for i in range(len(fractures)):
xends = [fractures[i][1][0], fractures[i][2][0]]
yends = [fractures[i][1][1], fractures[i][2][1]]
xpairs.append(xends)
ypairs.append(yends)
for xends,yends in zip(xpairs,ypairs):
plt.plot(xends, yends, 'b-', alpha=0.4)
plt.show()
def histogram(spacings):
plt.figure(1)
plt.subplot(211)
plt.hist(spacings, 100)
plt.xlabel('Spacing (m)', fontsize=15)
plt.ylabel('Frequency (count)', fontsize=15)
plt.show()
histogram(spacings)
print_fractures(fractures)
This code will produce the following output:
My questions are:
1) Why are two separate figures being created? I thought the subplot command would combine them into one figure. I thought it might be the multiple plt.show() commands, but I tried commenting those out and only calling it once from outside my functions and I still got 2 windows.
2) How can I combine them into 1 figure properly? Also, I would want figure 2 axes to have the same scale (i.e. so 400 m on the x axis is the same length as 400 m on the y-axis). Similarly, I'd like to stretch the histogram vertically as well - how is this accomplished?
As you observed already, you cannot call figure() inside each function if you intend to use only one figure (one Window). Instead, just call subplot() without calling show() inside the function. The show() will force pyplot to create a second figure IF you are in plt.ioff() mode. In plt.ion() mode you can keep the plt.show() calls inside the local context (inside the function).
To achieve the same scale for the x and y axes, use plt.axis('equal'). Below you can see an illustration of this prototype:
from numpy.random import random
import matplotlib.pyplot as plt
def print_fractures():
plt.subplot(212)
plt.plot([1,2,3,4])
def histogram():
plt.subplot(211)
plt.hist(random(1000), 100)
plt.xlabel('Spacing (m)', fontsize=15)
plt.ylabel('Frequency (count)', fontsize=15)
histogram()
print_fractures()
plt.axis('equal')
plt.show()

Categories