Edgecolor3d bug not accepting RGBA array?

Hi All,

I’m creating a three dimensional scatter plot, with large circle markers at each point. I want the edgecolor of each point to correspond to a certain ‘type’ . I have a list (‘TE’), consisting of 0s and 1s which describes the ‘type’ of each point.
Points with a fate=1 should have an edgecolor=black, and fate=0 should have an edgecolor=white.

fig = plt.figure()
ax = fig.gca(projection=‘3d’)
p = ax.scatter(points[:, 0], points[:, 1], points[:, 2], facecolors=[‘lightgrey’] * num_cells, edgecolors=[‘white’] * num_cells, picker=5, s=[150] * num_cells, alpha=1) #first plot with all edgecolours=white

p._edgecolor3d = (np.ones([num_cells, 4]) * np.reshape((1 - TE[:, 0]), [num_cells, 1]))

Variable list: points=x,y,z coords, num_cells=number of points, TE=boolean cell type.

If I run with matplotlib version 3.0.3 or earlier, this works fine and the plot works with the correct edgecolors. If I run with matplotlib version 3.1.1 the following error appears

File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\colors.py”, line 240, in _to_rgba_no_colorcycle
raise ValueError(“Invalid RGBA argument: {!r}”.format(orig_c))
ValueError: Invalid RGBA argument: masked_array(data=[0.8274509803921568, 0.8274509803921568,
0.8274509803921568, 0.5790922892379791],
mask=False,
fill_value=‘?’,
dtype=object)

For now I’m using the old version of Matplotlib, but wondered if I was doing something wrong? Any help would be great!

Thanks :grinning:

Hi @Jess_F,

Replacing your unknown variables and arrays with known examples, I can run the following code without error on my version of Matplotlib (V3.1.2). To my mind, the only thing that is untested here is what TE[:, 0] contains (I’ve substituted it with my x array of random numbers here for simplicity)

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

np.random.seed(19680801)
fig = plt.figure()
ax = fig.gca(projection='3d')
N = 50
num_cells = N
x = np.random.rand(N)
y = np.random.rand(N)
z = np.random.rand(N)
p = ax.scatter(x, y, z,
               facecolors=['lightgrey'] * num_cells,
               edgecolors=['white'] * num_cells,
               picker=5,
               s=[150] * num_cells,
               alpha=1)
p._edgecolor3d = (np.ones([num_cells, 4]) *
                  np.reshape((1-x), [num_cells,1]))
plt.show() 

Does the above code happen to work for you on V3.1.1 or do you still get the same error?

HtH
Laurence

Hi @laurence.molloy,

Thanks for getting back! I tried running your example using version matplotlib 3.1.1- it worked fine. I did notice that TE shape was (num_cells,1), whereas x in your example is shape (num_cells,).

I’ve therefore changed that, but my code still doesn’t work. I forgot to mention that I am using tkinter as well in my scripts.

I have stripped back my previous code such that I simply try the following …

fig = plt.figure()
ax = fig.gca(projection=‘3d’)
p = ax.scatter(points[:, 0], points[:, 1], points[:, 2])
plt.show()

This should therefore use standard defaults for the appearance of the plot. However I get the following error which makes me suspect that its an interaction between tkinter and matplotlib, or I’ve set it up incorrectly?

Exception in Tkinter callback
Traceback (most recent call last):
File “C:\Users\MDEFSJF2\Anaconda3\lib\tkinter_init_.py”, line 1705, in call
return self.func(*args)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\backends_backend_tk.py”, line 259, in resize
self.draw()
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\backends\backend_tkagg.py”, line 9, in draw
super(FigureCanvasTkAgg, self).draw()
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\backends\backend_agg.py”, line 388, in draw
self.figure.draw(self.renderer)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\artist.py”, line 38, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\figure.py”, line 1709, in draw
renderer, self, artists, self.suppressComposite)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\image.py”, line 135, in _draw_list_compositing_images
a.draw(renderer)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\artist.py”, line 38, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py”, line 292, in draw
reverse=True)):
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py”, line 291, in
key=lambda col: col.do_3d_projection(renderer),
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\mpl_toolkits\mplot3d\art3d.py”, line 542, in do_3d_projection
fcs = mcolors.to_rgba_array(fcs, self._alpha)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\colors.py”, line 294, in to_rgba_array
result[i] = to_rgba(cc, alpha)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\colors.py”, line 177, in to_rgba
rgba = to_rgba_no_colorcycle(c, alpha)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\colors.py”, line 240, in to_rgba_no_colorcycle
raise ValueError(“Invalid RGBA argument: {!r}”.format(orig_c))
ValueError: Invalid RGBA argument: masked_array(data=[0.12156862745098039, 0.4666666666666667,
0.7058823529411765, 0.5790922892379791],
mask=False,
fill_value=‘?’,
dtype=object)
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\MDEFSJF2\Anaconda3\lib\tkinter_init
.py", line 1705, in call
return self.func(*args)
File "C:\Users\MDEFSJF2\Anaconda3\lib\tkinter_init
.py", line 749, in callit
func(*args)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\backends_backend_tk.py”, line 338, in idle_draw
self.draw()
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\backends\backend_tkagg.py”, line 9, in draw
super(FigureCanvasTkAgg, self).draw()
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\backends\backend_agg.py”, line 388, in draw
self.figure.draw(self.renderer)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\artist.py”, line 38, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\figure.py”, line 1709, in draw
renderer, self, artists, self.suppressComposite)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\image.py”, line 135, in _draw_list_compositing_images
a.draw(renderer)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\artist.py”, line 38, in draw_wrapper
return draw(artist, renderer, *args, **kwargs)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py”, line 292, in draw
reverse=True)):
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py”, line 291, in
key=lambda col: col.do_3d_projection(renderer),
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\mpl_toolkits\mplot3d\art3d.py”, line 542, in do_3d_projection
fcs = mcolors.to_rgba_array(fcs, self._alpha)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\colors.py”, line 294, in to_rgba_array
result[i] = to_rgba(cc, alpha)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\colors.py”, line 177, in to_rgba
rgba = _to_rgba_no_colorcycle(c, alpha)
File “C:\Users\MDEFSJF2\Anaconda3\lib\site-packages\matplotlib\colors.py”, line 240, in _to_rgba_no_colorcycle
raise ValueError(“Invalid RGBA argument: {!r}”.format(orig_c))
ValueError: Invalid RGBA argument: masked_array(data=[0.12156862745098039, 0.4666666666666667,
0.7058823529411765, 0.5790922892379791],
mask=False,
fill_value=‘?’,
dtype=object)

Thanks again for helping!

Jess

P.s: also tried

p=ax.scatter(points[:, 0], points[:, 1], points[:, 2],s=150,c=‘green’,alpha=0)

but it still gives the value error

ValueError: Invalid RGBA argument: masked_array(data=[0.0, 0.5019607843137255, 0.0, 0.0],
mask=False,
fill_value=‘?’,
dtype=object)

Aha. Okay. So you’re using Tkinter?

Could you provide a minimal piece of code to demonstrate what you’re trying to do here? Perhaps extend my code example with tkinter instructions, one instruction at a time, to see where the error kicks in?

You can swap x, y, z for an ndarray to make it match your code pattern:

fig = plt.figure()
ax = fig.gca(projection='3d')
points = np.ndarray((50,3), buffer=np.random.rand(150), dtype=float)
p = ax.scatter3D(points[:,0], points[:,1], points[:,2])
plt.show()

Yes, I’ve tried to strip down the code as much as possible to show the error. The way I’m using tkinter is to import data from an excel file (col A=cell ID, col B=x, col C=y, col D=z). I just created a mock document, and saved it as an excel 97-2003 workbook.

If I try and create the scatterplot of this data, it throws the same argument. If I use the data generated within the script using np.random.rand (currently commented out) it works.

Hopefully this helps…

import numpy as np
from tkinter import filedialog
from tkinter import Tk
import pandas as pd
import matplotlib
from scipy.spatial import ConvexHull
from scipy.spatial import Delaunay
matplotlib.use(‘TkAgg’)
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

#my code allows the user to identify the excel file for analysis
#use tk to open the filedirectory in a popup window, select the file and open
root = Tk()
root.filename = filedialog.askopenfilename() #open dialogue box to allow use to locate and open data file
print(root.filename)
fname = root.filename
root.destroy()

#now get the data from the excel document, (I have made up a document with values) (my document actually has more info in it)
data = pd.read_excel(fname, header=None) #read in data as an array
data = np.asarray(data)
dshape = np.shape(data)
data = data[1:dshape[0], :] #ignore headings of columns
dshape = np.shape(data)

#unpack data into variables
num_cells = dshape[0] #infer number of cells from size of data table
cell_id = data[:, 0] #cell_ID output from segmentation or allocated during data import
x = data[:, 1] #x coordinate of cell position
y = data[:, 2] #y coordinate of cell position
z = data[:, 3] #z coordinate of cell position

#if i used the following x, y, z the code works?!
#num_cells=40
#x=np.random.rand(num_cells)
#y=np.random.rand(num_cells)
#z=np.random.rand(num_cells)
print(type(x))
print(type(x[1]))

points = np.array([x, y, z]) #combine x,y,z coordinates
points = points.T

fig = plt.figure()
ax = fig.add_subplot(111,projection=‘3d’) #coordinates are in three dimensions so set up axes for 3D

#if I do not try and plot the scater plot, I see the 3D axes and am able to rotate the axes, no error, and close the figure to end the script.
#if i try and create the scatter plot, it through the same error out.
p=ax.scatter(points[:, 0], points[:, 1], points[:, 2],s=150,c=‘green’,alpha=1)#,‘o’,markerfacecolor=‘lightgrey’, markeredgecolor=‘white’,markersize=15)
plt.show()

Thanks again!

Okay.

Perhaps it’s worth hard coding the file read in by pandas for now in order to remove tkinter from the equation.

If the code works then the tkinter stuff will need to be looked at more closely. If it fails, then it’s the data source and / or the import mechanism that needs to be looked at.

Scratch that.

I’ve just run your code and it works just fine for me.

I used LibreOffice (I don’t have MS Excel) saved as Excel 97-2003 with data that looks like this (and no header row):

1 0.630592793587525 0.714466240093695 0.430061126839239
2 0.357289883161154 0.217304823820574 0.265193041564099
3 0.702012530043877 0.454615007287645 0.411879429217291

So… I’m curious about the data you’re using now.

It might also be worth listing versions of all the modules you are using as well. We already know that my matplotlib is a minor version more recent than yours (3.1.2 vs 3.1.1). FYI… my Python is 3.7.3.

Laurence

You’ve got it!!!

I removed the headings from my excel and it now works! What an annoying problem, I’m not exactly sure what the heading was causing to go wrong though. Some way that pandas is importing the data perhaps?

Thank you for all of your help, I wouldn’t have thought the titles of the columns would cause a problem. Interestingly this problem is bypassed somehow in matplotlib3.0.3 ?

Have checked and run on matplotlib 3.1.1 AND 3.1.2 and both work fine. Its definitely something to do with the headings.

Jess :grinning:

Eeeeexcellent! :+1: :+1:

Wait… we could take this one step further…

Your code has this line:

data = pd.read_excel(fname, header=None)

Try changing it to

data = pd.read_excel(fname, header=0)

to identify the first row (row 0) as a header row and it will work just fine for you (tested myself just now to be absolutely certain). :wink:

Happy to be able to bottom this out for you.

Amazing- thanks so much! That gave us quite the run around.

:sweat_smile:

1 Like