Dynamically updating Matplotlib - python

I want to update a single Matplotlib figure with each timestep in my Notebook. I have referenced numerous API resources and examples forum answers here on StackOverflow, however, all of the proposed code either did not graph or displayed a new figure with each timestep, like this answer,
import matplotlib.pyplot as plt
import time
import random
from collections import deque
import numpy as np
# simulates input from serial port
def random_gen():
while True:
val = random.randint(1,10)
yield val
time.sleep(0.1)
a1 = deque([0]*100)
ax = plt.axes(xlim=(0, 20), ylim=(0, 10))
d = random_gen()
line, = plt.plot(a1)
plt.ion()
plt.ylim([0,10])
plt.show()
for i in range(0,20):
a1.appendleft(next(d))
datatoplot = a1.pop()
line.set_ydata(a1)
plt.draw()
print a1[0]
i += 1
time.sleep(0.1)
plt.pause(0.0001) #add this it will be OK.
and this answer.
import numpy as np
import matplotlib.pyplot as plt
plt.axis([0, 10, 0, 1])
for i in range(10):
y = np.random.random()
plt.scatter(i, y)
plt.pause(0.1)
How can I update a figure with each timestep in Python, via Matplotlib or possibly other means? I appreciate your perspectives.
Thank you :)

Real-time drawing by entering the interactive mode of matplotlib.
If you only use plt.show() to draw, the program will stop executing the subsequent program, so open the drawing window through plt.ion() to enter the interactive mode, use the program plt.plot() to draw in real time, after the drawing is completed, use plt .ioff() exits the interactive mode and uses plt.show() to display the final image data. If plt.show() is not added at the end, it will flash back.
import matplotlib.pyplot as plt
import numpy as np
ax=[]
ay=[]
bx=[]
by=[]
num=0
plt.ion()
# plt.rcParams['savefig.dpi'] = 200
# plt.rcParams['figure.dpi'] = 200
plt.rcParams['figure.figsize'] = (10, 10)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['lines.linewidth'] = 0.5
while num<100:
plt.clf()
plt.suptitle("TITLE",fontsize=30)
g1=np.random.random()
ax.append(num)
ay.append(g1)
agraphic=plt.subplot(2,1,1)
agraphic.set_title('TABLE1')
agraphic.set_xlabel('x',fontsize=10)
agraphic.set_ylabel('y', fontsize=20)
plt.plot(ax,ay,'g-')
#table2
bx.append(num)
by.append(g1)
bgraghic=plt.subplot(2, 1, 2)
bgraghic.set_title('TABLE2')
bgraghic.plot(bx,by,'r^')
plt.pause(0.4)
if num == 15:
plt.savefig('picture.png', dpi=300)
#break
num=num+1
plt.ioff()
plt.show()

Related

how to run a loop and update a plot at the same time in python

i am trying to write a code where i am running a function that controls the output of a particular device for a set period of time. also i have a second function that plots data from a sensor in real time. i am using multithreading module to run both the functions. however the plot becomes unresponsive. is there a better way of doing the same. will be very helpful if someone can comment on this.
i have presented a dummy code
`
import random
from itertools import count
from matplotlib import pyplot as plt
import time
import numpy as np
from IPython.display import display, clear_output
def funa(i):
start=time.time()
while time.time()-start<30:
i=i+1
print(i)
def show_fig():
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
start=time.time()
# Define and update plot
X=[]
Y=[]
while time.time()-start<30:
x = time.time()-start
X.append(x)
y = np.cos(x)
Y.append(y)
ax.cla()
ax.plot(X, Y)
display(fig)
clear_output(wait = True)
plt.pause(0.1)
import threading
thread1=threading.Thread(target=funa,args=(1,))
thread2=threading.Thread(target=show_fig)
a=time.time()
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(time.time()-a)
`

matplotlib.close() does not close plot

I'm using Python 3.6 in jupyter notebook. plt.close does not close plot. I tried with plt.ion() also and many other ways.
I want to display image, then wait for pause or input() and then remove the previous image and show the new one.
import matplotlib.pyplot as plt
from time import sleep
from scipy import eye
plt.imshow(eye(3))
plt.show()
sleep(1)
plt.close()
Here is an example that shows a sequence of plots, each for one second. Essential are the commants plt.show(block = False) and plt.pause(1) instead of sleep(1):
import numpy as np
import matplotlib.pyplot as plt
def show_image(n):
fig, ax = plt.subplots()
x = np.linspace(0,1,100)
y = x**n
ax.plot(x,y, label = 'x**{}'.format(n))
ax.legend()
plt.show(block=False)
plt.pause(1)
plt.close(fig)
for i in range(10):
show_image(i)
If I understand correctly, what you want is to show a plot, wait 1 second, then let it close automatically.
This would be achieved as follows.
import matplotlib.pyplot as plt
from scipy import eye
plt.imshow(eye(3))
def show_and_close(sec):
timer = plt.gcf().canvas.new_timer(interval=sec*1000)
timer.add_callback(lambda : plt.close())
timer.single_shot = True
timer.start()
plt.show()
show_and_close(1)

How to set matplotlib to show every image of an array?

How to set matplotlib to show every image of an array?
I want that everytime i click on the right arrow, it shows the next image and so on...
Is that possible?
width = 14
height = 14
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
data_images = X_train.reshape(X_train.shape[0],width,height)
print "Shape " ,data_images.shape #Shape (50000L, 14L, 14L)
plt.imshow(data_images[0])
plt.show()
I wanted to pass the "data_images" variable to plt.imshow and so everytime i clicked on next on the matplotlib, it would show the next image.
Working example with plt.connect().
You can change image by pressing any key.
import matplotlib.pyplot as plt
data_images = [
[[1,2,3],[1,2,3],[1,2,3]],
[[1,1,1],[2,2,2],[3,3,3]],
[[1,2,1],[2,2,2],[1,2,1]],
]
#----------------------------------
index = 0
def toggle_images(event):
global index
index += 1
if index < len(data_images):
plt.imshow(data_images[index])
plt.draw()
else:
plt.close()
#----------------------------------
plt.imshow(data_images[index])
plt.connect('key_press_event', toggle_images)
plt.show()
I would do this using ipywidgets within the IPython notebook. Here's an example:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact
images = np.random.random((500, 14, 14))
def browse_images(images):
N = images.shape[0]
def view_image(i=0):
plt.imshow(images[i], cmap='gray', interpolation='nearest')
plt.title('Image {0}'.format(i))
interact(view_image, i=(0, N-1))
browse_images(images)
Edit: the result, in the notebook page, will look something like this:
You can press the left or right arrow to advance the slider and view the next image.
You can do a bit better in the notebook than using inline:
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
from ipywidgets import interact
from IPython.display import display
images = np.random.random((500, 14, 14))
fig, ax = plt.subplots()
im = ax.imshow(images[0], cmap='gray', interpolation='nearest')
def browse_images(images):
N = images.shape[0]
def view_image(i=0):
im.set_data(images[i])
ax.set_title('Image {0}'.format(i))
fig.canvas.draw_idle()
interact(view_image, i=(0, N-1))
and then in the next cell
browse_images(images)
which will give you a pannable/zoom able figure. In mpl 1.5.0 you also get the pixel values under the cursor by default.
(I tested this on tmpnb.org)

Pylab only updating after raw_input call

I'm trying to continuously read from a file and plot using matplotlib as a way to create a bit of an animation. Here is the working code:
import numpy as np
import pylab
import time
print "start"
pylab.ion() # Unfortunately, will still need to run pylab.show() all the time
fig = pylab.figure()
ax = fig.add_subplot(1,1,1)
ax.set_xlim((0,128))
ax.set_ylim((0,128))
#Initialize the circle object to a silly location
f1 = pylab.Circle((60,68), radius=2, fc='y')
ax.add_patch(f1)
pylab.show()
# Start the animation
for i in range(0,1000):
if(i%2 == 0):
f1.center = 30, 30
else:
f1.center = 40, 40
pylab.show()
raw_input("Press Enter to continue...")
print("Updating")
#time.sleep(2) # This is going to be used later
Now, I want to replace the user input with a sleep timer:
import numpy as np
import pylab
import time
print "start"
pylab.ion() # Unfortunately, will still need to run pylab.show() all the time
fig = pylab.figure()
ax = fig.add_subplot(1,1,1)
ax.set_xlim((0,128))
ax.set_ylim((0,128))
#Initialize the circle object to a silly location
f1 = pylab.Circle((60,68), radius=2, fc='y')
ax.add_patch(f1)
pylab.show()
# Start the animation
for i in range(0,1000):
if(i%2 == 0):
f1.center = 30, 30
else:
f1.center = 40, 40
pylab.show()
#raw_input("Press Enter to continue...")
print("Updating")
time.sleep(2) # This is going to be used later
But this code doesn't work! It sleeps, but nothing is updated. What am I doing wrong?
You need to replace time.sleep(2) with pylab.pause(2) as indicated in the comments of this question.

Can I generate and show a different image during each loop with Matplotlib?

I am new to Matplotlib and Python. I mostly use Matlab. Currently, I am working with a Python code where I want to run a loop. In each loop, I will do some data processing and then show an image based on the processed data. When I go to the next loop, I want the previously stored image to be closed and generate a new image based on the latest data.
In other words, I want a python code equivalent to the following Matlab code:
x = [1 2 3];
for loop = 1:3
close all;
y = loop * x;
figure(1);
plot(x,y)
pause(2)
end
I tried the following python code to achieve my goal:
import numpy as np
import matplotlib
import matplotlib.lib as plt
from array import array
from time import sleep
if __name__ == '__main__':
x = [1, 2, 3]
for loop in range(0,3):
y = numpy.dot(x,loop)
plt.plot(x,y)
plt.waitforbuttonpress
plt.show()
This code puts all plots superimposed in the same figure. If I put the plt.show() command inside the for loop, only the first image is shown. Therefore, I could not replicate my Matlab code in Python.
try this:
import numpy
from matplotlib import pyplot as plt
if __name__ == '__main__':
x = [1, 2, 3]
plt.ion() # turn on interactive mode
for loop in range(0,3):
y = numpy.dot(x, loop)
plt.figure()
plt.plot(x,y)
plt.show()
_ = input("Press [enter] to continue.")
if you want to close the previous plot, before showing the next one:
import numpy
from matplotlib import pyplot as plt
if __name__ == '__main__':
x = [1, 2, 3]
plt.ion() # turn on interactive mode, non-blocking `show`
for loop in range(0,3):
y = numpy.dot(x, loop)
plt.figure() # create a new figure
plt.plot(x,y) # plot the figure
plt.show() # show the figure, non-blocking
_ = input("Press [enter] to continue.") # wait for input from the user
plt.close() # close the figure to show the next one.
plt.ion() turns on interactive mode making plt.show non-blocking.
and heres is a duplicate of your matlab code:
import numpy
import time
from matplotlib import pyplot as plt
if __name__ == '__main__':
x = [1, 2, 3]
plt.ion()
for loop in xrange(1, 4):
y = numpy.dot(loop, x)
plt.close()
plt.figure()
plt.plot(x,y)
plt.draw()
time.sleep(2)

Categories