First off, I'm trying to plot spherical harmonics in matplotlib as they are seen here in mayavi: http://docs.enthought.com/mayavi/mayavi/auto/example_spherical_harmonics.html
Here is where I'm at:
import matplotlib.pyplot as plt
from matplotlib import cm, colors
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy import special
# Create a sphere
r = 3
pi = np.pi
cos = np.cos
sin = np.sin
phi, theta = np.mgrid[0:pi:50j, 0:2*pi:50j]
x = r * sin(phi) * cos(theta)
y = r * sin(phi) * sin(theta)
z = r * cos(phi)
colorfunction=special.sph_harm(3,4,theta,phi).real
norm=colors.Normalize(vmin = np.min(colorfunction), vmax = np.max(colorfunction), clip = False)
print colorfunction
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z)
ax.plot_surface(
x, y, z, rstride=1, cstride=1, norm=norm, cmap=cm.jet, facecolors=cm.jet(colorfunction))
plt.show()
The idea is to use colorfunction
to colour the surface of the sphere according to the spherical harmonic. However, the output of this function is an array with negative numbers. What I need to do is 'normalize' this array so it behaves nicely with matplotlib's colormap. However, unlike the answer here, Color matplotlib plot_surface command with surface gradient , where the answer simply preforms a sloppy normalize by dividing by the largest element, I have negative elements so that just won't work. I'd ideally like to use matplotlib.colors.Normalize
but it just isn't working on facecolors.
I know that the norm is applying to the cmap=cm.jet
, because if I remove facecolors
argument entirely I get a new colormap that behaves according to my norm
function.
This is the crux of my issue, I cannot get my normalized colormap to apply to my facecolors. Any ideas?
This is the figure the above code currently generates. As you can see the negative values are cut-off entirely and the information is lost because the colormaps range is much larger than the actual values (so everything just looks blue).
Maybe this is too trivial, but:
ax.plot_surface(x, y, z, rstride=1, cstride=1, facecolors=cm.jet(norm(colorfunction)))
This normalizes colorfunction
. Also, it is sufficient to define the normalization function by:
norm = colors.Normalize()
This will automatically scale the input between 0..1.
The result:
It seems that cmap
and norm
keywords apply to the case where one uses Z data to color the surface, so they are not useful here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With