How to update a plot in matplotlib
You essentially have two options:
Do exactly what you're currently doing, but call
graph1.clear()
andgraph2.clear()
before replotting the data. This is the slowest, but most simplest and most robust option.Instead of replotting, you can just update the data of the plot objects. You'll need to make some changes in your code, but this should be much, much faster than replotting things every time. However, the shape of the data that you're plotting can't change, and if the range of your data is changing, you'll need to manually reset the x and y axis limits.
To give an example of the second option:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 6*np.pi, 100)
y = np.sin(x)
# You probably won't need this if you're embedding things in a tkinter plot...
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma
for phase in np.linspace(0, 10*np.pi, 500):
line1.set_ydata(np.sin(x + phase))
fig.canvas.draw()
fig.canvas.flush_events()
update plots on matplotlib
Replace this:
self.plot.remove()
with this:
self.plot.clear()
After that it should work.
Is there a way to update the matplotlib plot without closing the window?
One option to update the plot in a loop is to turn on interactive mode and to update the plot using pause.
For example:
import numpy as np
import matplotlib.pyplot as plt
point = plt.plot(0, 0, "g^")[0]
plt.ylim(0, 5)
plt.xlim(0, 5)
plt.ion()
plt.show()
start_time = time.time()
t = 0
while t < 4:
end_time = time.time()
t = end_time - start_time
print(t)
point.set_data(t, t)
plt.pause(1e-10)
However, for more advanced animation I would propose to use the animation class.
Dynamically updating plot in matplotlib
Is there a way in which I can update the plot just by adding more point[s] to it...
There are a number of ways of animating data in matplotlib, depending on the version you have. Have you seen the matplotlib cookbook examples? Also, check out the more modern animation examples in the matplotlib documentation. Finally, the animation API defines a function FuncAnimation which animates a function in time. This function could just be the function you use to acquire your data.
Each method basically sets the data
property of the object being drawn, so doesn't require clearing the screen or figure. The data
property can simply be extended, so you can keep the previous points and just keep adding to your line (or image or whatever you are drawing).
Given that you say that your data arrival time is uncertain your best bet is probably just to do something like:
import matplotlib.pyplot as plt
import numpy
hl, = plt.plot([], [])
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()
Then when you receive data from the serial port just call update_line
.
Python: Update plot instead of creating a new one
I think the function ion
and clf
could do the trick.
import numpy as np
import numpy.random as npr
import matplotlib.pyplot as plt
import seaborn as sns
#Constants
J = 1
h = 1
kbT = 1
beta = 1
#Grid
L = 20 #Dimensions
N = L**2 #Total number of grid points
#Initial configuration
spins = 2*np.random.randint(2, size = (L,L))-1
E = []
i = 0
plt.ion()
plt.figure()
plt.show()
while i < 100000:
for i in range(1,N):
i += 1
s = tuple(npr.randint(0, L, 2)) # Random initial coordinate
# x and y coordinate
(sx, sy) = s
# Periodic boundary condition
sl = (sx-1, sy)
sr = ((sx+1)%L, sy)
sb = (sx, sy-1)
st = (sx, (sy+1)%L)
# Energy
E = spins[s] * ( spins[sl] + spins[sr] + spins[sb] + spins[st] )
if E <= 0 : # If negative, flip
spins[s] *= -1
else:
x = np.exp(-E/kbT) # If positve, check condition
q = npr.rand()
if x > q:
spins[s] *= -1
# Plot (heatmap)
plt.clf()
sns.heatmap(spins, cmap = 'magma')
plt.pause(10e-10)
With the function ion
you are making interactive the plot, so you need to:
- Make it interactive
- Show the plot
- Clear the plot in your cycle
Here the reference for the ion
function.
Reference for clf
is here
Updating Matplotlib plot when clicked
There's nothing wrong with the way you bind your event. However, you only updated the data set and did not tell matplotlib
to do a re-plot with new data. To this end, I added the last 4 lines in the onclick
method. They are self-explanatory, but there are also comments.
import matplotlib.pyplot as plt
x = [1];
y = [1];
def onclick(event):
if event.button == 1:
x.append(event.xdata)
y.append(event.ydata)
#clear frame
plt.clf()
plt.scatter(x,y); #inform matplotlib of the new data
plt.draw() #redraw
fig,ax=plt.subplots()
ax.scatter(x,y)
fig.canvas.mpl_connect('button_press_event',onclick)
plt.show()
plt.draw()
NOTE: matplotlib
in my computer (ubuntu 14.04) changes the scale, so you probably want to look into how to fix the x-y scale.
Related Topics
How to Use Glob() to Find Files Recursively
Why Can't I Iterate Twice Over the Same Data
How to Find the Duplicates in a List and Create Another List With Them
How to Create a Tuple With Only One Element
Convert Hex String to Integer in Python
Combine Two Columns of Text in Pandas Dataframe
Using Module 'Subprocess' With Timeout
Concatenate Strings from Several Rows Using Pandas Groupby
How to Schedule Updates (F/E, to Update a Clock) in Tkinter
How to Print a Date in a Regular Format
Threading Pool Similar to the Multiprocessing Pool
How to Safely Create a Nested Directory
How to Create a New Column from the Output of Pandas Groupby().Sum()