Reputation: 11
I try to visualize the classification of points in 3D. When I give the classification to the 'c' parameter in the scatter function the result is as expected. But When I give the exact same classifications to the 'alpha' parameter, it seems to become noise.
Here is an example with a sin wave. (I scaled the alpha parameter to reveal that it's only noise)
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
mpl.rcParams['figure.facecolor'] = 'white'
# Orientation sampling
angles = range(0,360,10)
euler = np.array([[[[x,y,z] for z in angles] for y in angles] for x in angles])
euler = euler.reshape((-1,3))
# Make some classification
cls = np.abs(np.sin(euler.mean(1)))
print("min:", cls.min())
print("max:", cls.max())
print("mean:", cls.mean())
# visualize
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.scatter(euler[:,0],euler[:,1],euler[:,2], c=cls, s=5, alpha=1.0, cmap='viridis')
plt.show()
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.scatter(euler[:,0],euler[:,1],euler[:,2], c='b', s=5, alpha=cls**10/10)
plt.show()
Output:
min: 0.0
max: 0.9999727218865074
mean: 0.6366588835775282
c=cls
shows a nice sin wave:
alpha=cls**10/10
shows points with random alpha value:
I expected to see the same pattern when assigning the classification to the alpha value.
I currently work around the issue by using the point size to hide the lower classified points.
Upvotes: 0
Views: 76
Reputation: 80279
It is unclear what's going on. Normally, since matplotlib 3.4, alpha as an array is supported for a scatter plot, both 2D and 3D. Unlike the c
parameter, which automatically gets transformed to the range 0 - 1, the alpha parameter should allready be in the correct range.
Nevertheless, you can get the same effect using a colormap with alpha values.
Here is an example:
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap, to_rgba
import numpy as np
mpl.rcParams['figure.facecolor'] = 'white'
# Orientation sampling
angles = range(0, 360, 10)
euler = np.array([[[[x, y, z] for z in angles] for y in angles] for x in angles])
euler = euler.reshape((-1, 3))
# Make some classification
cls = np.abs(np.sin(euler.mean(1)))
# visualize
alpha_cmap = LinearSegmentedColormap.from_list('', ['b', to_rgba('b', alpha=0)])
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.scatter(euler[:, 0], euler[:, 1], euler[:, 2], c=cls, s=5, cmap=alpha_cmap)
plt.show()
As the c
parameter is used here, it gets automatically expanded to the range 0 to 1. You can experiment with vmin
and vmax
to change the range. Or you can use a different lower alpha when creating the
LinearSegmentedColormap
(optionally reversing the order of the colors).
Upvotes: 0