Andreas Schuldei
Andreas Schuldei

Reputation: 405

How to plot with matplotlib a 3d quiver plot with color gradient for length? gives error "ValueError: object too deep for desired array"

I want to indicate the length of the quivers (are the arrows calls quivers?) by color coding them. That is no issue with 2d quiver plots. Here it is done. With 3d projection it fails hard. This code reproduces the issue.

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')

# 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.8, 1, 0.8))

# 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 = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) *
     np.sin(np.pi * z))
M = np.sqrt(u**2 + v**2 + w**2)
ax.quiver(x, y, z, u, v, w, M)

plt.show()

this produces a long traceback within a couple of matplotlib files and ends with

ValueError: object too deep for desired array

How can I avoid this issue and color-code my quivers?

Upvotes: 2

Views: 1123

Answers (1)

Andreas Schuldei
Andreas Schuldei

Reputation: 405

As @venky__ pointed out, there has been discussion about similar things before. I put that into a subroutine and adjusted for arrow length, even taking into account complex numbers in my arrays. example graph

def plot_3d_quiver(x, y, z, u, v, w):
    c = np.sqrt(np.abs(v) ** 2 + np.abs(u) ** 2 + np.abs(w) ** 2)
    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 = plt.cm.jet(c)

    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.quiver(x, y, z, u, v, w, colors=c, length=0.1)
    plt.show()

Upvotes: 1

Related Questions