1

I have a 3-d plot, but 4 of my 16 data points have invalid data from one of components (ie a vector has good x and y data but bad z data). I could just omit the points entirely, but then I'm getting rid of good data (in the x and y directions). Ideally, I would like to be able to change the color of the ones missing data as a kind of flag, so that they are still plotted but I can tell which ones are missing the data.

I have have very little experience with color maps, especially in 3-d. I've tried adapting solutions from: (python) plot 3d surface with colormap as 4th dimension, function of x,y,z Create own colormap using matplotlib and plot color scale and this one which seems the most helpful: Adding colors to a 3d quiver plot in matplotlib But I just want all of them to be the same colors except for very specific data points and I'm not sure how to index the color map.

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

def main():

    data = [[  1.52940323e-06,   3.30263460e-07,   1.23333738e-02],
            [ 0.00062357, -0.00061659, -0.21386033],
            [-0.00028384,  0.00088403, -0.21165629],
            [ 0.00225299,  0.00180132, -0.1964095 ],
            [-0.00066298,  0.00271399, -0.23091235],
            [ 0.00054687, -0.00063866, -0.24299   ],
            [ 0.00170783, -0.00140304, -0.09094558],
            [-0.00378669, -0.00592137, -0.07358853],
            [  5.84581114e-07,  -3.58723162e-07,  -3.08931350e-02],
            [ 0.0003522 , -0.00067592, -0.23933634],
            [ -5.84077540e-07,   2.08945622e-07,  -4.31579608e-02],
            [-0.00196888,  0.00261409, -0.28115362],
            [ -1.65606166e-04,   1.89755530e-01,  -1.49510581e-02],
            [-0.00048166,  0.00095946, -0.26929835],
            [  8.26054997e-04,  -7.75840354e-05,  -3.05118605e-01],
            [ 0.0018271 ,  0.00078126, -0.18526635]]


    fig = plt.figure()
    ax = Axes3D(fig)



    x = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    y = [-0.002, -0.002, -0.002, -0.002, -0.001, -0.001, -0.001, -0.001, 
        0.001, 0.001, 0.001, 0.001, 0.002, 0.002, 0.002, 0.002]
    z = [-0.0022500000000000003, -0.00075, 0.00075, 0.0022500000000000003, 
         -0.0022500000000000003, -0.00075, 0.00075, 0.0022500000000000003, 
         -0.0022500000000000003, -0.00075, 0.00075, 0.0022500000000000003, 
         -0.0022500000000000003, -0.00075, 0.00075, 0.0022500000000000003]


    # data[0]= [0]*3
    # data[8]= [0]*3
    # data[10]= [0]*3
    # data[12]= [0]*3
    u = [data[i][0] for i in range(len(data))]
    v = [data[i][1] for i in range(len(data))]
    w = [data[i][2] for i in range(len(data))]
    cdict = {'green': np.array(len(u)), 'green': np.array(len(u)), 
             'green':np.array(len(u))}
    cdict = {'red': [0],'red': [0],'red': [0]}

    ax.quiver(x,y,z,u,v,w, length=0.001, normalize=True, colors=cdict)

    ax.set_xlabel("X direction")
    ax.set_ylabel("Y direction")
    ax.set_zlabel("Z direction")
    plt.axis('equal')
    plt.show()


if __name__ == '__main__':
    main()

This plots everything as red, instead of everything green and only certain vectors red. I'm not really sure what I'm doing, and any help would be much appreciated! (Also yes, I am stuck in the stone age with python 2)

Edit: Inspired by the answer below, I created a mask for 'bad' channels, then created two plots, one with the good channels in blue, and one with the bad channels in red.

dead_chans = [1, 0,0,0,0,0,0,0,1,0,1,0,1,0,0,0]
good_u = np.ma.masked_array(u,dead_chans)
good_v = np.ma.masked_array(v, dead_chans)
good_w = np.ma.masked_array(w, dead_chans)

dead_u = np.ma.masked_array(u, np.logical_not(dead_chans))
dead_v = np.ma.masked_array(v, np.logical_not(dead_chans))
dead_w = np.ma.masked_array(w, np.logical_not(dead_chans))

ax.quiver(x,y,z,good_u,good_v,good_w, length=0.01, normalize=True, color= 
'b')
ax.quiver(x,y,z,dead_u,dead_v,dead_w, length=0.01, normalize=True, color = 
'r')
plt.show()
whynot_77
  • 13
  • 5
  • `cdict = {'red': [0],'red': [0],'red': [0]}` overwrites the previous dictionary with green colors. Also, you can't have multiple same keys. No point specifying `'green` three times. It is currently unclear what you want. " 4 of my 16 data points are missing data "... Where? I don't see the missing data. Also, if the z-value is missing how do you plan to plot it in a 3d system? – Sheldore Jun 06 '19 at 16:06
  • @Sheldore right, I am not sure how to index the color map without re-writing over the previous dictionary. Also a clarification about the missing data, I'm reading in data off of a scope that has a few channels that are dead, so I am essentially plotting noise instead of actual data, I just updated the question to be (hopefully) clearer! – whynot_77 Jun 06 '19 at 16:15

1 Answers1

0

You can set the z values to a np.nan instead of ignoring them altogether. Then you could use colormap.set_bad() to change the color of your nan values to something specific.

Hope that helps

https://matplotlib.org/api/_as_gen/matplotlib.colors.Colormap.html

Edit

with help from this post: How can I plot NaN values as a special color with imshow in matplotlib?

Here's an example.

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

#Set the defualt cmap for mpl
mpl.rcParams['image.cmap'] = 'Blues'
cmap = mpl.cm.get_cmap()
cmap.set_bad(color='Red')

#Generate some data with np.nan values
x = np.arange(1,13,1)
y = np.arange(1,13,1)
vals = np.zeros([12,12])

for i in range(12):
    for j in range(12):
        if (i+j)%7==0:
            vals[i,j] = np.nan
        else:
            vals[i,j] = i*j

plt.pcolormesh(x,y,arr)

This code returns the following plot:

plot with nans

mneedham
  • 45
  • 4
  • Ok, I tried it an it seems like progress, but now because the data is masked it's not showing up... For reference I set w[0] = nan , then w = np.ma.masked_invalid(w), and the used set_bad and plotted it again using a cmap – whynot_77 Jun 06 '19 at 16:34