I would essentially like to do the following:
import matplotlib.pyplot as plt
import numpy as np
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
for i in range(10):
ax1.scatter(i, np.sqrt(i))
ax1.show() # something equivalent to this
ax2.scatter(i, i**2)
That is, each time a point is plotted on ax1, it is shown - ax2 being shown once.
You cannot show an axes alone. An axes is always part of a figure. For animations you would want to use an interactive backend. Then the code in a jupyter notebook could look like
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig1, ax1 = plt.subplots()
fig2, ax2 = plt.subplots()
frames = 10
x = np.arange(frames)
line1, = ax1.plot([],[], ls="", marker="o")
line2, = ax2.plot(x, x**2, ls="", marker="o")
ax2.set_visible(False)
def animate(i):
line1.set_data(x[:i], np.sqrt(x[:i]))
ax1.set_title(f"{i}")
ax1.relim()
ax1.autoscale_view()
if i==frames-1:
ax2.set_visible(True)
fig2.canvas.draw_idle()
ani = FuncAnimation(fig1, animate, frames=frames, repeat=False)
plt.show()
If you want to change plots dynamically I'd suggest you don't redraw the whole plot every time, this will result in very laggy behavior. Instead you could use Blit to do this. I used it in a previous project. Maybe it can help you too if you just take the parts from this you need:
Python project dynamically updating plot
Related
I am trying a code to plot a live graph but i always land up with an empty plot. Here is my code :
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
import random
style.use('fivethirtyeight')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
y = random.randint(0,100) # generate random data
x = i # set x as iteration number
ax1.clear()
ax1.plot(x, y, 'ro')
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
I get warning but i am using plt.show() to show animation. Not sure what i am doing wrong :
UserWarning: Animation was deleted without rendering anything. This is most likely not intended. To prevent deletion, assign the Animation to a variable, e.g. `anim`, that exists until you have outputted the Animation using `plt.show()` or `anim.save()`.
warnings.warn(
I want to give all the figures in my code a single title #Variable_cycles. Figures are not subplots but plotted separately. I am using %matplotlib to show plots in separate window. As far as i know plt.rcParams has no such key
import matplotlib.pyplot as plt
%matplotlib
plt.figure(1), plt.scatter(x,y,marker='o'),
plt.title("Variable_cycles"),
plt.show
plt.figure(2),
plt.scatter(x,y,marker='*'),
plt.title("Variable_cycles"),
plt.show
I don't believe there is such a setting in rcParams or similar, but if there are options you are setting for all figures, you could create a simple helper function to create the figure, apply those settings (e.g. the title, axes labels, etc), and return the figure object, then you just need to call that function once for each new figure. A simple example would be:
import matplotlib.pyplot as plt
%matplotlib
def makefigure():
# Create figure and axes
fig, ax = plt.subplots()
# Set title
fig.suptitle('Variable cycles')
# Set axes labels
ax.set_xlabel('My xlabel')
ax.set_ylabel('My ylabel')
# Put any other common settings here...
return fig, ax
fig1, ax1 = makefigure()
ax1.scatter(x, y, marker='o')
fig2, ax2 = makefigure()
ax2.scatter(x, y, marker='*')
I'm currently having an issue with saving colors and matplotlib. When I run the following code I get the expected result
import matplotlib.pyplot as plt
fig = plt.figure()
fig.patch.set_facecolor('black')
plt.title("test")
ax = plt.gca()
ax.patch.set_facecolor('black')
fig.patch.set_facecolor('xkcd:mint green')
plt.show()
Here is a screenshot of what is shown, which is the result I'm expecting.
However, when I run the save function either through python or by manually clicking save on the figure it results in the following image, without the colored borders.
Code to reproduce image above
import matplotlib.pyplot as plt
fig = plt.figure()
fig.patch.set_facecolor('black')
plt.title("test")
ax = plt.gca()
ax.patch.set_facecolor('black')
fig.patch.set_facecolor('xkcd:mint green')
# Also doesn't work with fig.savefig
plt.savefig("test.png", dpi=200)
#JohanC pointed out in the comments it takes a face color arguement.
Fixed code
import matplotlib.pyplot as plt
fig = plt.figure()
fig.patch.set_facecolor('black')
plt.title("test")
ax = plt.gca()
ax.patch.set_facecolor('black')
# Also doesn't work with fig.savefig
plt.savefig("test.png", facecolor='xkcd:mint green', dpi=200)
I want to see how a plot varies with different values using a loop. I want to see it on the same plot. But i do not want to remains of the previous plot in the figure. In MATLAB this is possible by creating a figure and just plotting over the same figure. Closing it when the loop ends.
Like,
fh = figure();
%for loop here
%do something with x and y
subplot(211), plot(x);
subplot(212), plot(y);
pause(1)
%loop done
close(fh);
I am not able to find the equivalent of this in matplotlib. Usually all the questions are related to plotting different series on the same plot, which seems to come naturally on matplotlib, by plotting several series using plt.plot() and then showing them all finally using plt.show(). But I want to refresh the plot.
There are essentially two different ways to create animations in matplotlib
interactive mode
Turning on interactive more is done using plt.ion(). This will create a plot even though show has not yet been called. The plot can be updated by calling plt.draw() or for an animation, plt.pause().
import matplotlib.pyplot as plt
x = [1,1]
y = [1,2]
fig, (ax1,ax2) = plt.subplots(nrows=2, sharex=True, sharey=True)
line1, = ax1.plot(x)
line2, = ax2.plot(y)
ax1.set_xlim(-1,17)
ax1.set_ylim(-400,3000)
plt.ion()
for i in range(15):
x.append(x[-1]+x[-2])
line1.set_data(range(len(x)), x)
y.append(y[-1]+y[-2])
line2.set_data(range(len(y)), y)
plt.pause(0.1)
plt.ioff()
plt.show()
FuncAnimation
Matplotlib provides an animation submodule, which simplifies creating animations and also allows to easily save them. The same as above, using FuncAnimation would look like:
import matplotlib.pyplot as plt
import matplotlib.animation
x = [1,1]
y = [1,2]
fig, (ax1,ax2) = plt.subplots(nrows=2, sharex=True, sharey=True)
line1, = ax1.plot(x)
line2, = ax2.plot(y)
ax1.set_xlim(-1,18)
ax1.set_ylim(-400,3000)
def update(i):
x.append(x[-1]+x[-2])
line1.set_data(range(len(x)), x)
y.append(y[-1]+y[-2])
line2.set_data(range(len(y)), y)
ani = matplotlib.animation.FuncAnimation(fig, update, frames=14, repeat=False)
plt.show()
An example to animate a sine wave with changing frequency and its power spectrum would be the following:
import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
x = np.linspace(0,24*np.pi,512)
y = np.sin(x)
def fft(x):
fft = np.abs(np.fft.rfft(x))
return fft**2/(fft**2).max()
fig, (ax1,ax2) = plt.subplots(nrows=2)
line1, = ax1.plot(x,y)
line2, = ax2.plot(fft(y))
ax2.set_xlim(0,50)
ax2.set_ylim(0,1)
def update(i):
y = np.sin((i+1)/30.*x)
line1.set_data(x,y)
y2 = fft(y)
line2.set_data(range(len(y2)), y2)
ani = matplotlib.animation.FuncAnimation(fig, update, frames=60, repeat=True)
plt.show()
If you call plt.show() inside the loop you will see the plot for each element on the loop as long as you close the window containing the figure. The process, will be plot for the first element, then if you close the window you will see the plot for the second element in the loop, etc
I am trying to animate a violinplot, so I have started off with something I think should be very basic, but it is not working. I think the problem is that violinplot doesn't accept set_data, but I don't otherwise know how to pass the changing data to violinplot. For this example I would like a plot where the mean slowly shifts to higher values. If I am barking up the wrong tree, please advise on a code which does work to animate violinplot.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
data = np.random.rand(100)
def animate(i):
v.set_data(data+i) # update the data
return v
v = ax.violinplot([])
ax.set_ylim(0,200)
v_ani = animation.FuncAnimation(fig, animate, np.arange(1, 200),
interval=50, blit=True)
Indeed, there is no set_data method for the violinplot. The reason is probably, that there is a lot of calculations going on in the background when creating such a plot and it consists of a lot of different elements, which are hard to update.
The easiest option would be to simply redraw the violin plot and not use blitting.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
data = np.random.normal(loc=25, scale=20, size=100)
def animate(i, data):
ax.clear()
ax.set_xlim(0,2)
ax.set_ylim(0,200)
data[:20] = np.random.normal(loc=25+i, scale=20, size=20)
np.random.shuffle(data)
ax.violinplot(data)
animate(0)
v_ani = animation.FuncAnimation(fig, animate, np.arange(1, 200),
fargs=(data,), interval=50, blit=False)
plt.show()