Search code examples
pythonmatplotlibcolorsarrows

Matplotlib - Separate colours for individual arrows


I am creating a series of xyz arrows and generating a series of pictures. How do make one red, one blue and the other green?

My code used is below.

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

class Arrow3D(FancyArrowPatch):
    def __init__(self, xs, ys, zs, *args, **kwargs):
        FancyArrowPatch.__init__(self, (0,0), (0,0), *args, **kwargs)
        self._verts3d = xs, ys, zs

    def draw(self, renderer):
        xs3d, ys3d, zs3d = self._verts3d
        xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
        self.set_positions((xs[0],ys[0]),(xs[1],ys[1]))
        FancyArrowPatch.draw(self, renderer)

mu_vec1 = np.array([0,0,0])
cov_mat1 = np.array([[1,0,0],[0,1,0],[0,0,1]])
class1_sample = np.random.multivariate_normal(mu_vec1, cov_mat1, 20)

eig_val, eig_vec = np.linalg.eig(cov_mat1)   

fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111, projection='3d', axisbg='black')

for v in eig_vec.T:
    a = Arrow3D([0, v[0]], [0, v[1]], 
                [0, v[2]], mutation_scale=20, lw=5, arrowstyle="-|>", color='red')
    ax.add_artist(a)
ax.axis('off')

plt.show()

Solution

  • First you create a list of your colors colors and then you include the list into the forloop using itertools.izip. This here worked for me:

    import numpy as np
    from matplotlib import pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    from matplotlib.patches import FancyArrowPatch
    from mpl_toolkits.mplot3d import proj3d
    import itertools
    
    class Arrow3D(FancyArrowPatch):
        def __init__(self, xs, ys, zs, *args, **kwargs):
            FancyArrowPatch.__init__(self, (0,0), (0,0), *args, **kwargs)
            self._verts3d = xs, ys, zs
    
        def draw(self, renderer):
            xs3d, ys3d, zs3d = self._verts3d
            xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
            self.set_positions((xs[0],ys[0]),(xs[1],ys[1]))
            FancyArrowPatch.draw(self, renderer)
    
    mu_vec1 = np.array([0,0,0])
    cov_mat1 = np.array([[1,0,0],[0,1,0],[0,0,1]])
    class1_sample = np.random.multivariate_normal(mu_vec1, cov_mat1, 20)
    
    eig_val, eig_vec = np.linalg.eig(cov_mat1)   
    
    fig = plt.figure(figsize=(10,10))
    ax = fig.add_subplot(111, projection='3d', axisbg='black')
    
    colors = ['red','blue','green']
    
    for v,c in itertools.izip(eig_vec.T,colors):
        a = Arrow3D([0, v[0]], [0, v[1]], 
                    [0, v[2]], mutation_scale=20, lw=5, arrowstyle="-|>", color=c)
        ax.add_artist(a)
    ax.axis('off')
    
    plt.show()