@@ -2746,7 +2746,7 @@ def calc_arrow(uvw, angle=15):
27462746
27472747 quiver3D = quiver
27482748
2749- def voxels (self , filled , color = None , ** kwargs ):
2749+ def voxels (self , filled , ** kwargs ):
27502750 """
27512751 Plot a set of filled voxels
27522752
@@ -2762,13 +2762,13 @@ def voxels(self, filled, color=None, **kwargs):
27622762 A 3d array of values, with truthy values indicating which voxels
27632763 to fill
27642764
2765- color : array_like
2766- The color to draw the faces of the voxels. This parameter can be:
2765+ facecolors, edgecolors : array_like
2766+ The color to draw the faces and edges of the voxels. This parameter
2767+ can be:
27672768
27682769 - A single color value, to color all voxels the same color. This
27692770 can be either a string, or a 1D rgb/rgba array
2770- - ``None``, indicating the above with the next color in the
2771- sequence
2771+ - ``None``, indicating to use the default
27722772 - A 3D ndarray of color names, with each item the color for the
27732773 corresponding voxel. The size must match the voxels.
27742774 - A 4D ndarray of rgb/rgba data, with the components along the
@@ -2796,21 +2796,29 @@ def voxels(self, filled, color=None, **kwargs):
27962796 if filled .ndim != 3 :
27972797 raise ValueError ("Argument filled must be 3-dimensional" )
27982798
2799- # handle the color argument
2800- if color is None :
2801- color = self ._get_patches_for_fill .get_next_color ()
2802- if np .ndim (color ) in (0 , 1 ):
2803- # single color, like "red" or [1, 0, 0]
2804- color = broadcast_to (color , filled .shape + np .shape (color ))
2805- elif np .ndim (color ) in (3 , 4 ):
2806- # 3D array of strings, or 4D array with last axis rgb
2807- if np .shape (color )[:3 ] != filled .shape :
2808- raise ValueError (
2809- "When multidimensional, color must match the shape of "
2810- "filled" )
2811- else :
2812- raise ValueError ("Invalid color argument" )
2799+ def _broadcast_color_arg (color , name ):
2800+ if np .ndim (color ) in (0 , 1 ):
2801+ # single color, like "red" or [1, 0, 0]
2802+ return broadcast_to (color , filled .shape + np .shape (color ))
2803+ elif np .ndim (color ) in (3 , 4 ):
2804+ # 3D array of strings, or 4D array with last axis rgb
2805+ if np .shape (color )[:3 ] != filled .shape :
2806+ raise ValueError (
2807+ "When multidimensional, {} must match the shape of "
2808+ "filled" .format (name ))
2809+ return color
2810+ else :
2811+ raise ValueError ("Invalid {} argument" .format (name ))
2812+
2813+ # intercept the facecolors, handling defaults and broacasting
2814+ facecolors = kwargs .pop ('facecolors' , None )
2815+ if facecolors is None :
2816+ facecolors = self ._get_patches_for_fill .get_next_color ()
2817+ facecolors = _broadcast_color_arg (facecolors , 'facecolors' )
28132818
2819+ # broadcast but no default on edgecolors
2820+ edgecolors = kwargs .pop ('edgecolors' , None )
2821+ edgecolors = _broadcast_color_arg (edgecolors , 'edgecolors' )
28142822
28152823 # always scale to the full array, even if the data is only in the center
28162824 self .auto_scale_xyz (
@@ -2884,7 +2892,8 @@ def permutation_matrices(n):
28842892 polygons = {}
28852893 for coord , faces in voxel_faces .items ():
28862894 poly = art3d .Poly3DCollection (faces ,
2887- facecolors = color [coord ],
2895+ facecolors = facecolors [coord ],
2896+ edgecolors = edgecolors [coord ],
28882897 ** kwargs
28892898 )
28902899 self .add_collection3d (poly )
0 commit comments