I want to plot the intensity over a sphere using plot_surface. The problem is, that it is not possible for me to normalize the color and to set the colobar correctly. All solutions I found in the internet do not work for me.
The code I wrote uses the distance of the surface of the sphere to a specific vector d as a kind of intensity. Here is my code:
def FieldTranslation(N = 250, d = [-0.001, 0, 0], R = 1):
d = np.array(d)
t = np.linspace(0, np.pi, N)
p = np.linspace(0, 2*np.pi, N)
t, p = np.meshgrid(t, p)
X = R * np.sin(t) * np.cos(p)
Y = R * np.sin(t) * np.sin(p)
Z = R * np.cos(t)
C = np.sqrt((X - d[0])**2 + (Y - d[1])**2 + (Z - d[2])**2)
CMax = np.maximum(C[..., 0], C[..., 1], C[..., 2])
C = C / CMax
if np.sum(d) == 0:
print('round')
C = np.round(C, 1)
fig, ax = plt.subplots(subplot_kw={'projection': '3d'})
scamap = plt.cm.ScalarMappable(cmap='inferno')
fcolors = scamap.to_rgba(C)
minn = -1 # fcolors.min()
maxx = 1 # fcolors.max()
s = ax.plot_surface(X, Y, Z, facecolors=fcolors, cmap='inferno', vmin = minn, vmax = maxx)
fig.colorbar(s)
plt.show()
This code creates an image like:
Here, the colobar does not fit to the colors of the plot and also, there should only be slide variations over the surface (when looking at the numbers in C).
If I set d = [0, 0, 0], the whole sphere turns black but the C values are all 1.
I already checked the forums and copied code from others, but nothing worked.
The colorbar drawn from s
is drawn from the Z
component.
You should give fig.colorbar
the custom scamap
you created:
X, Y, Z, C = field_translation()
fig = plt.figure(figsize=(12, 6))
ax_hist = fig.add_subplot(1, 2, 1)
ax_surf = fig.add_subplot(1, 2, 2, projection="3d")
ax_hist.hist(C.flat, bins=100)
# vmin, vmax = 0.6, 1.0
vmin, vmax = C.min(), C.max()
norm = mpl.colors.Normalize(vmin, vmax)
scamap = plt.cm.ScalarMappable(cmap="inferno", norm=norm)
fcolors = scamap.to_rgba(C)
ax_surf.plot_surface(X, Y, Z, facecolors=fcolors, cmap="inferno")
fig.colorbar(scamap, ax=ax_surf)
fig.tight_layout()
plt.show()