Python Plot 3d Vectors

Viewed 15918

Supppse that I wanted to take the following three [x,y,z] coordinates:

[0.799319 -3.477045e-01 0.490093]

[0.852512 9.113778e-16 -0.522708]

[0.296422 9.376042e-01 0.181748]

And plot them as vectors where the vector's start at the origin [0,0,0]. How can I go about doing this? I've been trying to use matplotlib's quiver, but I keep geting the following value error:

ValueError: need at least one array to concatenate

Here's my code (document_matrix_projections are the three coordinates above represented as a matrix):

D1, D2, D3 = zip(*document_matrix_projections)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.quiver(D1)
plt.show()
2 Answers

A good and pretty alternative to using matplolib's quiver() will be to plot using plotly which has the advantage of being interactive. The following function can plot vectors using the Scatter3d() in plotly. Here, the vectors have a big point to mark the direction instead of an arrowhead.

import numpy as np 
import plotly.graph_objs as go

def vector_plot(tvects,is_vect=True,orig=[0,0,0]):
    """Plot vectors using plotly"""

    if is_vect:
        if not hasattr(orig[0],"__iter__"):
            coords = [[orig,np.sum([orig,v],axis=0)] for v in tvects]
        else:
            coords = [[o,np.sum([o,v],axis=0)] for o,v in zip(orig,tvects)]
    else:
        coords = tvects

    data = []
    for i,c in enumerate(coords):
        X1, Y1, Z1 = zip(c[0])
        X2, Y2, Z2 = zip(c[1])
        vector = go.Scatter3d(x = [X1[0],X2[0]],
                              y = [Y1[0],Y2[0]],
                              z = [Z1[0],Z2[0]],
                              marker = dict(size = [0,5],
                                            color = ['blue'],
                                            line=dict(width=5,
                                                      color='DarkSlateGrey')),
                              name = 'Vector'+str(i+1))
        data.append(vector)

    layout = go.Layout(
             margin = dict(l = 4,
                           r = 4,
                           b = 4,
                           t = 4)
                  )
    fig = go.Figure(data=data,layout=layout)
    fig.show()

Plotting can be done simply by,

p0 = [0.799319, -3.477045e-01, 0.490093]
p1 = [0.852512, 9.113778e-16, -0.522708]
p2 = [0.296422, 9.376042e-01, 0.181748]

vector_plot([p0,p1,p2])

The output of the above looks:

The quiver() function needs locations of the arrows as X,Y,Z and U,V,W as the components of the arrow. So the following script can plot your data:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

p0 = [0.799319, -3.477045e-01, 0.490093]
p1 = [0.852512, 9.113778e-16, -0.522708]
p2 = [0.296422, 9.376042e-01, 0.181748]

origin = [0,0,0]
X, Y, Z = zip(origin,origin,origin) 
U, V, W = zip(p0,p1,p2)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.quiver(X,Y,Z,U,V,W,arrow_length_ratio=0.01)
plt.show()

But the results are not pretty. If you would like to use Mayavi, the following works:

import numpy as np
import mayavi.mlab as m

p0 = [0.799319, -3.477045e-01, 0.490093]
p1 = [0.852512, 9.113778e-16, -0.522708]
p2 = [0.296422, 9.376042e-01, 0.181748]

origin = [0,0,0]
X, Y, Z = zip(origin,origin,origin) 
U, V, W = zip(p0,p1,p2)

m.quiver3d(X,Y,Z,U,V,W)
Related