This is my first question and I hope I can describe my issue properly.
I tried to write down a minimal example. My goal is to get a nice plot of a vector field in the xy plane (so just one layer, but a 3d view) where the colors of my arrows should be completely red (blue) if they are pointing completely in the positive (negative) z-direction and gray if they are located in the xy plane. (Slightly red resp. red if they have some positive resp. negative z component etc - so I thought about a 'coolwarm' colormap. But I do not really know how to tho this. I tried to solve my problem with this question and the answers Adding colors to a 3d quiver plot in matplotlib and with the way I am adding my color bars to pcolormesh-plots where it is working fine. , but I didn't really manage to do it properly, as you can see here: plot obtained from my code
I do not really understand some of the code they used there and it would be nice if someone could help me with that :)
I do not understand what this part does q.set_array(np.linspace(-1,1,3))
and why I need q.set_edgecolor(c)
and q.set_facecolor(c)
.
Besides I am
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import BoundaryNorm
from matplotlib.ticker import MaxNLocator
# Make the grid
x, y, z = np.meshgrid(np.arange(-0.8, 1, 0.2),
np.arange(-0.8, 1, 0.2),
np.arange(0.0, 0.6, 0.5))
# Make the direction data for the arrows
u = np.sin(np.pi * x) * np.cos(np.pi * y) * np.cos(np.pi * z)
v = -np.cos(np.pi * x) * np.sin(np.pi * y) * np.cos(np.pi * z)
w = 0.2 + np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) * np.sin(np.pi * z)
#define colorbar like I usually do it for 2d density plot etc where it works
cmap = 'coolwarm'
cm = plt.get_cmap(cmap)
plot_min = -1.
plot_max = 1.
levels = MaxNLocator(nbins=100).tick_values(plot_min, plot_max)
norm = BoundaryNorm(levels, ncolors=cm.N, clip=True)
# Color by z-component of vectors (u,v,w) angle
c = w
# Flatten and normalize
c = (c.ravel() - c.min()) / c.ptp()
# Repeat for each body line and two head lines
c = np.concatenate((c, np.repeat(c, 2)))
# Colormap
c = getattr(plt.cm, cmap)(c)
fig = plt.figure(figsize=(10,7))
ax = fig.gca(projection='3d')
q = ax.quiver(x, y, z, u, v, w, colors=c, cmap = cmap, length=0.1, normalize=norm)
q.set_array(np.linspace(-1,1,3))
cbar = fig.colorbar(q, ticks=[-1, 0, 1], fraction=0.015)
cbar.ax.set_yticklabels(['-1', '0', '1'])
cbar.ax.tick_params(labelsize=15)
q.set_edgecolor(c)
q.set_facecolor(c)
#ax.set_zlim(-0.4, 0.4)
ax.view_init(azim=90, elev=20)
ax.grid(False)
plt.axis('off')
plt.show()
if this would work, it would be super cool! Is there a way to make the arrows look nicer? It would be perfect if the arrows could look like the ones in Mathematica-plots like this: example from Mathematica
Thank you a lot in advance!