ipython notebook 3.0.0
matplotlib 1.4.3
OS X 10.11.4
I am creating an interactive 3D scatter plot of a 3D data cube.
I've included here a toy example that generates the same problems I am encountering trying to plot my data cube.
If I generate a matplot window outside of the notebook, when I manually close it (clicking the red x) it stalls with 'the wheel' until I force quit.
#Generate matplot window outside of the notebook
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
#from matplot3d tutorial
def randrange(n, vmin, vmax):
return (vmax - vmin)*np.random.rand(n) + vmin
fig = plt.figure() ax = fig.add_subplot(111, projection='3d') n = 100 for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zl, zh)
ax.scatter(xs, ys, zs, c=c, marker=m)
ax.set_xlabel('X Label') ax.set_ylabel('Y Label') ax.set_zlabel('Z Label')
plt.show()
I've tried using mpld3 within the notebook but a non-interactive image displays along with the error
"TypeError: array([ 2., 20.]) is not JSON serializable"
#Use mpld3 within notebook
import matplotlib.pyplot as plt
import numpy as np
import mpld3
from mpl_toolkits.mplot3d import Axes3D
mpld3.enable_notebook()
def randrange(n, vmin, vmax):
return (vmax - vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zl, zh)
ax.scatter(xs, ys, zs, c=c, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
Some quick research into JSON serialization has been non-fruitful.
What is the best way to create an interactive 3D matplotlib scatter plot that won't stall?
In IPython, even if you aren't using the inline backend, it's best to use %matplotlib. This tells IPython and matplotlib to work together with eventloops and should help with the hang. To use the default GUI backend, use:
%matplotlib
Or to specify the qt backend:
%matplotlib qt
This avoids the need for plt.show() and the blocking of the kernel when plots are being drawn.
For best results, run this in he first cell of your notebook, on its own before any plotting commands.
Related
You can see I am using ax.plot but nothing happened.
Just call plt.show() when you've run all of your graph creation code:
import numpy as np
import matplotlib.pyplot as plt
x= np.arange(-10, 10, 0.1)
fig, ax = plt.subplots()
ax.plot(x, np.cos(x))
plt.show()
I would like to know if it possible to save matplotlib animation with lossless quality (or even vectorial format)
I have the following animation from matplotlib examples
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=True)
plt.show()
I found this post from 2013 Can matplotlib animation output vector sequence? and at the time it was not possible.
Has anything changed and is it now possible to output the data into vector-like format?
Below is the code to build a standalone continuous colorbar. I would like to mask, with black, all values between -3 and 3.
import matplotlib.pyplot as plt
import matplotlib as mpl
fig, ax = plt.subplots(figsize=(8, .25))
cmap = mpl.cm.twilight
norm = mpl.colors.Normalize(vmin=-9.6, vmax=9.6)
cbar = mpl.colorbar.ColorbarBase(ax, cmap=cmap, norm=norm, orientation='horizontal', ticks=[-3,3])
The function colors.ListedColormap creates a new colormap from a list of colors. The following code retrieves these colors from an existing map and makes the desired modifications:
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
cmap = mpl.cm.get_cmap('twilight', 256)
norm = mpl.colors.Normalize(vmin=-9.6, vmax=9.6)
maskedcolors = cmap(np.linspace(0, 1, 256))
black = np.array([0, 0, 0, 1])
maskedcolors[int(round(norm(-3) * 256)) : int(round(norm(3) * 256)) + 1] = black
maskedcmp = mpl.colors.ListedColormap(maskedcolors)
fig, ax = plt.subplots(figsize=(8, .5))
cbar = mpl.colorbar.ColorbarBase(ax, cmap=maskedcmp, norm=norm, orientation='horizontal', ticks=[-3, 3])
fig.subplots_adjust(bottom=0.5)
plt.show()
I am plotting a function on the surface of a sphere. To test my code, I simply plot the spherical coordinate phi divided by pi. I get
Unexpectedly, half of the sphere is of the same color, and the colors on the other half aren't correct (at phi=pi, i should get 1, not 2). If I divide the data array by 2, the problem disappears. Can someone explain to me what is happening?
Here is the code I use:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
# prepare the sphere surface
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
phi = np.linspace(0,2*np.pi, 50)
theta = np.linspace(0, np.pi, 25)
x=np.outer(np.cos(phi), np.sin(theta))
y=np.outer(np.sin(phi), np.sin(theta))
z=np.outer(np.ones(np.size(phi)), np.cos(theta))
# prepare function to plot
PHI=np.outer(phi,np.ones(np.size(theta)))
THETA=np.outer(np.ones(np.size(phi)),theta)
data = PHI/np.pi
# plot
surface=ax.plot_surface(x, y, z, cstride=1, rstride=1,
facecolors=cm.jet(data),cmap=plt.get_cmap('jet'))
# add colorbar
m = cm.ScalarMappable(cmap=surface.cmap,norm=surface.norm)
m.set_array(data)
plt.colorbar(m)
plt.show()
There is a little bit of chaos in the code.
When specifying facecolors, there is no reason to supply a colormap, because the facecolors do not need to be retrieved from a colormap.
Colormaps range from 0 to 1. Your data ranges from 0 to 2. Hence half of the facecolors are just the same. So you first need to normalize the data to the (0,1)-range, e.g. using a Normalize instance, then you can apply the colormap.
norm = plt.Normalize(vmin=data.min(), vmax=data.max())
surface=ax.plot_surface(x, y, z, cstride=1, rstride=1,
facecolors=cm.jet(norm(data)))
For the colorbar you should then use the same colormap and the same normalization as for the plot itself.
m = cm.ScalarMappable(cmap=cm.jet,norm=norm)
m.set_array(data)
Complete code:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
# prepare the sphere surface
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
phi = np.linspace(0,2*np.pi, 50)
theta = np.linspace(0, np.pi, 25)
x=np.outer(np.cos(phi), np.sin(theta))
y=np.outer(np.sin(phi), np.sin(theta))
z=np.outer(np.ones(np.size(phi)), np.cos(theta))
# prepare function to plot
PHI=np.outer(phi,np.ones(np.size(theta)))
THETA=np.outer(np.ones(np.size(phi)),theta)
data = PHI/np.pi
# plot
norm = plt.Normalize(vmin=data.min(), vmax=data.max())
surface=ax.plot_surface(x, y, z, cstride=1, rstride=1,
facecolors=cm.jet(norm(data)))
# add colorbar
m = cm.ScalarMappable(cmap=cm.jet,norm=norm)
m.set_array(data)
plt.colorbar(m)
plt.show()
I have three lists xs, ys, zs of data points in Python and I am trying to create a 3d plot with matplotlib using the scatter3d method.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plt.xlim(290)
plt.ylim(301)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.scatter(xs, ys, zs)
plt.savefig('dateiname.png')
plt.close()
The plt.xlim() and plt.ylim() work fine, but I don't find a function to set the borders in z-direction. How can I do so?
Simply use the set_zlim function of the axes object (like you already did with set_zlabel, which also isn't available as plt.zlabel):
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
xs = np.random.random(10)
ys = np.random.random(10)
zs = np.random.random(10)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.scatter(xs, ys, zs)
ax.set_zlim(-10,10)