I'm working on a simple 3D animation in matplotlib within an IPython notebook, but my points are changing alpha values mysteriously:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
from IPython.display import HTML
import requests
%matplotlib inline
requests.get('https://gist.github.com/duhaime/023897b9bda70e7728c7db9792a11bd3/raw/b632e2ea9fb693f303908f546a684a3afcc329c0/data.npy')
X = np.load('data.npy')
def update_points(time, points):
arr = np.array([[ X[time][i][0], X[time][i][1] ] for i in range(int(X.shape[1]))])
points.set_offsets(arr) # set x, y values
points.set_3d_properties(X[time][:,2][:], zdir='z') # set z value
def get_plot():
fig = plt.figure()
ax = p3.Axes3D(fig)
ax.set_xlim(-10,10)
ax.set_ylim(-10,10)
ax.set_zlim(-10,10)
points = ax.scatter(X[0][:,0][:], X[0][:,1][:], X[0][:,2][:]) # x,y,z vals
return animation.FuncAnimation(fig,
update_points,
200, # steps
interval=100, # how often to refresh plot
fargs=(points,),
blit=False
).to_jshtml()
HTML(get_plot())
Does anyone know why the points' alpha values are changing? Any suggestions others can offer would be very helpful!
Use the depthshade argument of Axes3d.scatter
depthshade Whether or not to shade the scatter markers to give the appearance of depth. Default is True.
Set this to False to have no alpha changes in your plot.
This doesn't explain what's mutating the alpha values, but one can mutate them back to 1 in the update function:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
from IPython.display import HTML
import requests
%matplotlib inline
requests.get('https://gist.github.com/duhaime/023897b9bda70e7728c7db9792a11bd3/raw/b632e2ea9fb693f303908f546a684a3afcc329c0/data.npy')
X = np.load('data.npy')
def update_points(time, points):
arr = np.array([[ X[time][i][0], X[time][i][1] ] for i in range(int(X.shape[1]))])
points.set_offsets(arr) # set x, y values
points.set_3d_properties(X[time][:,2][:], zdir='z') # set z value
points.set_alpha(1)
def get_plot(lim=3):
fig = plt.figure()
ax = p3.Axes3D(fig)
ax.set_xlim(-lim, lim)
ax.set_ylim(-lim, lim)
ax.set_zlim(-lim, lim)
points = ax.scatter(X[0][:,0][:], X[0][:,1][:], X[0][:,2][:]) # x,y,z vals
return animation.FuncAnimation(fig,
update_points,
200, # steps
interval=100, # how often to refresh plot
fargs=(points,),
blit=False
).to_jshtml()
HTML(get_plot())
Related
The question, in brief, is: is it possible (with the tools of matplotlib.animation or other modules for python) to obtain a slow-motion on certain frames of the animation?
Some context:
I have a matplotlib animated plot in which I am varying one variable and showing a contour plot over two other ones. My idea was to slow down the animation while I am near the maximum of the function, so that I can more clearly pinpoint it, while accelerate far from it where there is not much interest.
At the moment, my best idea is to double the frames closest to the maximum, but can someone have a better idea?
Thank you everyone!
Code snippet:
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
X = np.linspace(1,10, 100)
Y = np.linspace(1,10, 100)
R = np.linspace(-1, 1, 100)
ims = []
for r in R:
z = func(X, Y, r)
im = plt.imshow(z)
ims.append(im)
if check_r(r):
ims.append(im)
where func() is a function that return a (len(X), len(Y)) array that depends on r (for instance Z[i,j] = X[i]**r * Y[j]**(1-r) or whatever, while check_r() test if r is within the range of the values that need to be maximized.
Your idea is the best, I think. And I've found another way using matplotlib animation. The idea is that use frames as slow delay, by making same points.
In this example just sin curve is plotted but it will be applied other functions.
(most of code is took from here)
import numpy as np
import matplotlib.animation as animation
import matplotlib.pylab as plt
import pandas as pd
TWOPI = 2*np.pi
fig, ax = plt.subplots()
# making frames "delay"
frames = np.arange(0.0, TWOPI, 0.1)
frames = np.insert(frames, 17, [1.7]*5)
frames = np.insert(frames, 16, [1.6]*5)
frames = np.insert(frames, 15, [1.5]*5)
t = np.arange(0.0, TWOPI, 0.001)
s = np.sin(t)
l = plt.plot(t, s)
ax = plt.axis([0,TWOPI,-1,1])
redDot, = plt.plot([0], [np.sin(0)], 'ro')
def animate(i):
redDot.set_data(i, np.sin(i))
return redDot,
myAnimation = animation.FuncAnimation(fig, animate, frames=frames,
interval=100, blit=True, repeat=True)
I am trying to plot z transforms of some signals using the mpl_toolkits in python, but the output is totally blank. What am I doing wrong? The input numpy arrays have non-zero values. Here is my code:
import numpy as np
import matplotlib.pyplot as plt
import math
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# initialize r and theta
r = 10
theta = r*np.linspace(-math.pi,math.pi,100)
theta = np.meshgrid(theta,theta)[0]
# calculate z
z = r*(np.cos(theta) + 1j*np.sin(theta))
# calculate z transform for first signal
xs1 = np.abs(z/(z-2))
# calculate z transform for second signal
xs2 = np.abs((np.power(z,3)+2*np.power(z,2)+3*z+3)/np.power(z,3))
# plot the transforms
fig1 = plt.figure(0)
ax1 = fig1.add_subplot(111, projection='3d')
fig2 = plt.figure(1)
ax2 = fig2.add_subplot(111, projection='3d')
ax1.plot_surface(z.real,z.imag,xs1,cmap = cm.coolwarm)
ax2.plot_surface(z.real,z.imag,xs2,cmap = cm.coolwarm)
plt.show()
Here is one of the output:
I'm using Matplotlib's function hist2d() and I want to unpack the output in order to further use it. Here's what I do: I simply load with numpy a 2-column file containing my data and use the following code
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np
traj = np.loadtxt('trajectory.txt')
x = traj[:,0]
y = traj[:,1]
M, xe, ye, img = plt.hist2d(x, y, bins = 80, norm = LogNorm())
plt.imshow(M)
plt.show()
The result I get is the following:
Instead, if I try to directly plot the hist2d results without unpacking them:
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np
traj = np.loadtxt('trajectory.txt')
x = traj[:,0]
y = traj[:,1]
plt.hist2d(x, y, bins = 80, norm = LogNorm())
plt.show()
I get the whole plot without the strange blue box. What am I doing wrong?
You can create a histogram plot directly with plt.hist2d. This calculates the histogram and plots it to the current axes. There is no need to show it yet another time using imshow.
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np; np.random.seed(9)
x = np.random.rayleigh(size=9900)
y = np.random.rayleigh(size=9900)
M, xe, ye, img = plt.hist2d(x, y, bins = 80, norm = LogNorm())
plt.show()
Or, you may first calculate the histogram and afterwards plot the result as an image to the current axes. Note that the histogram produced by numpy is transposed, see Matplotlib 2D histogram seems transposed, making it necessary to call imshow(M.T). Also note that in order to obtain the correct axes labeling, you need to set the imshow's extent to the extremal values of the xe and ye edge arrays.
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import numpy as np; np.random.seed(9)
x = np.random.rayleigh(size=9900)
y = np.random.rayleigh(size=9900)
M, xe, ye = np.histogram2d(x, y, bins = 80)
extent = [xe[0], xe[-1], ye[0], ye[-1]]
plt.imshow(M.T, extent=extent, norm = LogNorm(), origin="lower")
plt.show()
I just wondered about the performance of matplotlib.pyplot.savefig(). It's a simple map. With only the country-borders it takes around 1 sec.
When i print a grid of only 21x19 values with text() on the map it needs 3 sec! Why is that so? Is there a workatound?
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import pickle
import numpy as np
import time
plt.clf()
m = pickle.load(open('a.pickle','rb'))
c = pickle.load(open('b.pickle','rb'))
x, y = m(lons, lats) # compute map proj coordinates
for i in range(322,343,1): # lons
for j in range(97,116,1): # lats
plt.text(x[j,i], y[j,i], int(round(data[j,i])),fontsize=7, color='k', ha='center', va='center')
print time.clock()-t1
plt.savefig('/var/www/img/test.png', bbox_inches='tight',pad_inches=0.05, dpi=100)
print time.clock()-t1
plt.close('all')
I have a bar graph which retrieves its y values from a dict. Instead of showing several graphs with all the different values and me having to close every single one, I need it to update values on the same graph. Is there a solution for this?
Here is an example of how you can animate a bar plot.
You call plt.bar only once, save the return value rects, and then call rect.set_height to modify the bar plot.
Calling fig.canvas.draw() updates the figure.
import matplotlib
matplotlib.use('TKAgg')
import matplotlib.pyplot as plt
import numpy as np
def animated_barplot():
# http://www.scipy.org/Cookbook/Matplotlib/Animations
mu, sigma = 100, 15
N = 4
x = mu + sigma*np.random.randn(N)
rects = plt.bar(range(N), x, align = 'center')
for i in range(50):
x = mu + sigma*np.random.randn(N)
for rect, h in zip(rects, x):
rect.set_height(h)
fig.canvas.draw()
fig = plt.figure()
win = fig.canvas.manager.window
win.after(100, animated_barplot)
plt.show()
I've simplified the above excellent solution to its essentials, with more details at my blogpost:
import numpy as np
import matplotlib.pyplot as plt
numBins = 100
numEvents = 100000
file = 'datafile_100bins_100000events.histogram'
histogramSeries = np.loadtext(file)
fig, ax = plt.subplots()
rects = ax.bar(range(numBins), np.ones(numBins)*40) # 40 is upper bound of y-axis
for i in range(numEvents):
for rect,h in zip(rects,histogramSeries[i,:]):
rect.set_height(h)
fig.canvas.draw()
plt.pause(0.001)